diff --git a/cmd/flux/bootstrap.go b/cmd/flux/bootstrap.go index 47b01127..1cef362e 100644 --- a/cmd/flux/bootstrap.go +++ b/cmd/flux/bootstrap.go @@ -57,6 +57,7 @@ var ( bootstrapArch = flags.Arch(defaults.Arch) bootstrapLogLevel = flags.LogLevel(defaults.LogLevel) bootstrapRequiredComponents = []string{"source-controller", "kustomize-controller"} + bootstrapTokenAuth bool ) const ( @@ -75,14 +76,16 @@ func init() { bootstrapCmd.PersistentFlags().Var(&bootstrapArch, "arch", bootstrapArch.Description()) bootstrapCmd.PersistentFlags().StringVar(&bootstrapBranch, "branch", bootstrapDefaultBranch, "default branch (for GitHub this must match the default branch setting for the organization)") - rootCmd.AddCommand(bootstrapCmd) bootstrapCmd.PersistentFlags().BoolVar(&bootstrapWatchAllNamespaces, "watch-all-namespaces", true, "watch for custom resources in all namespaces, if set to false it will only watch the namespace where the toolkit is installed") bootstrapCmd.PersistentFlags().BoolVar(&bootstrapNetworkPolicy, "network-policy", true, "deny ingress access to the toolkit controllers from other namespaces using network policies") + bootstrapCmd.PersistentFlags().BoolVar(&bootstrapTokenAuth, "token-auth", false, + "when enabled, the personal access token will be used instead of SSH deploy key") bootstrapCmd.PersistentFlags().Var(&bootstrapLogLevel, "log-level", bootstrapLogLevel.Description()) bootstrapCmd.PersistentFlags().StringVar(&bootstrapManifestsPath, "manifests", "", "path to the manifest directory") bootstrapCmd.PersistentFlags().MarkHidden("manifests") + rootCmd.AddCommand(bootstrapCmd) } func bootstrapValidate() error { diff --git a/cmd/flux/bootstrap_github.go b/cmd/flux/bootstrap_github.go index 5565a98a..0fd0a1aa 100644 --- a/cmd/flux/bootstrap_github.go +++ b/cmd/flux/bootstrap_github.go @@ -26,6 +26,8 @@ import ( "time" "github.com/spf13/cobra" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "github.com/fluxcd/flux2/internal/utils" "github.com/fluxcd/pkg/git" @@ -35,7 +37,7 @@ var bootstrapGitHubCmd = &cobra.Command{ Use: "github", Short: "Bootstrap toolkit components in a GitHub repository", Long: `The bootstrap github command creates the GitHub repository if it doesn't exists and -commits the toolkit components manifests to the master branch. +commits the toolkit components manifests to the main branch. Then it configures the target cluster to synchronize with the repository. If the toolkit components are present on the cluster, the bootstrap command will perform an upgrade if needed.`, @@ -54,8 +56,11 @@ the bootstrap command will perform an upgrade if needed.`, # Run bootstrap for a public repository on a personal account flux bootstrap github --owner= --repository= --private=false --personal=true - # Run bootstrap for a private repo hosted on GitHub Enterprise - flux bootstrap github --owner= --repository= --hostname= + # Run bootstrap for a private repo hosted on GitHub Enterprise using SSH auth + flux bootstrap github --owner= --repository= --hostname= --ssh-hostname= + + # Run bootstrap for a private repo hosted on GitHub Enterprise using HTTPS auth + flux bootstrap github --owner= --repository= --hostname= --token-auth # Run bootstrap for a an existing repository with a branch named main flux bootstrap github --owner= --repository= --branch=main @@ -64,15 +69,16 @@ the bootstrap command will perform an upgrade if needed.`, } var ( - ghOwner string - ghRepository string - ghInterval time.Duration - ghPersonal bool - ghPrivate bool - ghHostname string - ghPath string - ghTeams []string - ghDelete bool + ghOwner string + ghRepository string + ghInterval time.Duration + ghPersonal bool + ghPrivate bool + ghHostname string + ghPath string + ghTeams []string + ghDelete bool + ghSSHHostname string ) const ( @@ -87,6 +93,7 @@ func init() { bootstrapGitHubCmd.Flags().BoolVar(&ghPrivate, "private", true, "is private repository") bootstrapGitHubCmd.Flags().DurationVar(&ghInterval, "interval", time.Minute, "sync interval") bootstrapGitHubCmd.Flags().StringVar(&ghHostname, "hostname", git.GitHubDefaultHostname, "GitHub hostname") + bootstrapGitHubCmd.Flags().StringVar(&ghSSHHostname, "ssh-hostname", "", "GitHub SSH hostname, to be used when the SSH host differs from the HTTPS one") bootstrapGitHubCmd.Flags().StringVar(&ghPath, "path", "", "repository path, when specified the cluster sync will be scoped to this path") bootstrapGitHubCmd.Flags().BoolVar(&ghDelete, "delete", false, "delete repository (used for testing only)") @@ -110,6 +117,10 @@ func bootstrapGitHubCmdRun(cmd *cobra.Command, args []string) error { return err } + if ghSSHHostname != "" { + repository.SSHHost = ghSSHHostname + } + provider := &git.GithubProvider{ IsPrivate: ghPrivate, IsPersonal: ghPersonal, @@ -155,7 +166,7 @@ func bootstrapGitHubCmdRun(cmd *cobra.Command, args []string) error { } } - // clone repository and checkout the master branch + // clone repository and checkout the main branch if err := repository.Checkout(ctx, bootstrapBranch, tmpDir); err != nil { return err } @@ -201,28 +212,45 @@ func bootstrapGitHubCmdRun(cmd *cobra.Command, args []string) error { logger.Successf("install completed") } - // setup SSH deploy key - if shouldCreateDeployKey(ctx, kubeClient, namespace) { - logger.Actionf("configuring deploy key") - u, err := url.Parse(repository.GetSSH()) - if err != nil { - return fmt.Errorf("git URL parse failed: %w", err) + if bootstrapTokenAuth { + // setup HTTPS token auth + secret := corev1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: namespace, + Namespace: namespace, + }, + StringData: map[string]string{ + "username": "git", + "password": ghToken, + }, } - - key, err := generateDeployKey(ctx, kubeClient, u, namespace) - if err != nil { - return fmt.Errorf("generating deploy key failed: %w", err) + if err := upsertSecret(ctx, kubeClient, secret); err != nil { + return err } + } else { + // setup SSH deploy key + if shouldCreateDeployKey(ctx, kubeClient, namespace) { + logger.Actionf("configuring deploy key") + u, err := url.Parse(repository.GetSSH()) + if err != nil { + return fmt.Errorf("git URL parse failed: %w", err) + } - keyName := "flux" - if ghPath != "" { - keyName = fmt.Sprintf("flux-%s", ghPath) - } + key, err := generateDeployKey(ctx, kubeClient, u, namespace) + if err != nil { + return fmt.Errorf("generating deploy key failed: %w", err) + } - if changed, err := provider.AddDeployKey(ctx, repository, key, keyName); err != nil { - return err - } else if changed { - logger.Successf("deploy key configured") + keyName := "flux" + if ghPath != "" { + keyName = fmt.Sprintf("flux-%s", ghPath) + } + + if changed, err := provider.AddDeployKey(ctx, repository, key, keyName); err != nil { + return err + } else if changed { + logger.Successf("deploy key configured") + } } } diff --git a/cmd/flux/bootstrap_gitlab.go b/cmd/flux/bootstrap_gitlab.go index 5d504def..546d93fb 100644 --- a/cmd/flux/bootstrap_gitlab.go +++ b/cmd/flux/bootstrap_gitlab.go @@ -45,22 +45,22 @@ the bootstrap command will perform an upgrade if needed.`, export GITLAB_TOKEN= # Run bootstrap for a private repo using HTTPS token authentication - flux bootstrap gitlab --owner= --repository= + flux bootstrap gitlab --owner= --repository= --token-auth # Run bootstrap for a private repo using SSH authentication - flux bootstrap gitlab --owner= --repository= --ssh-hostname=gitlab.com + flux bootstrap gitlab --owner= --repository= # Run bootstrap for a repository path flux bootstrap gitlab --owner= --repository= --path=dev-cluster # Run bootstrap for a public repository on a personal account - flux bootstrap gitlab --owner= --repository= --private=false --personal=true + flux bootstrap gitlab --owner= --repository= --private=false --personal --token-auth # Run bootstrap for a private repo hosted on a GitLab server - flux bootstrap gitlab --owner= --repository= --hostname= + 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 + flux bootstrap gitlab --owner= --repository= --branch=main --token-auth `, RunE: bootstrapGitLabCmdRun, } @@ -83,7 +83,7 @@ func init() { bootstrapGitLabCmd.Flags().BoolVar(&glPrivate, "private", true, "is private repository") bootstrapGitLabCmd.Flags().DurationVar(&glInterval, "interval", time.Minute, "sync interval") bootstrapGitLabCmd.Flags().StringVar(&glHostname, "hostname", git.GitLabDefaultHostname, "GitLab hostname") - bootstrapGitLabCmd.Flags().StringVar(&glSSHHostname, "ssh-hostname", "", "GitLab SSH hostname, when specified a deploy key will be added to the repository") + bootstrapGitLabCmd.Flags().StringVar(&glSSHHostname, "ssh-hostname", "", "GitLab SSH hostname, to be used when the SSH host differs from the HTTPS one") bootstrapGitLabCmd.Flags().StringVar(&glPath, "path", "", "repository path, when specified the cluster sync will be scoped to this path") bootstrapCmd.AddCommand(bootstrapGitLabCmd) @@ -180,7 +180,22 @@ func bootstrapGitLabCmdRun(cmd *cobra.Command, args []string) error { repoURL := repository.GetURL() - if glSSHHostname != "" { + if bootstrapTokenAuth { + // setup HTTPS token auth + secret := corev1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: namespace, + Namespace: namespace, + }, + StringData: map[string]string{ + "username": "git", + "password": glToken, + }, + } + if err := upsertSecret(ctx, kubeClient, secret); err != nil { + return err + } + } else { // setup SSH deploy key repoURL = repository.GetSSH() if shouldCreateDeployKey(ctx, kubeClient, namespace) { @@ -206,21 +221,6 @@ func bootstrapGitLabCmdRun(cmd *cobra.Command, args []string) error { logger.Successf("deploy key configured") } } - } else { - // setup HTTPS token auth - secret := corev1.Secret{ - ObjectMeta: metav1.ObjectMeta{ - Name: namespace, - Namespace: namespace, - }, - StringData: map[string]string{ - "username": "git", - "password": glToken, - }, - } - if err := upsertSecret(ctx, kubeClient, secret); err != nil { - return err - } } // configure repo synchronization diff --git a/docs/cmd/flux_bootstrap.md b/docs/cmd/flux_bootstrap.md index 5a74161a..4d1f20b0 100644 --- a/docs/cmd/flux_bootstrap.md +++ b/docs/cmd/flux_bootstrap.md @@ -17,6 +17,7 @@ The bootstrap sub-commands bootstrap the toolkit components on the targeted Git --log-level logLevel log level, available options are: (debug, info, error) (default info) --network-policy deny ingress access to the toolkit controllers from other namespaces using network policies (default true) --registry string container registry where the toolkit images are published (default "ghcr.io/fluxcd") + --token-auth when enabled, the personal access token will be used instead of SSH deploy key -v, --version string toolkit version (default "latest") --watch-all-namespaces watch for custom resources in all namespaces, if set to false it will only watch the namespace where the toolkit is installed (default true) ``` diff --git a/docs/cmd/flux_bootstrap_github.md b/docs/cmd/flux_bootstrap_github.md index a105a216..4186515a 100644 --- a/docs/cmd/flux_bootstrap_github.md +++ b/docs/cmd/flux_bootstrap_github.md @@ -5,7 +5,7 @@ Bootstrap toolkit components in a GitHub repository ### Synopsis The bootstrap github command creates the GitHub repository if it doesn't exists and -commits the toolkit components manifests to the master branch. +commits the toolkit components manifests to the main branch. Then it configures the target cluster to synchronize with the repository. If the toolkit components are present on the cluster, the bootstrap command will perform an upgrade if needed. @@ -32,8 +32,11 @@ flux bootstrap github [flags] # Run bootstrap for a public repository on a personal account flux bootstrap github --owner= --repository= --private=false --personal=true - # Run bootstrap for a private repo hosted on GitHub Enterprise - flux bootstrap github --owner= --repository= --hostname= + # Run bootstrap for a private repo hosted on GitHub Enterprise using SSH auth + flux bootstrap github --owner= --repository= --hostname= --ssh-hostname= + + # Run bootstrap for a private repo hosted on GitHub Enterprise using HTTPS auth + flux bootstrap github --owner= --repository= --hostname= --token-auth # Run bootstrap for a an existing repository with a branch named main flux bootstrap github --owner= --repository= --branch=main @@ -43,15 +46,16 @@ flux bootstrap github [flags] ### Options ``` - -h, --help help for github - --hostname string GitHub hostname (default "github.com") - --interval duration sync interval (default 1m0s) - --owner string GitHub user or organization name - --path string repository path, when specified the cluster sync will be scoped to this path - --personal is personal repository - --private is private repository (default true) - --repository string GitHub repository name - --team stringArray GitHub team to be given maintainer access + -h, --help help for github + --hostname string GitHub hostname (default "github.com") + --interval duration sync interval (default 1m0s) + --owner string GitHub user or organization name + --path string repository path, when specified the cluster sync will be scoped to this path + --personal is personal repository + --private is private repository (default true) + --repository string GitHub repository name + --ssh-hostname string GitHub SSH hostname, to be used when the SSH host differs from the HTTPS one + --team stringArray GitHub team to be given maintainer access ``` ### Options inherited from parent commands @@ -68,6 +72,7 @@ flux bootstrap github [flags] --network-policy deny ingress access to the toolkit controllers from other namespaces using network policies (default true) --registry string container registry where the toolkit images are published (default "ghcr.io/fluxcd") --timeout duration timeout for this operation (default 5m0s) + --token-auth when enabled, the personal access token will be used instead of SSH deploy key --verbose print generated objects -v, --version string toolkit version (default "latest") --watch-all-namespaces watch for custom resources in all namespaces, if set to false it will only watch the namespace where the toolkit is installed (default true) diff --git a/docs/cmd/flux_bootstrap_gitlab.md b/docs/cmd/flux_bootstrap_gitlab.md index 131d7441..a4682511 100644 --- a/docs/cmd/flux_bootstrap_gitlab.md +++ b/docs/cmd/flux_bootstrap_gitlab.md @@ -21,22 +21,22 @@ flux bootstrap gitlab [flags] export GITLAB_TOKEN= # Run bootstrap for a private repo using HTTPS token authentication - flux bootstrap gitlab --owner= --repository= + flux bootstrap gitlab --owner= --repository= --token-auth # Run bootstrap for a private repo using SSH authentication - flux bootstrap gitlab --owner= --repository= --ssh-hostname=gitlab.com + flux bootstrap gitlab --owner= --repository= # Run bootstrap for a repository path flux bootstrap gitlab --owner= --repository= --path=dev-cluster # Run bootstrap for a public repository on a personal account - flux bootstrap gitlab --owner= --repository= --private=false --personal=true + flux bootstrap gitlab --owner= --repository= --private=false --personal --token-auth # Run bootstrap for a private repo hosted on a GitLab server - flux bootstrap gitlab --owner= --repository= --hostname= + 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 + flux bootstrap gitlab --owner= --repository= --branch=main --token-auth ``` @@ -51,7 +51,7 @@ flux bootstrap gitlab [flags] --personal is personal repository --private is private repository (default true) --repository string GitLab repository name - --ssh-hostname string GitLab SSH hostname, when specified a deploy key will be added to the repository + --ssh-hostname string GitLab SSH hostname, to be used when the SSH host differs from the HTTPS one ``` ### Options inherited from parent commands @@ -68,6 +68,7 @@ flux bootstrap gitlab [flags] --network-policy deny ingress access to the toolkit controllers from other namespaces using network policies (default true) --registry string container registry where the toolkit images are published (default "ghcr.io/fluxcd") --timeout duration timeout for this operation (default 5m0s) + --token-auth when enabled, the personal access token will be used instead of SSH deploy key --verbose print generated objects -v, --version string toolkit version (default "latest") --watch-all-namespaces watch for custom resources in all namespaces, if set to false it will only watch the namespace where the toolkit is installed (default true) diff --git a/docs/guides/installation.md b/docs/guides/installation.md index bfd34816..f8270a3a 100644 --- a/docs/guides/installation.md +++ b/docs/guides/installation.md @@ -129,6 +129,19 @@ To run the bootstrap for a repository hosted on GitHub Enterprise, you have to s ```sh flux bootstrap github \ + --hostname=my-github-enterprise.com \ + --ssh-hostname=my-github-enterprise.com \ + --owner=my-github-organization \ + --repository=my-repository \ + --branch=main \ + --path=clusters/my-cluster +``` + +If your GitHub Enterprise has SSH access disabled, you can use HTTPS and token authentication with: + +```sh +flux bootstrap github \ + --token-auth \ --hostname=my-github-enterprise.com \ --owner=my-github-organization \ --repository=my-repository \ @@ -155,6 +168,7 @@ flux bootstrap gitlab \ --repository=my-repository \ --branch=master \ --path=clusters/my-cluster \ + --token-auth \ --personal ``` @@ -189,6 +203,7 @@ To run the bootstrap for a repository hosted on GitLab on-prem or enterprise, yo ```sh flux bootstrap gitlab \ --hostname=my-gitlab.com \ + --token-auth \ --owner=my-gitlab-group \ --repository=my-repository \ --branch=master \