diff --git a/cmd/flux/bootstrap_bitbucket_server.go b/cmd/flux/bootstrap_bitbucket_server.go index 7cbfce73..105da32b 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" @@ -288,6 +289,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 81a2d544..ad30e8bb 100644 --- a/cmd/flux/bootstrap_gitea.go +++ b/cmd/flux/bootstrap_gitea.go @@ -253,6 +253,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)) } @@ -266,6 +272,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 a0c5974e..6ae1cb9a 100644 --- a/cmd/flux/bootstrap_github.go +++ b/cmd/flux/bootstrap_github.go @@ -260,6 +260,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)) } @@ -273,6 +279,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 c1a16902..58e3e127 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" @@ -322,6 +323,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 {