Skip to content

Commit

Permalink
feature: add BYOID support for OCI artifacts and Helm charts (GoogleC…
Browse files Browse the repository at this point in the history
…ontainerTools#1121)

This commit integrates BYOID support into Config Sync by supporting a
new auth type for OCI and Helm: `k8sserviceaccount`. It requires GKE or
Fleet Workload Identity to be enabled. The KSA along with WI will be
exchanged to a federated token which can be used to authenticate to
Ubermint-enabled GCP services directly.
  • Loading branch information
nan-yu authored and tiffanny29631 committed Feb 5, 2024
1 parent 2bed09b commit 93c7a36
Show file tree
Hide file tree
Showing 27 changed files with 756 additions and 242 deletions.
4 changes: 2 additions & 2 deletions cmd/helm-sync/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,8 @@ var (
flIncludeCRDs = flag.String("include-crds", os.Getenv(reconcilermanager.HelmIncludeCRDs),
"include CRDs in the helm rendering output")
flAuth = flag.String("auth", util.EnvString(reconcilermanager.HelmAuthType, string(configsync.AuthNone)),
fmt.Sprintf("the authentication type for access to the Helm repository. Must be one of %s, %s, %s or %s. Defaults to %s",
configsync.AuthGCPServiceAccount, configsync.AuthToken, configsync.AuthGCENode, configsync.AuthNone, configsync.AuthNone))
fmt.Sprintf("the authentication type for access to the Helm repository. Must be one of %s, %s, %s, %s or %s. Defaults to %s",
configsync.AuthGCPServiceAccount, configsync.AuthK8sServiceAccount, configsync.AuthToken, configsync.AuthGCENode, configsync.AuthNone, configsync.AuthNone))
flReleaseName = flag.String("release-name", os.Getenv(reconcilermanager.HelmReleaseName),
"the name of helm release")
flNamespace = flag.String("namespace", os.Getenv(reconcilermanager.HelmReleaseNamespace),
Expand Down
6 changes: 3 additions & 3 deletions cmd/oci-sync/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,8 @@ import (
var flImage = flag.String("image", util.EnvString(reconcilermanager.OciSyncImage, ""),
"the OCI image repository for the package")
var flAuth = flag.String("auth", util.EnvString(reconcilermanager.OciSyncAuth, string(configsync.AuthNone)),
fmt.Sprintf("the authentication type for access to the OCI package. Must be one of %s, %s, or %s. Defaults to %s",
configsync.AuthGCPServiceAccount, configsync.AuthGCENode, configsync.AuthNone, configsync.AuthNone))
fmt.Sprintf("the authentication type for access to the OCI package. Must be one of %s, %s, %s, or %s. Defaults to %s",
configsync.AuthGCPServiceAccount, configsync.AuthK8sServiceAccount, configsync.AuthGCENode, configsync.AuthNone, configsync.AuthNone))
var flRoot = flag.String("root", util.EnvString("OCI_SYNC_ROOT", util.EnvString("HOME", "")+"/oci"),
"the root directory for oci-sync operations, under which --dest will be created")
var flDest = flag.String("dest", util.EnvString("OCI_SYNC_DEST", ""),
Expand Down Expand Up @@ -86,7 +86,7 @@ func main() {
switch configsync.AuthType(*flAuth) {
case configsync.AuthNone:
auth = authn.Anonymous
case configsync.AuthGCPServiceAccount, configsync.AuthGCENode:
case configsync.AuthGCPServiceAccount, configsync.AuthK8sServiceAccount, configsync.AuthGCENode:
a, err := google.NewEnvAuthenticator()
if err != nil {
utillog.HandleError(log, true, "ERROR: failed to get the authentication with type %q: %v", *flAuth, err)
Expand Down
2 changes: 1 addition & 1 deletion e2e/nomostest/nt.go
Original file line number Diff line number Diff line change
Expand Up @@ -971,7 +971,7 @@ func gitCommitFromSpec(nt *NT, gitSpec *v1beta1.Git) (string, error) {
pattern = "HEAD"
}
var args []string
if strings.Contains(gitSpec.Repo, "https://source.developers.google.com") {
if strings.Contains(gitSpec.Repo, testing.CSRHost) {
cloneDir, err := cloneCloudSourceRepo(nt, gitSpec.Repo)
if err != nil {
return "", err
Expand Down
15 changes: 12 additions & 3 deletions e2e/nomostest/testing/env.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,19 @@
package testing

const (
// ARHost is the host address of the Artifact Registry
ARHost = "us-docker.pkg.dev"

// GCRHost is the host address of the Container Registry
GCRHost = "gcr.io"

// CSRHost is the host address of the Cloud Source Repositories
CSRHost = "https://source.developers.google.com"

// TestInfraContainerRegistry is the Config Sync test-infra registry hosted on GCR
TestInfraContainerRegistry = "gcr.io/kpt-config-sync-ci-artifacts"
TestInfraContainerRegistry = GCRHost + "/kpt-config-sync-ci-artifacts"
// TestInfraArtifactRegistry is the Config Sync test-infra registry hosted on GAR
TestInfraArtifactRegistry = "us-docker.pkg.dev/kpt-config-sync-ci-artifacts/test-infra"
TestInfraArtifactRegistry = ARHost + "/kpt-config-sync-ci-artifacts/test-infra"
// ConfigSyncTestPublicRegistry is the Config Sync config-sync-test-public registry hosted on GAR
ConfigSyncTestPublicRegistry = "us-docker.pkg.dev/kpt-config-sync-ci-artifacts/config-sync-test-public"
ConfigSyncTestPublicRegistry = ARHost + "/kpt-config-sync-ci-artifacts/config-sync-test-public"
)
5 changes: 3 additions & 2 deletions e2e/nomostest/testutils/fleet_membership.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import (
corev1 "k8s.io/api/core/v1"
"kpt.dev/configsync/e2e/nomostest"
"kpt.dev/configsync/pkg/api/configmanagement"
"kpt.dev/configsync/pkg/api/configsync"
hubv1 "kpt.dev/configsync/pkg/api/hub/v1"
"kpt.dev/configsync/pkg/metadata"
"kpt.dev/configsync/pkg/reconcilermanager"
Expand Down Expand Up @@ -122,7 +123,7 @@ func ClearMembershipInfo(nt *nomostest.NT, fleetMembership, fleetProject, gkeURI

// ReconcilerPodHasFWICredsAnnotation checks whether the reconciler Pod has the
// FWI credentials annotation.
func ReconcilerPodHasFWICredsAnnotation(nt *nomostest.NT, reconcilerName, gsaEmail string) error {
func ReconcilerPodHasFWICredsAnnotation(nt *nomostest.NT, reconcilerName, gsaEmail string, auth configsync.AuthType) error {
var podList = &corev1.PodList{}
if err := nt.KubeClient.List(podList, client.InNamespace(configmanagement.ControllerNamespace), client.MatchingLabels{metadata.ReconcilerLabel: reconcilerName}); err != nil {
return err
Expand All @@ -140,7 +141,7 @@ func ReconcilerPodHasFWICredsAnnotation(nt *nomostest.NT, reconcilerName, gsaEma
if err := nt.KubeClient.Get("membership", "", membership); err != nil {
return err
}
expectedCreds, err := controllers.BuildFWICredsContent(membership.Spec.WorkloadIdentityPool, membership.Spec.IdentityProvider, gsaEmail)
expectedCreds, err := controllers.BuildFWICredsContent(membership.Spec.WorkloadIdentityPool, membership.Spec.IdentityProvider, gsaEmail, auth)
if err != nil {
return err
}
Expand Down
2 changes: 1 addition & 1 deletion e2e/testcases/csr_auth_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ const (
// references resources for tenant-a, tenant-b, and tenant-c.
// Each tenant includes a NetworkPolicy, a Role and a RoleBinding.
func csrRepo() string {
return fmt.Sprintf("https://source.developers.google.com/p/%s/r/kustomize-components", *e2e.GCPProject)
return fmt.Sprintf("%s/p/%s/r/kustomize-components", nomostesting.CSRHost, *e2e.GCPProject)
}

func gsaCSRReaderEmail() string {
Expand Down
3 changes: 2 additions & 1 deletion e2e/testcases/kcc_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,8 @@ func TestKCCResourcesOnCSR(t *testing.T) {

rs := fake.RootSyncObjectV1Beta1(configsync.RootSyncName)
nt.T.Log("sync to the kcc resources from a CSR repo")
nt.MustMergePatch(rs, fmt.Sprintf(`{"spec": {"git": {"dir": "kcc", "branch": "main", "repo": "https://source.developers.google.com/p/%s/r/configsync-kcc", "auth": "gcpserviceaccount","gcpServiceAccountEmail": "e2e-test-csr-reader@%s.iam.gserviceaccount.com", "secretRef": {"name": ""}}, "sourceFormat": "unstructured"}}`, *e2e.GCPProject, *e2e.GCPProject))
nt.MustMergePatch(rs, fmt.Sprintf(`{"spec": {"git": {"dir": "kcc", "branch": "main", "repo": "%s/p/%s/r/configsync-kcc", "auth": "gcpserviceaccount","gcpServiceAccountEmail": "e2e-test-csr-reader@%s.iam.gserviceaccount.com", "secretRef": {"name": ""}}, "sourceFormat": "unstructured"}}`,
nomostesting.CSRHost, *e2e.GCPProject, *e2e.GCPProject))

err := nt.WatchForAllSyncs(
nomostest.WithRootSha1Func(nomostest.RemoteRootRepoSha1Fn),
Expand Down
4 changes: 2 additions & 2 deletions e2e/testcases/oci_sync_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,12 +63,12 @@ const (
// privateGCRImage pulls the private OCI image by tag
// The test environment GCR is assumed to be private.
func privateGCRImage() string {
return fmt.Sprintf("gcr.io/%s/config-sync-test/kustomize-components:v1", *e2e.GCPProject)
return fmt.Sprintf("%s/%s/config-sync-test/kustomize-components:v1", nomostesting.GCRHost, *e2e.GCPProject)
}

// privateARImage() pulls the private OCI image by tag
func privateARImage() string {
return fmt.Sprintf("us-docker.pkg.dev/%s/config-sync-test-private/kustomize-components:v1", *e2e.GCPProject)
return fmt.Sprintf("%s/%s/config-sync-test-private/kustomize-components:v1", nomostesting.ARHost, *e2e.GCPProject)
}

func gsaARReaderEmail() string {
Expand Down
Loading

0 comments on commit 93c7a36

Please sign in to comment.