Enable caching contextual Login Credentials

Provide an optional Cache to the Login Manager used to retrive
contextual login credentials.

Signed-off-by: Soule BA <bah.soule@gmail.com>
This commit is contained in:
Soule BA 2024-06-19 17:33:07 +02:00
parent 59ad5a72ee
commit 5ecc6b10a8
No known key found for this signature in database
GPG Key ID: 4D40965192802994
12 changed files with 158 additions and 34 deletions

4
go.mod
View File

@ -22,13 +22,14 @@ require (
github.com/fluxcd/cli-utils v0.36.0-flux.7
github.com/fluxcd/pkg/apis/event v0.9.0
github.com/fluxcd/pkg/apis/meta v1.5.0
github.com/fluxcd/pkg/cache v0.0.1
github.com/fluxcd/pkg/git v0.19.0
github.com/fluxcd/pkg/git/gogit v0.19.0
github.com/fluxcd/pkg/gittestserver v0.12.0
github.com/fluxcd/pkg/helmtestserver v0.18.0
github.com/fluxcd/pkg/lockedfile v0.3.0
github.com/fluxcd/pkg/masktoken v0.4.0
github.com/fluxcd/pkg/oci v0.37.1
github.com/fluxcd/pkg/oci v0.38.0
github.com/fluxcd/pkg/runtime v0.47.1
github.com/fluxcd/pkg/sourceignore v0.7.0
github.com/fluxcd/pkg/ssh v0.13.0
@ -314,7 +315,6 @@ require (
github.com/spf13/cobra v1.8.0 // indirect
github.com/spf13/viper v1.18.2 // indirect
github.com/spiffe/go-spiffe/v2 v2.2.0 // indirect
github.com/stretchr/objx v0.5.1 // indirect
github.com/subosito/gotenv v1.6.0 // indirect
github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d // indirect
github.com/thales-e-security/pool v0.0.2 // indirect

10
go.sum
View File

@ -342,6 +342,8 @@ github.com/fluxcd/pkg/apis/event v0.9.0 h1:iKxU+3v/3bAuC1C1iXg1mjbIiaEQet7WETh8l
github.com/fluxcd/pkg/apis/event v0.9.0/go.mod h1:5LjcTeppPMEyOgtTbIP7q2GbVwIRUfujIxynIjHBV/k=
github.com/fluxcd/pkg/apis/meta v1.5.0 h1:/G82d2Az5D9op3F+wJUpD8jw/eTV0suM6P7+cSURoUM=
github.com/fluxcd/pkg/apis/meta v1.5.0/go.mod h1:Y3u7JomuuKtr5fvP1Iji2/50FdRe5GcBug2jawNVkdM=
github.com/fluxcd/pkg/cache v0.0.1 h1:aeDQm4D37btj6I01p6ZKW6JNOZm3CIYN5PaVzyhHr38=
github.com/fluxcd/pkg/cache v0.0.1/go.mod h1:R3TJIK9XaohHNc3BeqfZX/UivMrx8Xz6ihGoVAjh75k=
github.com/fluxcd/pkg/git v0.19.0 h1:zIv+GAT0ieIUpnGBVi3Bhax/qq4Rr28BW7Jv4DTt6zE=
github.com/fluxcd/pkg/git v0.19.0/go.mod h1:wkqUOSrTjtsVVk/gC6/7RxVpi9GcqAA+7O5HVJF5S14=
github.com/fluxcd/pkg/git/gogit v0.19.0 h1:SdoNAmC/HTPXniQjp609X59rCsBiA+Sdq1Hv8SnYC6I=
@ -354,8 +356,8 @@ github.com/fluxcd/pkg/lockedfile v0.3.0 h1:tZkBAffcxyt4zMigHIKc54cKgN5I/kFF005gy
github.com/fluxcd/pkg/lockedfile v0.3.0/go.mod h1:5iCYXAs953LlXZq7nTId9ZSGnHVvTfZ0mDmrDE49upk=
github.com/fluxcd/pkg/masktoken v0.4.0 h1:pRItymXzW8dhT9Fd4XfnbrgKeySPeeLCrr6W1pgrUbM=
github.com/fluxcd/pkg/masktoken v0.4.0/go.mod h1:MP1nCsr2tJbH8hnhZP4+7TfTR0ggrKOJgi9Bo7Mj/6M=
github.com/fluxcd/pkg/oci v0.37.1 h1:p4rfCHZlBWL+Q5Xey51iiBRmoje0IevCBT0/r8iae3M=
github.com/fluxcd/pkg/oci v0.37.1/go.mod h1:LrVuX6VACenJ5ycQJxec+I7YJegCsE4nzRUV+6RuxcY=
github.com/fluxcd/pkg/oci v0.38.0 h1:a9pCdqiUPZ7YOnYDXVXCxELBU0r6xbDnGv4C6YUz7vU=
github.com/fluxcd/pkg/oci v0.38.0/go.mod h1:mYVSxnpVutRmWu6mpwxm7hXFn6qdhLEjspL04ej/WZU=
github.com/fluxcd/pkg/runtime v0.47.1 h1:Q1tAFsp92uurWyoEe52AmMC4k+6DYTPBrUQDs+nz/9c=
github.com/fluxcd/pkg/runtime v0.47.1/go.mod h1:97a+PqpWMgQsoqh91uH3EQz+/DC7Uxc8xcu/rDHFC5c=
github.com/fluxcd/pkg/sourceignore v0.7.0 h1:qQrB2o543wA1o4vgR62ufwkAaDp8+f8Wdj1HKDlmDrU=
@ -911,8 +913,8 @@ github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+
github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/objx v0.5.1 h1:4VhoImhV/Bm0ToFkXFi8hXNXwpDRZ/ynw3amt82mzq0=
github.com/stretchr/objx v0.5.1/go.mod h1:/iHQpkQwBD6DLUmQ4pE+s1TXdob1mORJ4/UFdrifcy0=
github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=

View File

@ -47,7 +47,7 @@ func NewCacheRecorder() *CacheRecorder {
return &CacheRecorder{
cacheEventsCounter: prometheus.NewCounterVec(
prometheus.CounterOpts{
Name: "gotk_cache_events_total",
Name: "gotk_sc_cache_events_total",
Help: "Total number of cache retrieval events for a Gitops Toolkit resource reconciliation.",
},
[]string{"event_type", "name", "namespace"},

View File

@ -138,8 +138,9 @@ type HelmChartReconciler struct {
Getters helmgetter.Providers
ControllerName string
Cache *cache.Cache
TTL time.Duration
OIDCAuthenticator *soci.OIDCAuthenticator
Cache *cache.Cache
TTL time.Duration
*cache.CacheRecorder
patchOptions []patch.Option
@ -527,7 +528,8 @@ func (r *HelmChartReconciler) buildFromHelmRepository(ctx context.Context, obj *
return chartRepoConfigErrorReturn(err, obj)
}
clientOpts, certsTmpDir, err := getter.GetClientOpts(ctxTimeout, r.Client, repo, normalizedURL)
clientOpts, certsTmpDir, err := getter.GetClientOptsWithOIDCAuth(ctxTimeout,
r.Client, r.OIDCAuthenticator, repo, normalizedURL)
if err != nil && !errors.Is(err, getter.ErrDeprecatedTLSConfig) {
e := serror.NewGeneric(
err,
@ -1012,8 +1014,9 @@ func (r *HelmChartReconciler) namespacedChartRepositoryCallback(ctx context.Cont
}
obj = &sourcev1.HelmRepository{
Spec: sourcev1.HelmRepositorySpec{
URL: url,
Timeout: &metav1.Duration{Duration: 60 * time.Second},
URL: url,
Timeout: &metav1.Duration{Duration: 60 * time.Second},
Provider: sourcev1beta2.GenericOCIProvider,
},
}
}
@ -1022,7 +1025,8 @@ func (r *HelmChartReconciler) namespacedChartRepositoryCallback(ctx context.Cont
ctxTimeout, cancel := context.WithTimeout(ctx, obj.GetTimeout())
defer cancel()
clientOpts, certsTmpDir, err := getter.GetClientOpts(ctxTimeout, r.Client, obj, normalizedURL)
clientOpts, certsTmpDir, err := getter.GetClientOptsWithOIDCAuth(ctxTimeout, r.Client,
r.OIDCAuthenticator, obj, normalizedURL)
if err != nil && !errors.Is(err, getter.ErrDeprecatedTLSConfig) {
return nil, err
}

View File

@ -1129,8 +1129,9 @@ func TestHelmChartReconciler_buildFromHelmRepository(t *testing.T) {
GenerateName: "helmrepository-",
},
Spec: sourcev1.HelmRepositorySpec{
URL: server.URL(),
Timeout: &metav1.Duration{Duration: timeout},
URL: server.URL(),
Timeout: &metav1.Duration{Duration: timeout},
Provider: sourcev1beta2.GenericOCIProvider,
},
Status: sourcev1.HelmRepositoryStatus{
Artifact: &sourcev1.Artifact{
@ -2647,11 +2648,14 @@ func TestHelmChartReconciler_reconcileSourceFromOCI_authStrategy(t *testing.T) {
},
}
authenticator, er := oci.NewOIDCAuthenticator(oci.WithCacheCapacity(1))
g.Expect(er).NotTo(HaveOccurred())
r := &HelmChartReconciler{
Client: clientBuilder.Build(),
EventRecorder: record.NewFakeRecorder(32),
Getters: testGetters,
RegistryClientGenerator: registry.ClientGenerator,
OIDCAuthenticator: authenticator,
patchOptions: getPatchOptions(helmChartReadyCondition.Owned, "sc"),
}

View File

@ -50,6 +50,7 @@ import (
"github.com/fluxcd/pkg/runtime/patch"
sourcev1 "github.com/fluxcd/source-controller/api/v1"
sourcev1beta2 "github.com/fluxcd/source-controller/api/v1beta2"
"github.com/fluxcd/source-controller/internal/cache"
intdigest "github.com/fluxcd/source-controller/internal/digest"
"github.com/fluxcd/source-controller/internal/helm/getter"
@ -819,6 +820,7 @@ func TestHelmRepositoryReconciler_reconcileSource(t *testing.T) {
Spec: sourcev1.HelmRepositorySpec{
Interval: metav1.Duration{Duration: interval},
Timeout: &metav1.Duration{Duration: timeout},
Provider: sourcev1beta2.GenericOCIProvider,
},
}

View File

@ -141,6 +141,7 @@ type OCIRepositoryReconciler struct {
Storage *Storage
ControllerName string
requeueDependency time.Duration
OIDCAuthenticator *soci.OIDCAuthenticator
patchOptions []patch.Option
}
@ -355,7 +356,7 @@ func (r *OCIRepositoryReconciler) reconcileSource(ctx context.Context, sp *patch
if _, ok := keychain.(soci.Anonymous); obj.Spec.Provider != ociv1.GenericOCIProvider && ok {
var authErr error
auth, authErr = soci.OIDCAuth(ctxTimeout, obj.Spec.URL, obj.Spec.Provider)
auth, authErr = r.OIDCAuthenticator.Authorization(ctxTimeout, obj.Spec.URL, obj.Spec.Provider)
if authErr != nil && !errors.Is(authErr, oci.ErrUnconfiguredProvider) {
e := serror.NewGeneric(
fmt.Errorf("failed to get credential from %s: %w", obj.Spec.Provider, authErr),

View File

@ -69,8 +69,10 @@ import (
sourcev1 "github.com/fluxcd/source-controller/api/v1"
ociv1 "github.com/fluxcd/source-controller/api/v1beta2"
sourcev1beta2 "github.com/fluxcd/source-controller/api/v1beta2"
intdigest "github.com/fluxcd/source-controller/internal/digest"
serror "github.com/fluxcd/source-controller/internal/error"
soci "github.com/fluxcd/source-controller/internal/oci"
snotation "github.com/fluxcd/source-controller/internal/oci/notation"
sreconcile "github.com/fluxcd/source-controller/internal/reconcile"
)
@ -795,11 +797,15 @@ func TestOCIRepository_reconcileSource_authStrategy(t *testing.T) {
obj.Spec.Insecure = true
}
authenticator, er := soci.NewOIDCAuthenticator(soci.WithCacheCapacity(1))
g.Expect(er).NotTo(HaveOccurred())
r := &OCIRepositoryReconciler{
Client: clientBuilder.Build(),
EventRecorder: record.NewFakeRecorder(32),
Storage: testStorage,
patchOptions: getPatchOptions(ociRepositoryReadyCondition.Owned, "sc"),
Client: clientBuilder.Build(),
EventRecorder: record.NewFakeRecorder(32),
Storage: testStorage,
OIDCAuthenticator: authenticator,
patchOptions: getPatchOptions(ociRepositoryReadyCondition.Owned, "sc"),
}
opts := makeRemoteOptions(ctx, makeTransport(tt.insecure), authn.DefaultKeychain, nil)
@ -1147,6 +1153,7 @@ func TestOCIRepository_reconcileSource_remoteReference(t *testing.T) {
Interval: metav1.Duration{Duration: interval},
Timeout: &metav1.Duration{Duration: timeout},
Insecure: true,
Provider: sourcev1beta2.GenericOCIProvider,
},
}
@ -1398,6 +1405,7 @@ func TestOCIRepository_reconcileSource_verifyOCISourceSignatureNotation(t *testi
},
Interval: metav1.Duration{Duration: interval},
Timeout: &metav1.Duration{Duration: timeout},
Provider: sourcev1beta2.GenericOCIProvider,
},
}
@ -1718,6 +1726,7 @@ func TestOCIRepository_reconcileSource_verifyOCISourceTrustPolicyNotation(t *tes
},
Interval: metav1.Duration{Duration: interval},
Timeout: &metav1.Duration{Duration: timeout},
Provider: sourcev1beta2.GenericOCIProvider,
},
}
@ -2042,6 +2051,7 @@ func TestOCIRepository_reconcileSource_verifyOCISourceSignatureCosign(t *testing
},
Interval: metav1.Duration{Duration: interval},
Timeout: &metav1.Duration{Duration: timeout},
Provider: sourcev1beta2.GenericOCIProvider,
},
}
@ -2265,6 +2275,7 @@ func TestOCIRepository_reconcileSource_verifyOCISourceSignature_keyless(t *testi
},
Interval: metav1.Duration{Duration: interval},
Timeout: &metav1.Duration{Duration: timeout},
Provider: sourcev1beta2.GenericOCIProvider,
Reference: tt.reference,
},
}
@ -2448,6 +2459,7 @@ func TestOCIRepository_reconcileSource_noop(t *testing.T) {
Reference: &ociv1.OCIRepositoryRef{Tag: "6.1.5"},
Interval: metav1.Duration{Duration: interval},
Timeout: &metav1.Duration{Duration: timeout},
Provider: sourcev1beta2.GenericOCIProvider,
Insecure: true,
},
}

View File

@ -64,13 +64,17 @@ func (o ClientOpts) MustLoginToRegistry() bool {
return len(o.RegLoginOpts) > 0 && o.RegLoginOpts[0] != nil
}
// GetClientOpts uses the provided HelmRepository object and a normalized
// GetClientOptsWithOIDCAuth uses the provided HelmRepository object and a normalized
// URL to construct a HelmClientOpts object. If obj is an OCI HelmRepository,
// then the returned options object will also contain the required registry
// auth mechanisms.
// A temporary directory is created to store the certs files if needed and its path is returned along with the options object. It is the
// caller's responsibility to clean up the directory.
func GetClientOpts(ctx context.Context, c client.Client, obj *sourcev1.HelmRepository, url string) (*ClientOpts, string, error) {
func GetClientOptsWithOIDCAuth(ctx context.Context, c client.Client, oidcAuthenticator *soci.OIDCAuthenticator,
obj *sourcev1.HelmRepository, url string) (*ClientOpts, string, error) {
if obj.Spec.Provider != sourcev1beta2.GenericOCIProvider && oidcAuthenticator == nil {
return nil, "", fmt.Errorf("OIDC authenticator is not configured")
}
hrOpts := &ClientOpts{
GetterOpts: []helmgetter.Option{
helmgetter.WithURL(url),
@ -137,7 +141,7 @@ func GetClientOpts(ctx context.Context, c client.Client, obj *sourcev1.HelmRepos
}
}
} else if obj.Spec.Provider != sourcev1beta2.GenericOCIProvider && obj.Spec.Type == sourcev1.HelmRepositoryTypeOCI && ociRepo {
authenticator, authErr := soci.OIDCAuth(ctx, obj.Spec.URL, obj.Spec.Provider)
authenticator, authErr := oidcAuthenticator.Authorization(ctx, obj.Spec.URL, obj.Spec.Provider)
if authErr != nil && !errors.Is(authErr, oci.ErrUnconfiguredProvider) {
return nil, "", fmt.Errorf("failed to get credential from '%s': %w", obj.Spec.Provider, authErr)
}
@ -179,6 +183,16 @@ func GetClientOpts(ctx context.Context, c client.Client, obj *sourcev1.HelmRepos
return hrOpts, dir, err
}
// GetClientOpts uses the provided HelmRepository object and a normalized
// URL to construct a HelmClientOpts object. If obj is an OCI HelmRepository,
// then the returned options object will also contain the required registry
// auth mechanisms.
// A temporary directory is created to store the certs files if needed and its path is returned along with the options object. It is the
// caller's responsibility to clean up the directory.
func GetClientOpts(ctx context.Context, c client.Client, obj *sourcev1.HelmRepository, url string) (*ClientOpts, string, error) {
return GetClientOptsWithOIDCAuth(ctx, c, nil, obj, url)
}
func fetchSecret(ctx context.Context, c client.Client, name, namespace string) (*corev1.Secret, error) {
key := types.NamespacedName{
Namespace: namespace,

View File

@ -30,6 +30,7 @@ import (
fakeclient "sigs.k8s.io/controller-runtime/pkg/client/fake"
helmv1 "github.com/fluxcd/source-controller/api/v1"
sourcev1beta2 "github.com/fluxcd/source-controller/api/v1beta2"
)
func TestGetClientOpts(t *testing.T) {
@ -143,6 +144,7 @@ func TestGetClientOpts(t *testing.T) {
Duration: time.Second,
},
Insecure: tt.insecure,
Provider: sourcev1beta2.GenericOCIProvider,
},
}
if tt.oci {
@ -249,7 +251,8 @@ func TestGetClientOpts_registryTLSLoginOption(t *testing.T) {
Timeout: &metav1.Duration{
Duration: time.Second,
},
Type: helmv1.HelmRepositoryTypeOCI,
Provider: sourcev1beta2.GenericOCIProvider,
Type: helmv1.HelmRepositoryTypeOCI,
},
}

View File

@ -20,14 +20,30 @@ import (
"context"
"fmt"
"strings"
"time"
"github.com/fluxcd/pkg/cache"
"github.com/fluxcd/pkg/oci/auth/login"
"github.com/google/go-containerregistry/pkg/authn"
"github.com/google/go-containerregistry/pkg/name"
"sigs.k8s.io/controller-runtime/pkg/metrics"
sourcev1 "github.com/fluxcd/source-controller/api/v1beta2"
)
const (
// We want to cache the authenticators for the 3rd party providers
// There are at least 3 providers (aws, azure, gcp), but there could be more
// e.g. alibaba, ibm, etc. But realistically, we can expect the number of
// providers to be less than 10.
DefaultAuthCacheCapacity = 10
// The cache cleanup interval, to remove expired entries
// 1 minute is a reasonable interval for authentication tokens.
// We don't want to be aggressive with the cleanup, as the tokens
// are valid for a longer period of time usually.
defaultAuthCacheInterval = time.Minute
)
// Anonymous is an authn.AuthConfig that always returns an anonymous
// authenticator. It is useful for registries that do not require authentication
// or when the credentials are not known.
@ -39,15 +55,62 @@ func (a Anonymous) Resolve(_ authn.Resource) (authn.Authenticator, error) {
return authn.Anonymous, nil
}
// OIDCAuth generates the OIDC credential authenticator based on the specified cloud provider.
func OIDCAuth(ctx context.Context, url, provider string) (authn.Authenticator, error) {
// OIDCAuthenticatorOptionFunc is a functional option for the OIDCAuthenticator.
type OIDCAuthenticatorOptionFunc func(opts *oidcAuthenticatorOptions)
type oidcAuthenticatorOptions struct {
capacity int
}
// WithCacheCapacity sets the capacity of the cache.
func WithCacheCapacity(capacity int) OIDCAuthenticatorOptionFunc {
return func(opts *oidcAuthenticatorOptions) {
opts.capacity = capacity
}
}
// OIDCAuthenticator holds a manager for the OIDC authenticators.
// It caches the authenticators to avoid re-authenticating for the same URL.
type OIDCAuthenticator struct {
manager *login.Manager
cache cache.Expirable[cache.StoreObject[authn.Authenticator]]
}
// NewOIDCAuthenticator returns a new OIDCAuthenticator.
// The capacity is the number of authenticators to cache.
// If the capacity is less than or equal to 0, the cache is disabled.
func NewOIDCAuthenticator(opts ...OIDCAuthenticatorOptionFunc) (*OIDCAuthenticator, error) {
o := &oidcAuthenticatorOptions{}
for _, opt := range opts {
opt(o)
}
var (
c cache.Expirable[cache.StoreObject[authn.Authenticator]]
err error
)
if o.capacity > 0 {
c, err = cache.New(o.capacity, cache.StoreObjectKeyFunc,
cache.WithCleanupInterval[cache.StoreObject[authn.Authenticator]](defaultAuthCacheInterval),
cache.WithMetricsRegisterer[cache.StoreObject[authn.Authenticator]](metrics.Registry))
if err != nil {
return nil, fmt.Errorf("failed to create cache: %w", err)
}
}
manager := login.NewManager()
return &OIDCAuthenticator{cache: c, manager: manager}, nil
}
// Authorization returns an authenticator for the OIDC credentials.
func (o *OIDCAuthenticator) Authorization(ctx context.Context, url, provider string) (authn.Authenticator, error) {
u := strings.TrimPrefix(url, sourcev1.OCIRepositoryPrefix)
ref, err := name.ParseReference(u)
if err != nil {
return nil, fmt.Errorf("failed to parse URL '%s': %w", u, err)
}
opts := login.ProviderOptions{}
opts := login.ProviderOptions{Cache: o.cache}
switch provider {
case sourcev1.AmazonOCIProvider:
opts.AwsAutoLogin = true
@ -57,5 +120,5 @@ func OIDCAuth(ctx context.Context, url, provider string) (authn.Authenticator, e
opts.GcpAutoLogin = true
}
return login.NewManager().Login(ctx, u, ref, opts)
return o.manager.Login(ctx, u, ref, opts)
}

31
main.go
View File

@ -50,7 +50,7 @@ import (
"github.com/fluxcd/pkg/runtime/pprof"
"github.com/fluxcd/pkg/runtime/probes"
"github.com/fluxcd/source-controller/api/v1"
v1 "github.com/fluxcd/source-controller/api/v1"
"github.com/fluxcd/source-controller/api/v1beta2"
// +kubebuilder:scaffold:imports
@ -61,6 +61,7 @@ import (
"github.com/fluxcd/source-controller/internal/features"
"github.com/fluxcd/source-controller/internal/helm"
"github.com/fluxcd/source-controller/internal/helm/registry"
"github.com/fluxcd/source-controller/internal/oci"
)
const controllerName = "source-controller"
@ -187,6 +188,8 @@ func main() {
mustSetupHelmLimits(helmIndexLimit, helmChartLimit, helmChartFileLimit)
helmIndexCache, helmIndexCacheItemTTL := mustInitHelmCache(helmCacheMaxSize, helmCacheTTL, helmCachePurgeInterval)
authenticator := mustInitOIDCAuthenticator()
ctx := ctrl.SetupSignalHandler()
if err := (&controller.GitRepositoryReconciler{
@ -228,6 +231,7 @@ func main() {
EventRecorder: eventRecorder,
Metrics: metrics,
ControllerName: controllerName,
OIDCAuthenticator: authenticator,
Cache: helmIndexCache,
TTL: helmIndexCacheItemTTL,
CacheRecorder: cacheRecorder,
@ -252,11 +256,12 @@ func main() {
}
if err := (&controller.OCIRepositoryReconciler{
Client: mgr.GetClient(),
Storage: storage,
EventRecorder: eventRecorder,
ControllerName: controllerName,
Metrics: metrics,
Client: mgr.GetClient(),
Storage: storage,
EventRecorder: eventRecorder,
ControllerName: controllerName,
Metrics: metrics,
OIDCAuthenticator: authenticator,
}).SetupWithManagerAndOptions(mgr, controller.OCIRepositoryReconcilerOptions{
RateLimiter: helper.GetRateLimiter(rateLimiterOptions),
}); err != nil {
@ -406,6 +411,20 @@ func mustInitHelmCache(maxSize int, itemTTL, purgeInterval string) (*cache.Cache
return cache.New(maxSize, interval), ttl
}
func mustInitOIDCAuthenticator() *oci.OIDCAuthenticator {
capacity := oci.DefaultAuthCacheCapacity
disabled, found := os.LookupEnv("LOGIN_CACHE_DISABLED")
if found && disabled == "true" {
capacity = -1
}
authenticator, err := oci.NewOIDCAuthenticator(oci.WithCacheCapacity(capacity))
if err != nil {
setupLog.Error(err, "unable to initialise OIDC authenticator")
os.Exit(1)
}
return authenticator
}
func mustInitStorage(path string, storageAdvAddr string, artifactRetentionTTL time.Duration, artifactRetentionRecords int, artifactDigestAlgo string) *controller.Storage {
if storageAdvAddr == "" {
storageAdvAddr = determineAdvStorageAddr(storageAdvAddr)