From 2dde6bf536f34e2e4a64c500791ff775cdc51984 Mon Sep 17 00:00:00 2001 From: Matheus Pimenta Date: Sat, 3 May 2025 15:24:05 +0100 Subject: [PATCH] Upgrade fluxcd/pkg cache, auth, git and gogit Signed-off-by: Matheus Pimenta --- go.mod | 10 +-- go.sum | 20 ++--- .../controller/gitrepository_controller.go | 79 +++++++++++++------ .../gitrepository_controller_test.go | 11 ++- 4 files changed, 81 insertions(+), 39 deletions(-) diff --git a/go.mod b/go.mod index baf6ceab..483d4649 100644 --- a/go.mod +++ b/go.mod @@ -24,10 +24,10 @@ require ( github.com/fluxcd/cli-utils v0.36.0-flux.13 github.com/fluxcd/pkg/apis/event v0.17.0 github.com/fluxcd/pkg/apis/meta v1.11.0 - github.com/fluxcd/pkg/auth v0.10.0 - github.com/fluxcd/pkg/cache v0.8.0 - github.com/fluxcd/pkg/git v0.27.0 - github.com/fluxcd/pkg/git/gogit v0.28.0 + github.com/fluxcd/pkg/auth v0.11.0 + github.com/fluxcd/pkg/cache v0.9.0 + github.com/fluxcd/pkg/git v0.28.0 + github.com/fluxcd/pkg/git/gogit v0.30.0 github.com/fluxcd/pkg/gittestserver v0.17.0 github.com/fluxcd/pkg/helmtestserver v0.24.0 github.com/fluxcd/pkg/lockedfile v0.6.0 @@ -164,7 +164,7 @@ require ( github.com/containerd/log v0.1.0 // indirect github.com/containerd/platforms v0.2.1 // indirect github.com/containerd/stargz-snapshotter/estargz v0.16.3 // indirect - github.com/coreos/go-oidc/v3 v3.12.0 // indirect + github.com/coreos/go-oidc/v3 v3.14.1 // indirect github.com/coreos/go-systemd/v22 v22.5.0 // indirect github.com/cyberphone/json-canonicalization v0.0.0-20231011164504-785e29786b46 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect diff --git a/go.sum b/go.sum index d3d1f52f..c0731334 100644 --- a/go.sum +++ b/go.sum @@ -286,8 +286,8 @@ github.com/containerd/platforms v0.2.1 h1:zvwtM3rz2YHPQsF2CHYM8+KtB5dvhISiXh5ZpS github.com/containerd/platforms v0.2.1/go.mod h1:XHCb+2/hzowdiut9rkudds9bE5yJ7npe7dG/wG+uFPw= github.com/containerd/stargz-snapshotter/estargz v0.16.3 h1:7evrXtoh1mSbGj/pfRccTampEyKpjpOnS3CyiV1Ebr8= github.com/containerd/stargz-snapshotter/estargz v0.16.3/go.mod h1:uyr4BfYfOj3G9WBVE8cOlQmXAbPN9VEQpBBeJIuOipU= -github.com/coreos/go-oidc/v3 v3.12.0 h1:sJk+8G2qq94rDI6ehZ71Bol3oUHy63qNYmkiSjrc/Jo= -github.com/coreos/go-oidc/v3 v3.12.0/go.mod h1:gE3LgjOgFoHi9a4ce4/tJczr0Ai2/BoDhf0r5lltWI0= +github.com/coreos/go-oidc/v3 v3.14.1 h1:9ePWwfdwC4QKRlCXsJGou56adA/owXczOzwKdOumLqk= +github.com/coreos/go-oidc/v3 v3.14.1/go.mod h1:HaZ3szPaZ0e4r6ebqvsLWlk2Tn+aejfmrfah6hnSYEU= github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs= github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g= @@ -374,14 +374,14 @@ github.com/fluxcd/pkg/apis/event v0.17.0 h1:foEINE++pCJlWVhWjYDXfkVmGKu8mQ4BDBlb github.com/fluxcd/pkg/apis/event v0.17.0/go.mod h1:0fLhLFiHlRTDKPDXdRnv+tS7mCMIQ0fJxnEfmvGM/5A= github.com/fluxcd/pkg/apis/meta v1.11.0 h1:h8q95k6ZEK1HCfsLkt8Np3i6ktb6ZzcWJ6hg++oc9w0= github.com/fluxcd/pkg/apis/meta v1.11.0/go.mod h1:+son1Va60x2eiDcTwd7lcctbI6C+K3gM7R+ULmEq1SI= -github.com/fluxcd/pkg/auth v0.10.0 h1:acvokI08SVwZwYMMtlUqglZCPPSJKMvvFZ/3zRwWsLI= -github.com/fluxcd/pkg/auth v0.10.0/go.mod h1:Fpzdo9QOpmWRs60s/frxy1sFb+XGN2WNDIty5aJjnbY= -github.com/fluxcd/pkg/cache v0.8.0 h1:juNNGmJ2qKK16oLgX3mFA20kyo+LcfPwIBjt9KGG+S4= -github.com/fluxcd/pkg/cache v0.8.0/go.mod h1:jMwabjWfsC5lW8hE7NM3wtGNwSJ38Javx6EKbEi7INU= -github.com/fluxcd/pkg/git v0.27.0 h1:/IHNNKQY2eopq3xWjUpvx6F3WmH2RqWQ3gmRyeBfcUg= -github.com/fluxcd/pkg/git v0.27.0/go.mod h1:s0EFqP4jTKkUq0z/jSlsIhnIAl6HvPTnucrkSqRxE5Q= -github.com/fluxcd/pkg/git/gogit v0.28.0 h1:Eyi+0r7QFHv1rlGeZw2kclAiMe59WNAADl/YyUjPygQ= -github.com/fluxcd/pkg/git/gogit v0.28.0/go.mod h1:hMl2Q5UpnOJ5NmfI1qT9wrlV5Shb8LojXRKdokFu+DI= +github.com/fluxcd/pkg/auth v0.11.0 h1:1BC6fQ71lCLFKz7juGlvWq9ysR2HVl5JPOWoxy4RMWE= +github.com/fluxcd/pkg/auth v0.11.0/go.mod h1:BJVrbanLH0AoUBzOH7u016D21Zl3dvEd0AnAWVOo5Vs= +github.com/fluxcd/pkg/cache v0.9.0 h1:EGKfOLMG3fOwWnH/4Axl5xd425mxoQbZzlZoLfd8PDk= +github.com/fluxcd/pkg/cache v0.9.0/go.mod h1:jMwabjWfsC5lW8hE7NM3wtGNwSJ38Javx6EKbEi7INU= +github.com/fluxcd/pkg/git v0.28.0 h1:by7XTOvj4ZUPH1alYMJtDCVryhHue+UfjhrnPuJt5vA= +github.com/fluxcd/pkg/git v0.28.0/go.mod h1:VPv6O3mYnYvn79LOdWAFCl4fE8o651cxW/p/yxBoq2g= +github.com/fluxcd/pkg/git/gogit v0.30.0 h1:tdKRT4EDV8Cc2tBX+bg4H4gdcND7M4OEl6DQy1jSJmo= +github.com/fluxcd/pkg/git/gogit v0.30.0/go.mod h1:UCm/fOBuvX43BNz7Rc61Sukp2gBG/qxlOASaBkwMFvc= github.com/fluxcd/pkg/gittestserver v0.17.0 h1:JlBvWZQTDOI+np5Z+084m3DkeAH1hMusEybyRUDF63k= github.com/fluxcd/pkg/gittestserver v0.17.0/go.mod h1:E/40EmLoXcMqd6gLuLDC9F6KJxqHVGbBBeMNKk5XdxU= github.com/fluxcd/pkg/helmtestserver v0.24.0 h1:9sSfRG17GnDIup4sI8V+fdvKROtunU4JyIo34uvXq3Q= diff --git a/internal/controller/gitrepository_controller.go b/internal/controller/gitrepository_controller.go index 646698ec..9e815fa2 100644 --- a/internal/controller/gitrepository_controller.go +++ b/internal/controller/gitrepository_controller.go @@ -27,7 +27,7 @@ import ( "time" securejoin "github.com/cyphar/filepath-securejoin" - "github.com/fluxcd/pkg/auth/azure" + "github.com/fluxcd/pkg/auth" "github.com/fluxcd/pkg/git/github" "github.com/fluxcd/pkg/runtime/logger" "github.com/go-git/go-git/v5/plumbing/transport" @@ -485,9 +485,10 @@ func (r *GitRepositoryReconciler) reconcileSource(ctx context.Context, sp *patch } var proxyOpts *transport.ProxyOptions + var proxyURL *url.URL if obj.Spec.ProxySecretRef != nil { var err error - proxyOpts, err = r.getProxyOpts(ctx, obj.Spec.ProxySecretRef.Name, obj.GetNamespace()) + proxyOpts, proxyURL, err = r.getProxyOpts(ctx, obj.Spec.ProxySecretRef.Name, obj.GetNamespace()) if err != nil { e := serror.NewGeneric( fmt.Errorf("failed to configure proxy options: %w", err), @@ -509,7 +510,7 @@ func (r *GitRepositoryReconciler) reconcileSource(ctx context.Context, sp *patch return sreconcile.ResultEmpty, e } - authOpts, err := r.getAuthOpts(ctx, obj, *u) + authOpts, err := r.getAuthOpts(ctx, obj, *u, proxyURL) if err != nil { // Return error as the world as observed may change return sreconcile.ResultEmpty, err @@ -622,28 +623,45 @@ func (r *GitRepositoryReconciler) reconcileSource(ctx context.Context, sp *patch // getProxyOpts fetches the secret containing the proxy settings, constructs a // transport.ProxyOptions object using those settings and then returns it. func (r *GitRepositoryReconciler) getProxyOpts(ctx context.Context, proxySecretName, - proxySecretNamespace string) (*transport.ProxyOptions, error) { + proxySecretNamespace string) (*transport.ProxyOptions, *url.URL, error) { proxyData, err := r.getSecretData(ctx, proxySecretName, proxySecretNamespace) if err != nil { - return nil, fmt.Errorf("failed to get proxy secret '%s/%s': %w", proxySecretNamespace, proxySecretName, err) + return nil, nil, fmt.Errorf("failed to get proxy secret '%s/%s': %w", proxySecretNamespace, proxySecretName, err) } - address, ok := proxyData["address"] + b, ok := proxyData["address"] if !ok { - return nil, fmt.Errorf("invalid proxy secret '%s/%s': key 'address' is missing", proxySecretNamespace, proxySecretName) + return nil, nil, fmt.Errorf("invalid proxy secret '%s/%s': key 'address' is missing", proxySecretNamespace, proxySecretName) } + address := string(b) + username := string(proxyData["username"]) + password := string(proxyData["password"]) + proxyOpts := &transport.ProxyOptions{ - URL: string(address), - Username: string(proxyData["username"]), - Password: string(proxyData["password"]), + URL: address, + Username: username, + Password: password, } - return proxyOpts, nil + + proxyURL, err := url.Parse(string(address)) + if err != nil { + return nil, nil, fmt.Errorf("invalid address in proxy secret '%s/%s': %w", proxySecretNamespace, proxySecretName, err) + } + switch { + case username != "" && password == "": + proxyURL.User = url.User(username) + case username != "" && password != "": + proxyURL.User = url.UserPassword(username, password) + } + + return proxyOpts, proxyURL, nil } // getAuthOpts fetches the secret containing the auth options (if specified), // constructs a git.AuthOptions object using those options along with the provided // URL and returns it. -func (r *GitRepositoryReconciler) getAuthOpts(ctx context.Context, obj *sourcev1.GitRepository, u url.URL) (*git.AuthOptions, error) { +func (r *GitRepositoryReconciler) getAuthOpts(ctx context.Context, obj *sourcev1.GitRepository, + u url.URL, proxyURL *url.URL) (*git.AuthOptions, error) { var authData map[string][]byte if obj.Spec.SecretRef != nil { var err error @@ -659,7 +677,7 @@ func (r *GitRepositoryReconciler) getAuthOpts(ctx context.Context, obj *sourcev1 } // Configure authentication strategy to access the source - authOpts, err := git.NewAuthOptions(u, authData) + opts, err := git.NewAuthOptions(u, authData) if err != nil { e := serror.NewGeneric( fmt.Errorf("failed to configure authentication options: %w", err), @@ -669,14 +687,28 @@ func (r *GitRepositoryReconciler) getAuthOpts(ctx context.Context, obj *sourcev1 return nil, e } + var authOpts []auth.Option + + if r.tokenCache != nil { + involvedObject := cache.InvolvedObject{ + Kind: sourcev1.GitRepositoryKind, + Name: obj.GetName(), + Namespace: obj.GetNamespace(), + Operation: cache.OperationReconcile, + } + authOpts = append(authOpts, auth.WithCache(*r.tokenCache, involvedObject)) + } + + if proxyURL != nil { + authOpts = append(authOpts, auth.WithProxyURL(*proxyURL)) + } + // Configure provider authentication if specified in spec switch obj.GetProvider() { case sourcev1.GitProviderAzure: - authOpts.ProviderOpts = &git.ProviderOptions{ - Name: sourcev1.GitProviderAzure, - AzureOpts: []azure.OptFunc{ - azure.WithAzureDevOpsScope(), - }, + opts.ProviderOpts = &git.ProviderOptions{ + Name: sourcev1.GitProviderAzure, + AuthOpts: authOpts, } case sourcev1.GitProviderGitHub: // if provider is github, but secret ref is not specified @@ -689,11 +721,13 @@ func (r *GitRepositoryReconciler) getAuthOpts(ctx context.Context, obj *sourcev1 return nil, e } - authOpts.ProviderOpts = &git.ProviderOptions{ + opts.ProviderOpts = &git.ProviderOptions{ Name: sourcev1.GitProviderGitHub, GitHubOpts: []github.OptFunc{ github.WithAppData(authData), - github.WithCache(r.tokenCache, sourcev1.GitRepositoryKind, obj.GetName(), obj.GetNamespace()), + github.WithProxyURL(proxyURL), + github.WithCache(r.tokenCache, sourcev1.GitRepositoryKind, + obj.GetName(), obj.GetNamespace(), cache.OperationReconcile), }, } default: @@ -707,7 +741,7 @@ func (r *GitRepositoryReconciler) getAuthOpts(ctx context.Context, obj *sourcev1 return nil, e } } - return authOpts, nil + return opts, nil } func (r *GitRepositoryReconciler) getSecretData(ctx context.Context, name, namespace string) (map[string][]byte, error) { @@ -1116,7 +1150,8 @@ func (r *GitRepositoryReconciler) reconcileDelete(ctx context.Context, obj *sour controllerutil.RemoveFinalizer(obj, sourcev1.SourceFinalizer) // Cleanup caches. - r.tokenCache.DeleteEventsForObject(sourcev1.GitRepositoryKind, obj.GetName(), obj.GetNamespace()) + r.tokenCache.DeleteEventsForObject(sourcev1.GitRepositoryKind, + obj.GetName(), obj.GetNamespace(), cache.OperationReconcile) // Stop reconciliation as the object is being deleted return sreconcile.ResultEmpty, nil diff --git a/internal/controller/gitrepository_controller_test.go b/internal/controller/gitrepository_controller_test.go index 5dca5b16..596f0148 100644 --- a/internal/controller/gitrepository_controller_test.go +++ b/internal/controller/gitrepository_controller_test.go @@ -899,7 +899,7 @@ func TestGitRepositoryReconciler_getAuthOpts_provider(t *testing.T) { if tt.beforeFunc != nil { tt.beforeFunc(obj) } - opts, err := r.getAuthOpts(context.TODO(), obj, *url) + opts, err := r.getAuthOpts(context.TODO(), obj, *url, nil) if tt.wantErr != nil { g.Expect(err).To(HaveOccurred()) @@ -2267,6 +2267,7 @@ func TestGitRepositoryReconciler_getProxyOpts(t *testing.T) { secret string err string proxyOpts *transport.ProxyOptions + proxyURL *url.URL }{ { name: "non-existent secret", @@ -2286,16 +2287,22 @@ func TestGitRepositoryReconciler_getProxyOpts(t *testing.T) { Username: "user", Password: "pass", }, + proxyURL: &url.URL{ + Scheme: "https", + Host: "example.com", + User: url.UserPassword("user", "pass"), + }, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { g := NewWithT(t) - opts, err := r.getProxyOpts(context.TODO(), tt.secret, "default") + opts, proxyURL, err := r.getProxyOpts(context.TODO(), tt.secret, "default") if opts != nil { g.Expect(err).ToNot(HaveOccurred()) g.Expect(opts).To(Equal(tt.proxyOpts)) + g.Expect(proxyURL).To(Equal(tt.proxyURL)) } else { g.Expect(err).To(HaveOccurred()) g.Expect(err.Error()).To(ContainSubstring(tt.err))