@@ -111,6 +111,74 @@ func TestPublicOCI(t *testing.T) {
111111 kustomizecomponents .ValidateAllTenants (nt , string (declared .RootScope ), "../base" , tenant )
112112}
113113
114+ // TestOCIARTokenAuth verifies Config Sync can pull Helm chart from private
115+ // Artifact Registry with Token auth type.
116+ //
117+ // Test pre-requisites:
118+ // - Google service account
119+ // `e2e-test-ar-reader@${GCP_PROJECT}.iam.gserviceaccount.com` is created
120+ // with `roles/artifactregistry.reader` for accessing images in Artifact
121+ // Registry.
122+ // - A JSON key file is generated for this service account and stored in
123+ // Secret Manager
124+ //
125+ // Test handles service account key rotation.
126+ func TestOCIARTokenAuth (t * testing.T ) {
127+ nt := nomostest .New (t ,
128+ nomostesting .SyncSourceOCI ,
129+ ntopts .SyncWithGitSource (nomostest .DefaultRootSyncID , ntopts .Unstructured ),
130+ ntopts .RequireGKE (t ),
131+ ntopts .RequireOCIArtifactRegistry (t ),
132+ )
133+ rootSyncID := nomostest .DefaultRootSyncID
134+ rootSyncKey := rootSyncID .ObjectKey
135+
136+ gsaKeySecretID := "config-sync-ci-ar-key"
137+ gsaEmail := registryproviders .ArtifactRegistryReaderEmail ()
138+ gsaName := registryproviders .ArtifactRegistryReaderName
139+ gsaKeyFilePath , err := fetchServiceAccountKeyFile (nt , * e2e .GCPProject , gsaKeySecretID , gsaEmail , gsaName )
140+ if err != nil {
141+ nt .T .Fatal (err )
142+ }
143+
144+ nt .T .Log ("Creating kubernetes secret for authentication" )
145+ _ , err = nt .Shell .Kubectl ("create" , "secret" , "generic" , "foo" ,
146+ "--namespace" , configsync .ControllerNamespace ,
147+ "--from-literal" , "username=_json_key" ,
148+ "--from-file" , fmt .Sprintf ("password=%s" , gsaKeyFilePath ))
149+ if err != nil {
150+ nt .T .Fatalf ("failed to create secret, err: %v" , err )
151+ }
152+ nt .T .Cleanup (func () {
153+ nt .MustKubectl ("delete" , "secret" , "foo" , "-n" , configsync .ControllerNamespace , "--ignore-not-found" )
154+ })
155+
156+ // OCI image will only contain the bookinfo-admin role
157+ bookinfoRole := k8sobjects .RoleObject (core .Name ("bookinfo-admin" ))
158+ image , err := nt .BuildAndPushOCIImage (rootSyncKey , registryproviders .ImageInputObjects (nt .Scheme , bookinfoRole ))
159+ if err != nil {
160+ nt .T .Fatalf ("failed to push oci image: %v" , err )
161+ }
162+
163+ nt .T .Log ("Update RootSync to sync from a private Artifact Registry" )
164+ rs := nt .RootSyncObjectOCI (configsync .RootSyncName , image .OCIImageID ().WithoutDigest (), "" , image .Digest )
165+ rs .Spec .Oci = & v1beta1.Oci {
166+ Image : rs .Spec .Oci .Image ,
167+ Auth : configsync .AuthToken ,
168+ SecretRef : & v1beta1.SecretReference {
169+ Name : "foo" ,
170+ },
171+ Period : metav1.Duration {Duration : 5 * time .Second },
172+ }
173+ nt .Must (nt .KubeClient .Apply (rs ))
174+
175+ nt .T .Log ("Wait for RootSync to sync from an oci image chart" )
176+ nt .Must (nt .WatchForAllSyncs ())
177+
178+ nt .T .Log ("Validate Role from OCI image exists" )
179+ nt .Must (nt .Validate (bookinfoRole .Name , "default" , & rbacv1.Role {}))
180+ }
181+
114182func TestSwitchFromGitToOciCentralized (t * testing.T ) {
115183 namespace := testNs
116184 rootSyncID := nomostest .DefaultRootSyncID
0 commit comments