@@ -22,6 +22,7 @@ import (
22
22
"fmt"
23
23
"net/url"
24
24
"os"
25
+ "strings"
25
26
"time"
26
27
27
28
helmgetter "helm.sh/helm/v3/pkg/getter"
@@ -41,10 +42,13 @@ import (
41
42
"sigs.k8s.io/controller-runtime/pkg/predicate"
42
43
43
44
"github.com/fluxcd/pkg/apis/meta"
45
+ "github.com/fluxcd/pkg/oci"
46
+ "github.com/fluxcd/pkg/oci/auth/login"
44
47
"github.com/fluxcd/pkg/runtime/conditions"
45
48
helper "github.com/fluxcd/pkg/runtime/controller"
46
49
"github.com/fluxcd/pkg/runtime/patch"
47
50
"github.com/fluxcd/pkg/runtime/predicates"
51
+ "github.com/google/go-containerregistry/pkg/name"
48
52
49
53
"github.com/fluxcd/source-controller/api/v1beta2"
50
54
sourcev1 "github.com/fluxcd/source-controller/api/v1beta2"
@@ -204,6 +208,9 @@ func (r *HelmRepositoryOCIReconciler) Reconcile(ctx context.Context, req ctrl.Re
204
208
// block at the very end to summarize the conditions to be in a consistent
205
209
// state.
206
210
func (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
+
207
214
oldObj := obj .DeepCopy ()
208
215
209
216
defer func () {
@@ -296,6 +303,20 @@ func (r *HelmRepositoryOCIReconciler) reconcile(ctx context.Context, obj *v1beta
296
303
}
297
304
}
298
305
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 :=
310
+ fmt .Errorf ("failed to get credential from %s: %w" , obj .Spec .Provider , authErr )
311
+ conditions .MarkFalse (obj , meta .ReadyCondition , sourcev1 .AuthenticationFailedReason , e .Error ())
312
+ result , retErr = ctrl.Result {}, e
313
+ return
314
+ }
315
+ if auth != nil {
316
+ loginOpts = append (loginOpts , auth )
317
+ }
318
+ }
319
+
299
320
// Create registry client and login if needed.
300
321
registryClient , file , err := r .RegistryClientGenerator (loginOpts != nil )
301
322
if err != nil {
@@ -366,3 +387,42 @@ func (r *HelmRepositoryOCIReconciler) eventLogf(ctx context.Context, obj runtime
366
387
}
367
388
r .Eventf (obj , eventType , reason , msg )
368
389
}
390
+
391
+ // oidcAuth generates the OIDC credential authenticator based on the specified cloud provider.
392
+ func oidcAuth (ctx context.Context , obj * sourcev1.HelmRepository ) (helmreg.LoginOption , error ) {
393
+ url := strings .TrimPrefix (obj .Spec .URL , helmreg .OCIScheme )
394
+ ref , err := name .ParseReference (url )
395
+ if err != nil {
396
+ return nil , fmt .Errorf ("failed to parse URL '%s': %w" , obj .Spec .URL , err )
397
+ }
398
+
399
+ loginOpt , err := loginWithManager (ctx , obj .Spec .Provider , url , ref )
400
+ if err != nil {
401
+ return nil , fmt .Errorf ("failed to login to registry '%s': %w" , obj .Spec .URL , err )
402
+ }
403
+
404
+ return loginOpt , nil
405
+ }
406
+
407
+ func loginWithManager (ctx context.Context , provider , url string , ref name.Reference ) (helmreg.LoginOption , error ) {
408
+ opts := login.ProviderOptions {}
409
+ switch provider {
410
+ case sourcev1 .AmazonOCIProvider :
411
+ opts .AwsAutoLogin = true
412
+ case sourcev1 .AzureOCIProvider :
413
+ opts .AzureAutoLogin = true
414
+ case sourcev1 .GoogleOCIProvider :
415
+ opts .GcpAutoLogin = true
416
+ }
417
+
418
+ auth , err := login .NewManager ().Login (ctx , url , ref , opts )
419
+ if err != nil {
420
+ return nil , err
421
+ }
422
+
423
+ if auth == nil {
424
+ return nil , nil
425
+ }
426
+
427
+ return registry .OIDCAdaptHelper (auth )
428
+ }
0 commit comments