@@ -22,6 +22,7 @@ import (
2222 "fmt"
2323 "net/url"
2424 "os"
25+ "strings"
2526 "time"
2627
2728 helmgetter "helm.sh/helm/v3/pkg/getter"
@@ -41,10 +42,13 @@ import (
4142 "sigs.k8s.io/controller-runtime/pkg/predicate"
4243
4344 "github.com/fluxcd/pkg/apis/meta"
45+ "github.com/fluxcd/pkg/oci"
46+ "github.com/fluxcd/pkg/oci/auth/login"
4447 "github.com/fluxcd/pkg/runtime/conditions"
4548 helper "github.com/fluxcd/pkg/runtime/controller"
4649 "github.com/fluxcd/pkg/runtime/patch"
4750 "github.com/fluxcd/pkg/runtime/predicates"
51+ "github.com/google/go-containerregistry/pkg/name"
4852
4953 "github.com/fluxcd/source-controller/api/v1beta2"
5054 sourcev1 "github.com/fluxcd/source-controller/api/v1beta2"
@@ -204,6 +208,9 @@ func (r *HelmRepositoryOCIReconciler) Reconcile(ctx context.Context, req ctrl.Re
204208// block at the very end to summarize the conditions to be in a consistent
205209// state.
206210func (r * HelmRepositoryOCIReconciler ) reconcile (ctx context.Context , obj * v1beta2.HelmRepository ) (result ctrl.Result , retErr error ) {
211+ ctxTimeout , cancel := context .WithTimeout (ctx , obj .Spec .Timeout .Duration )
212+ defer cancel ()
213+
207214 oldObj := obj .DeepCopy ()
208215
209216 defer func () {
@@ -296,6 +303,19 @@ func (r *HelmRepositoryOCIReconciler) reconcile(ctx context.Context, obj *v1beta
296303 }
297304 }
298305
306+ if obj .Spec .Provider != sourcev1 .GenericOCIProvider && obj .Spec .Type == sourcev1 .HelmRepositoryTypeOCI {
307+ auth , authErr := oidcAuth (ctxTimeout , obj )
308+ if authErr != nil && ! errors .Is (authErr , oci .ErrUnconfiguredProvider ) {
309+ e := fmt .Errorf ("failed to get credential from %s: %w" , obj .Spec .Provider , authErr )
310+ conditions .MarkFalse (obj , meta .ReadyCondition , sourcev1 .AuthenticationFailedReason , e .Error ())
311+ result , retErr = ctrl.Result {}, e
312+ return
313+ }
314+ if auth != nil {
315+ loginOpts = append (loginOpts , auth )
316+ }
317+ }
318+
299319 // Create registry client and login if needed.
300320 registryClient , file , err := r .RegistryClientGenerator (loginOpts != nil )
301321 if err != nil {
@@ -366,3 +386,42 @@ func (r *HelmRepositoryOCIReconciler) eventLogf(ctx context.Context, obj runtime
366386 }
367387 r .Eventf (obj , eventType , reason , msg )
368388}
389+
390+ // oidcAuth generates the OIDC credential authenticator based on the specified cloud provider.
391+ func oidcAuth (ctx context.Context , obj * sourcev1.HelmRepository ) (helmreg.LoginOption , error ) {
392+ url := strings .TrimPrefix (obj .Spec .URL , sourcev1 .OCIRepositoryPrefix )
393+ ref , err := name .ParseReference (url )
394+ if err != nil {
395+ return nil , fmt .Errorf ("failed to parse URL '%s': %w" , obj .Spec .URL , err )
396+ }
397+
398+ loginOpt , err := loginWithManager (ctx , obj .Spec .Provider , url , ref )
399+ if err != nil {
400+ return nil , fmt .Errorf ("failed to login to registry '%s': %w" , obj .Spec .URL , err )
401+ }
402+
403+ return loginOpt , nil
404+ }
405+
406+ func loginWithManager (ctx context.Context , provider , url string , ref name.Reference ) (helmreg.LoginOption , error ) {
407+ opts := login.ProviderOptions {}
408+ switch provider {
409+ case sourcev1 .AmazonOCIProvider :
410+ opts .AwsAutoLogin = true
411+ case sourcev1 .AzureOCIProvider :
412+ opts .AzureAutoLogin = true
413+ case sourcev1 .GoogleOCIProvider :
414+ opts .GcpAutoLogin = true
415+ }
416+
417+ auth , err := login .NewManager ().Login (ctx , url , ref , opts )
418+ if err != nil {
419+ return nil , err
420+ }
421+
422+ if auth == nil {
423+ return nil , nil
424+ }
425+
426+ return registry .OIDCAdaptHelper (auth )
427+ }
0 commit comments