diff --git a/cmd/flux/bootstrap_bitbucket_server.go b/cmd/flux/bootstrap_bitbucket_server.go index 3490ffbe..c595b482 100644 --- a/cmd/flux/bootstrap_bitbucket_server.go +++ b/cmd/flux/bootstrap_bitbucket_server.go @@ -24,6 +24,7 @@ import ( "github.com/fluxcd/pkg/git" "github.com/fluxcd/pkg/git/gogit" + "github.com/fluxcd/pkg/git/signature" "github.com/spf13/cobra" "github.com/fluxcd/flux2/v2/internal/flags" @@ -287,6 +288,31 @@ func bootstrapBServerCmdRun(cmd *cobra.Command, args []string) error { bootstrapOpts = append(bootstrapOpts, bootstrap.WithReconcile()) } + if bootstrapArgs.sshSigningKeyFile != "" { + pemBytes, err := os.ReadFile(bootstrapArgs.sshSigningKeyFile) + if err != nil { + return fmt.Errorf("failed to read SSH signing key file: %w", err) + } + pwd, err := effectiveSshSigningPassword() + if err != nil { + return err + } + bootstrapOpts = append(bootstrapOpts, + bootstrap.WithSSHCommitSigning(pemBytes, []byte(pwd))) + } + + if bootstrapArgs.sshSigningReusePrivateKey { + pemBytes, err := os.ReadFile(bootstrapArgs.privateKeyFile) + if err != nil { + return fmt.Errorf("failed to read transport private key for signing: %w", err) + } + if _, err := signature.NewSSHSigner(pemBytes, []byte(gitArgs.password)); err != nil { + return fmt.Errorf("invalid signing key (reused from --private-key-file): %w", err) + } + bootstrapOpts = append(bootstrapOpts, + bootstrap.WithSSHCommitSigning(pemBytes, []byte(gitArgs.password))) + } + // Setup bootstrapper with constructed configs b, err := bootstrap.NewGitProviderBootstrapper(gitClient, providerClient, kubeClient, bootstrapOpts...) if err != nil { diff --git a/cmd/flux/bootstrap_gitea.go b/cmd/flux/bootstrap_gitea.go index c6db27f8..20628f6f 100644 --- a/cmd/flux/bootstrap_gitea.go +++ b/cmd/flux/bootstrap_gitea.go @@ -252,6 +252,12 @@ func bootstrapGiteaCmdRun(cmd *cobra.Command, args []string) error { bootstrap.WithLogger(logger), bootstrap.WithGitCommitSigning(entityList, bootstrapArgs.gpgPassphrase, bootstrapArgs.gpgKeyID), } + + if bootstrapArgs.sshSigningReusePrivateKey { + return fmt.Errorf("--ssh-signing-reuse-private-key is not supported by 'bootstrap gitea'; " + + "that subcommand generates the SSH transport key in-process and has no operator-supplied key to reuse") + } + if bootstrapArgs.sshHostname != "" { bootstrapOpts = append(bootstrapOpts, bootstrap.WithSSHHostname(bootstrapArgs.sshHostname)) } @@ -265,6 +271,19 @@ func bootstrapGiteaCmdRun(cmd *cobra.Command, args []string) error { bootstrapOpts = append(bootstrapOpts, bootstrap.WithReconcile()) } + if bootstrapArgs.sshSigningKeyFile != "" { + pemBytes, err := os.ReadFile(bootstrapArgs.sshSigningKeyFile) + if err != nil { + return fmt.Errorf("failed to read SSH signing key file: %w", err) + } + pwd, err := effectiveSshSigningPassword() + if err != nil { + return err + } + bootstrapOpts = append(bootstrapOpts, + bootstrap.WithSSHCommitSigning(pemBytes, []byte(pwd))) + } + // Setup bootstrapper with constructed configs b, err := bootstrap.NewGitProviderBootstrapper(gitClient, providerClient, kubeClient, bootstrapOpts...) if err != nil { diff --git a/cmd/flux/bootstrap_github.go b/cmd/flux/bootstrap_github.go index 9c5ca2a2..e78ebc60 100644 --- a/cmd/flux/bootstrap_github.go +++ b/cmd/flux/bootstrap_github.go @@ -259,6 +259,12 @@ func bootstrapGitHubCmdRun(cmd *cobra.Command, args []string) error { bootstrap.WithLogger(logger), bootstrap.WithGitCommitSigning(entityList, bootstrapArgs.gpgPassphrase, bootstrapArgs.gpgKeyID), } + + if bootstrapArgs.sshSigningReusePrivateKey { + return fmt.Errorf("--ssh-signing-reuse-private-key is not supported by 'bootstrap github'; " + + "that subcommand generates the SSH transport key in-process and has no operator-supplied key to reuse") + } + if bootstrapArgs.sshHostname != "" { bootstrapOpts = append(bootstrapOpts, bootstrap.WithSSHHostname(bootstrapArgs.sshHostname)) } @@ -272,6 +278,19 @@ func bootstrapGitHubCmdRun(cmd *cobra.Command, args []string) error { bootstrapOpts = append(bootstrapOpts, bootstrap.WithReconcile()) } + if bootstrapArgs.sshSigningKeyFile != "" { + pemBytes, err := os.ReadFile(bootstrapArgs.sshSigningKeyFile) + if err != nil { + return fmt.Errorf("failed to read SSH signing key file: %w", err) + } + pwd, err := effectiveSshSigningPassword() + if err != nil { + return err + } + bootstrapOpts = append(bootstrapOpts, + bootstrap.WithSSHCommitSigning(pemBytes, []byte(pwd))) + } + // Setup bootstrapper with constructed configs b, err := bootstrap.NewGitProviderBootstrapper(gitClient, providerClient, kubeClient, bootstrapOpts...) if err != nil { diff --git a/cmd/flux/bootstrap_gitlab.go b/cmd/flux/bootstrap_gitlab.go index 9f4510ca..2e08bff6 100644 --- a/cmd/flux/bootstrap_gitlab.go +++ b/cmd/flux/bootstrap_gitlab.go @@ -27,6 +27,7 @@ import ( "github.com/fluxcd/go-git-providers/gitprovider" "github.com/fluxcd/pkg/git" "github.com/fluxcd/pkg/git/gogit" + "github.com/fluxcd/pkg/git/signature" "github.com/spf13/cobra" "github.com/fluxcd/flux2/v2/internal/flags" @@ -321,6 +322,31 @@ func bootstrapGitLabCmdRun(cmd *cobra.Command, args []string) error { bootstrapOpts = append(bootstrapOpts, bootstrap.WithReconcile()) } + if bootstrapArgs.sshSigningKeyFile != "" { + pemBytes, err := os.ReadFile(bootstrapArgs.sshSigningKeyFile) + if err != nil { + return fmt.Errorf("failed to read SSH signing key file: %w", err) + } + pwd, err := effectiveSshSigningPassword() + if err != nil { + return err + } + bootstrapOpts = append(bootstrapOpts, + bootstrap.WithSSHCommitSigning(pemBytes, []byte(pwd))) + } + + if bootstrapArgs.sshSigningReusePrivateKey { + pemBytes, err := os.ReadFile(bootstrapArgs.privateKeyFile) + if err != nil { + return fmt.Errorf("failed to read transport private key for signing: %w", err) + } + if _, err := signature.NewSSHSigner(pemBytes, []byte(gitArgs.password)); err != nil { + return fmt.Errorf("invalid signing key (reused from --private-key-file): %w", err) + } + bootstrapOpts = append(bootstrapOpts, + bootstrap.WithSSHCommitSigning(pemBytes, []byte(gitArgs.password))) + } + // Setup bootstrapper with constructed configs b, err := bootstrap.NewGitProviderBootstrapper(gitClient, providerClient, kubeClient, bootstrapOpts...) if err != nil {