mirror of
https://github.com/fluxcd/flux2.git
synced 2026-02-08 00:37:27 +00:00
Merge pull request #3654 from timofurrer/gitlab-deploy-token-auth
Implement `--deploy-token-auth` in GitLab bootstrapping
This commit is contained in:
commit
2ac2a75c8c
4 changed files with 112 additions and 26 deletions
|
|
@ -65,7 +65,11 @@ the bootstrap command will perform an upgrade if needed.`,
|
|||
flux bootstrap gitlab --owner=<group> --repository=<repository name> --hostname=<domain> --token-auth
|
||||
|
||||
# Run bootstrap for a an existing repository with a branch named main
|
||||
flux bootstrap gitlab --owner=<organization> --repository=<repository name> --branch=main --token-auth`,
|
||||
flux bootstrap gitlab --owner=<organization> --repository=<repository name> --branch=main --token-auth
|
||||
|
||||
# Run bootstrap for a private repository using Deploy Token authentication
|
||||
flux bootstrap gitlab --owner=<group> --repository=<repository name> --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"))
|
||||
}
|
||||
|
|
|
|||
10
go.mod
10
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
|
||||
|
|
|
|||
19
go.sum
19
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=
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
Loading…
Reference in a new issue