From 91d1e1df485ddce4f6134cff9dd546507b44b023 Mon Sep 17 00:00:00 2001 From: Timo Furrer Date: Tue, 14 Mar 2023 17:26:13 +0100 Subject: [PATCH 1/2] Update go-git-providers to v0.15.0 Signed-off-by: Timo Furrer --- go.mod | 10 +++++----- go.sum | 19 ++++++++++--------- 2 files changed, 15 insertions(+), 14 deletions(-) diff --git a/go.mod b/go.mod index 275974fc..5df8c924 100644 --- a/go.mod +++ b/go.mod @@ -7,7 +7,7 @@ require ( github.com/ProtonMail/go-crypto v0.0.0-20230217124315-7d5c6f04bbb8 github.com/cyphar/filepath-securejoin v0.2.3 github.com/distribution/distribution/v3 v3.0.0-20230223072852-e5d5810851d1 - github.com/fluxcd/go-git-providers v0.14.0 + github.com/fluxcd/go-git-providers v0.15.0 github.com/fluxcd/go-git/v5 v5.0.0-20221219190809-2e5c9d01cfc4 github.com/fluxcd/helm-controller/api v0.31.2 github.com/fluxcd/image-automation-controller/api v0.31.0 @@ -125,7 +125,7 @@ require ( github.com/gogo/protobuf v1.3.2 // indirect github.com/golang-jwt/jwt/v4 v4.4.2 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect - github.com/golang/protobuf v1.5.2 // indirect + github.com/golang/protobuf v1.5.3 // indirect github.com/gomodule/redigo v1.8.2 // indirect github.com/gonvenience/neat v1.3.11 // indirect github.com/gonvenience/term v1.0.2 // indirect @@ -190,7 +190,7 @@ require ( github.com/texttheater/golang-levenshtein v1.0.1 // indirect github.com/vbatts/tar-split v0.11.2 // indirect github.com/virtuald/go-ordered-json v0.0.0-20170621173500-b18e6e673d74 // indirect - github.com/xanzy/go-gitlab v0.78.0 // indirect + github.com/xanzy/go-gitlab v0.81.0 // indirect github.com/xanzy/ssh-agent v0.3.3 // indirect github.com/xlab/treeprint v1.1.0 // indirect github.com/yvasiyarov/go-metrics v0.0.0-20140926110328-57bccd1ccd43 // indirect @@ -199,7 +199,7 @@ require ( go.starlark.net v0.0.0-20221028183056-acb66ad56dd2 // indirect golang.org/x/mod v0.8.0 // indirect golang.org/x/net v0.8.0 // indirect - golang.org/x/oauth2 v0.3.0 // indirect + golang.org/x/oauth2 v0.6.0 // indirect golang.org/x/sync v0.1.0 // indirect golang.org/x/sys v0.6.0 // indirect golang.org/x/text v0.8.0 // indirect @@ -207,7 +207,7 @@ require ( golang.org/x/tools v0.6.0 // indirect gomodules.xyz/jsonpatch/v2 v2.2.0 // indirect google.golang.org/appengine v1.6.7 // indirect - google.golang.org/protobuf v1.28.1 // indirect + google.golang.org/protobuf v1.29.0 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/warnings.v0 v0.1.2 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect diff --git a/go.sum b/go.sum index c6f75694..4acc2861 100644 --- a/go.sum +++ b/go.sum @@ -195,8 +195,8 @@ github.com/felixge/httpsnoop v1.0.3 h1:s/nj+GCswXYzN5v2DpNMuMQYe+0DDwt5WVCU6CWBd github.com/felixge/httpsnoop v1.0.3/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/flowstack/go-jsonschema v0.1.1/go.mod h1:yL7fNggx1o8rm9RlgXv7hTBWxdBM0rVwpMwimd3F3N0= github.com/fluxcd/gitkit v0.6.0 h1:iNg5LTx6ePo+Pl0ZwqHTAkhbUHxGVSY3YCxCdw7VIFg= -github.com/fluxcd/go-git-providers v0.14.0 h1:F662wkiMevhGYKCwe9AJItpq42aJbd+tQq7d5Yskh/k= -github.com/fluxcd/go-git-providers v0.14.0/go.mod h1:cxVVQEBEswAIgbRVi50Cf6pEM/+RhNcNwDpsIkN6pG0= +github.com/fluxcd/go-git-providers v0.15.0 h1:WuBw+CcmXi7UhSf8mFNB6tbGelS0kVlgI9wtlWjzimk= +github.com/fluxcd/go-git-providers v0.15.0/go.mod h1:SgShGfc2rA5Gi7N65CBjMOIolarDZzZCMzEHOoY3P0I= github.com/fluxcd/go-git/v5 v5.0.0-20221219190809-2e5c9d01cfc4 h1:Gm5sGGk+/Wq6RhX4xpCZ2IqjDp5XkjlhENaAuAlpdKc= github.com/fluxcd/go-git/v5 v5.0.0-20221219190809-2e5c9d01cfc4/go.mod h1:raWgfUV7lDQVXp4QXUaeNNJkRVKz97UQuF+0kdY7Vmo= github.com/fluxcd/helm-controller/api v0.31.2 h1:d/lbCPYiQP+YnPNhdIOGRzHUWDIhnxI9dUSaOCx/RK8= @@ -319,8 +319,9 @@ github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QD github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= +github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/gomodule/redigo v1.8.2 h1:H5XSIre1MB5NbPYFp+i1NBbb5qN1W8Y8YAQoAYbkm8k= github.com/gomodule/redigo v1.8.2/go.mod h1:P9dn9mFrCBvWhGE1wpxx6fgq7BAeLBk+UUUzlpkBYO0= github.com/gonvenience/bunt v1.3.4 h1:Row599Ohja2BPooaqd1tHYdTAKu6SWq7W/UeakTXddM= @@ -611,8 +612,8 @@ github.com/vbatts/tar-split v0.11.2 h1:Via6XqJr0hceW4wff3QRzD5gAk/tatMw/4ZA7cTlI github.com/vbatts/tar-split v0.11.2/go.mod h1:vV3ZuO2yWSVsz+pfFzDG/upWH1JhjOiEaWq6kXyQ3VI= github.com/virtuald/go-ordered-json v0.0.0-20170621173500-b18e6e673d74 h1:JwtAtbp7r/7QSyGz8mKUbYJBg2+6Cd7OjM8o/GNOcVo= github.com/virtuald/go-ordered-json v0.0.0-20170621173500-b18e6e673d74/go.mod h1:RmMWU37GKR2s6pgrIEB4ixgpVCt/cf7dnJv3fuH1J1c= -github.com/xanzy/go-gitlab v0.78.0 h1:8jUHfQVAprG04Av5g0PxVd3CNsZ5hCbojIax7Hba1mE= -github.com/xanzy/go-gitlab v0.78.0/go.mod h1:DlByVTSXhPsJMYL6+cm8e8fTJjeBmhrXdC/yvkKKt6M= +github.com/xanzy/go-gitlab v0.81.0 h1:ofbhZ5ZY9AjHATWQie4qd2JfncdUmvcSA/zfQB767Dk= +github.com/xanzy/go-gitlab v0.81.0/go.mod h1:VMbY3JIWdZ/ckvHbQqkyd3iYk2aViKrNIQ23IbFMQDo= github.com/xanzy/ssh-agent v0.3.0/go.mod h1:3s9xbODqPuuhK9JV1R321M/FlMZSBvE5aY6eAcqrDh0= github.com/xanzy/ssh-agent v0.3.2/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw= github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM= @@ -743,8 +744,8 @@ golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4Iltr golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= -golang.org/x/oauth2 v0.3.0 h1:6l90koy8/LaBLmLu8jpHeHexzMwEita0zFfYlggy2F8= -golang.org/x/oauth2 v0.3.0/go.mod h1:rQrIauxkUhJ6CuwEXwymO2/eh4xz2ZWF1nBkcxS+tGk= +golang.org/x/oauth2 v0.6.0 h1:Lh8GPgSKBfWSwFvtuWOfeI3aAAnbXTSutYxJiOJFgIw= +golang.org/x/oauth2 v0.6.0/go.mod h1:ycmewcwgD4Rpr3eZJLSB4Kyyljb3qDh40vJ8STE5HKw= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -979,8 +980,8 @@ google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlba google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w= -google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.29.0 h1:44S3JjaKmLEE4YIkjzexaP+NzZsudE3Zin5Njn/pYX0= +google.golang.org/protobuf v1.29.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= From 2e1721ca854a0366baf78d29df3ef3893b1e8f5c Mon Sep 17 00:00:00 2001 From: Timo Furrer Date: Fri, 3 Mar 2023 22:30:46 +0100 Subject: [PATCH 2/2] Implement `--deploy-token-auth` in GitLab bootstrapping This change set implements support for the `--deploy-token-auth` option in the `flux bootstrap gitlab` command. That option will reconcile a GitLab Project Deploy Token to use for the authentication of the GitLab git repository. A GitLab Project Deploy Token can be used the same way as a Personal Access Token which is already supported via `--token-auth`. The difference with the GitLab Project Deploy Token is that the token is managed (created, updated, deleted) by Flux and not provided by the user. This change is transparent to the source-controller. A prerequisite for this change is the `fluxcd/go-git-providers` change here: * https://github.com/fluxcd/go-git-providers/pull/191 See related discussion here: https://github.com/fluxcd/flux2/discussions/3595 GitLab Issue here: https://gitlab.com/gitlab-org/gitlab/-/issues/392605 Signed-off-by: Timo Furrer --- cmd/flux/bootstrap_gitlab.go | 40 ++++++++++++----- pkg/bootstrap/bootstrap_provider.go | 69 +++++++++++++++++++++++++++++ 2 files changed, 97 insertions(+), 12 deletions(-) diff --git a/cmd/flux/bootstrap_gitlab.go b/cmd/flux/bootstrap_gitlab.go index e5d27229..34d877a0 100644 --- a/cmd/flux/bootstrap_gitlab.go +++ b/cmd/flux/bootstrap_gitlab.go @@ -65,7 +65,11 @@ the bootstrap command will perform an upgrade if needed.`, flux bootstrap gitlab --owner= --repository= --hostname= --token-auth # Run bootstrap for a an existing repository with a branch named main - flux bootstrap gitlab --owner= --repository= --branch=main --token-auth`, + flux bootstrap gitlab --owner= --repository= --branch=main --token-auth + + # Run bootstrap for a private repository using Deploy Token authentication + flux bootstrap gitlab --owner= --repository= --deploy-token-auth + `, RunE: bootstrapGitLabCmdRun, } @@ -77,16 +81,17 @@ const ( ) type gitlabFlags struct { - owner string - repository string - interval time.Duration - personal bool - private bool - hostname string - path flags.SafeRelativePath - teams []string - readWriteKey bool - reconcile bool + owner string + repository string + interval time.Duration + personal bool + private bool + hostname string + path flags.SafeRelativePath + teams []string + readWriteKey bool + reconcile bool + deployTokenAuth bool } var gitlabArgs gitlabFlags @@ -102,6 +107,7 @@ func init() { bootstrapGitLabCmd.Flags().Var(&gitlabArgs.path, "path", "path relative to the repository root, when specified the cluster sync will be scoped to this path") bootstrapGitLabCmd.Flags().BoolVar(&gitlabArgs.readWriteKey, "read-write-key", false, "if true, the deploy key is configured with read/write permissions") bootstrapGitLabCmd.Flags().BoolVar(&gitlabArgs.reconcile, "reconcile", false, "if true, the configured options are also reconciled if the repository already exists") + bootstrapGitLabCmd.Flags().BoolVar(&gitlabArgs.deployTokenAuth, "deploy-token-auth", false, "when enabled, a Project Deploy Token is generated and will be used instead of the SSH deploy token") bootstrapCmd.AddCommand(bootstrapGitLabCmd) } @@ -123,6 +129,10 @@ func bootstrapGitLabCmdRun(cmd *cobra.Command, args []string) error { return err } + if bootstrapArgs.tokenAuth && gitlabArgs.deployTokenAuth { + return fmt.Errorf("--token-auth and --deploy-token-auth cannot be set both.") + } + if err := bootstrapValidate(); err != nil { return err } @@ -225,6 +235,9 @@ func bootstrapGitLabCmdRun(cmd *cobra.Command, args []string) error { secretOpts.Username = "git" secretOpts.Password = glToken secretOpts.CAFile = caBundle + } else if gitlabArgs.deployTokenAuth { + // the actual deploy token will be reconciled later + secretOpts.CAFile = caBundle } else { keypair, err := sourcesecret.LoadKeyPairFromPath(bootstrapArgs.privateKeyFile, gitArgs.password) if err != nil { @@ -274,9 +287,12 @@ func bootstrapGitLabCmdRun(cmd *cobra.Command, args []string) error { if bootstrapArgs.sshHostname != "" { bootstrapOpts = append(bootstrapOpts, bootstrap.WithSSHHostname(bootstrapArgs.sshHostname)) } - if bootstrapArgs.tokenAuth { + if bootstrapArgs.tokenAuth || gitlabArgs.deployTokenAuth { bootstrapOpts = append(bootstrapOpts, bootstrap.WithSyncTransportType("https")) } + if gitlabArgs.deployTokenAuth { + bootstrapOpts = append(bootstrapOpts, bootstrap.WithDeployTokenAuth()) + } if !gitlabArgs.private { bootstrapOpts = append(bootstrapOpts, bootstrap.WithProviderRepositoryConfig("", "", "public")) } diff --git a/pkg/bootstrap/bootstrap_provider.go b/pkg/bootstrap/bootstrap_provider.go index 63600926..74aa48ef 100644 --- a/pkg/bootstrap/bootstrap_provider.go +++ b/pkg/bootstrap/bootstrap_provider.go @@ -59,6 +59,8 @@ type GitProviderBootstrapper struct { sshHostname string + useDeployTokenAuth bool + provider gitprovider.Client } @@ -184,6 +186,16 @@ func (o reconcileOption) applyGitProvider(b *GitProviderBootstrapper) { b.reconcile = true } +func WithDeployTokenAuth() GitProviderOption { + return deployTokenAuthOption(true) +} + +type deployTokenAuthOption bool + +func (o deployTokenAuthOption) applyGitProvider(b *GitProviderBootstrapper) { + b.useDeployTokenAuth = true +} + func (b *GitProviderBootstrapper) ReconcileSyncConfig(ctx context.Context, options sync.Options) error { if b.repository == nil { return errors.New("repository is required") @@ -208,6 +220,26 @@ func (b *GitProviderBootstrapper) ReconcileSyncConfig(ctx context.Context, optio return b.PlainGitBootstrapper.ReconcileSyncConfig(ctx, options) } +func (b *GitProviderBootstrapper) ReconcileSourceSecret(ctx context.Context, options sourcesecret.Options) error { + if b.repository == nil { + return errors.New("repository is required") + } + + if b.useDeployTokenAuth { + deployTokenInfo, err := b.reconcileDeployToken(ctx, options) + if err != nil { + return err + } + + if deployTokenInfo != nil { + options.Username = deployTokenInfo.Username + options.Password = deployTokenInfo.Token + } + } + + return b.PlainGitBootstrapper.ReconcileSourceSecret(ctx, options) +} + // ReconcileRepository reconciles an organization or user repository with the // GitProviderBootstrapper configuration. On success, the URL in the embedded // PlainGitBootstrapper is set to clone URL for the configured protocol. @@ -261,6 +293,32 @@ func (b *GitProviderBootstrapper) reconcileDeployKey(ctx context.Context, secret return nil } +func (b *GitProviderBootstrapper) reconcileDeployToken(ctx context.Context, options sourcesecret.Options) (*gitprovider.DeployTokenInfo, error) { + dts, err := b.repository.DeployTokens() + if err != nil { + return nil, err + } + + b.logger.Actionf("checking to reconcile deploy token for source secret") + name := deployTokenName(options.Namespace, b.branch, options.Name, options.TargetPath) + deployTokenInfo := gitprovider.DeployTokenInfo{Name: name} + + deployToken, changed, err := dts.Reconcile(ctx, deployTokenInfo) + if err != nil { + return nil, err + } + + if changed { + b.logger.Successf("configured deploy token %q for %q", deployTokenInfo.Name, b.repository.Repository().String()) + deployTokenInfo := deployToken.Get() + return &deployTokenInfo, nil + } + + b.logger.Successf("reconciled deploy token for source secret") + + return nil, nil +} + // reconcileOrgRepository reconciles a gitprovider.OrgRepository // with the GitProviderBootstrapper values, including any // gitprovider.TeamAccessInfo configurations. @@ -554,6 +612,17 @@ func deployKeyName(namespace, secretName, branch, path string) string { return name } +func deployTokenName(namespace, secretName, branch, path string) string { + var elems []string + for _, v := range []string{namespace, secretName, branch, path} { + if v == "" { + continue + } + elems = append(elems, v) + } + return strings.Join(elems, "-") +} + // setHostname is a helper to replace the hostname of the given URL. // TODO(hidde): support for this should be added in go-git-providers. func setHostname(URL, hostname string) (string, error) {