-
Notifications
You must be signed in to change notification settings - Fork 2
fix(openbao): improve install command #430
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
fc9a5f6
0b7f24e
519db8d
21496e4
7783a9a
2571c92
6044373
eb5cb4f
cce8f3a
f9b1e88
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -4,12 +4,16 @@ | |
| package cmd | ||
|
|
||
| import ( | ||
| "bufio" | ||
| "context" | ||
| "errors" | ||
| "fmt" | ||
| "io" | ||
| "os" | ||
| "os/exec" | ||
| "os/signal" | ||
| "path/filepath" | ||
| "strings" | ||
| "syscall" | ||
| "time" | ||
|
|
||
|
|
@@ -29,19 +33,30 @@ type InstallOpenBaoCmd struct { | |
| // InstallOpenBaoOpts holds the CLI flags for the OpenBao installer. | ||
| type InstallOpenBaoOpts struct { | ||
| *GlobalOptions | ||
| Namespace string | ||
| SecretsEngineName string | ||
| BaoUsername string | ||
| DRBackupPath string | ||
| Replicas int | ||
| StorageSize string | ||
| Timeout time.Duration | ||
| AgeKeyFile string | ||
| Yes bool | ||
| } | ||
|
|
||
| func (c *InstallOpenBaoCmd) RunE(_ *cobra.Command, _ []string) error { | ||
| if err := validateOpenBaoPrereqs(); err != nil { | ||
| return err | ||
| } | ||
|
|
||
| // If --age-key-file is provided, set SOPS_AGE_KEY_FILE so ResolveAgeKey | ||
| // picks it up. Otherwise, fall back to the normal auto-discovery chain. | ||
| if c.Opts.AgeKeyFile != "" { | ||
| if err := os.Setenv("SOPS_AGE_KEY_FILE", c.Opts.AgeKeyFile); err != nil { | ||
| return fmt.Errorf("setting SOPS_AGE_KEY_FILE: %w", err) | ||
|
Comment on lines
+54
to
+56
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. changes global process state permanently. We should pass the key file path through the OpenBaoInstallerConfig |
||
| } | ||
| } | ||
|
|
||
| configDir, err := os.UserConfigDir() | ||
| if err != nil { | ||
| return fmt.Errorf("determining user config directory: %w", err) | ||
|
|
@@ -54,6 +69,7 @@ func (c *InstallOpenBaoCmd) RunE(_ *cobra.Command, _ []string) error { | |
| } | ||
|
|
||
| cfg := installer.OpenBaoInstallerConfig{ | ||
| Namespace: c.Opts.Namespace, | ||
| SecretsEngineName: c.Opts.SecretsEngineName, | ||
| Username: c.Opts.BaoUsername, | ||
| DRBackupPath: c.Opts.DRBackupPath, | ||
|
|
@@ -69,6 +85,32 @@ func (c *InstallOpenBaoCmd) RunE(_ *cobra.Command, _ []string) error { | |
| return fmt.Errorf("initializing openbao installer: %w", err) | ||
| } | ||
|
|
||
| inst.ConfirmFunc = func() error { | ||
| if c.Opts.Yes { | ||
| return nil | ||
| } | ||
|
|
||
| fmt.Printf("\nWARNING: No DR backup found at: %s\n", c.Opts.DRBackupPath) | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We use log. Can we change all the fmt.Print stuff to log.Print |
||
| fmt.Println("This will perform a FRESH OpenBao initialization:") | ||
| fmt.Println(" - Existing Vault CR will be deleted") | ||
| fmt.Println(" - All OpenBao pods will be terminated") | ||
| fmt.Println(" - Persistent volume claims (data) will be deleted") | ||
| fmt.Println(" - Existing unseal keys will be removed") | ||
| fmt.Println("") | ||
| fmt.Println("If you intended to restore from a backup, verify --dr-backup-path is correct.") | ||
| fmt.Print("\nType 'yes' to continue: ") | ||
|
|
||
| reader := bufio.NewReader(os.Stdin) | ||
| input, err := reader.ReadString('\n') | ||
| if err != nil && !errors.Is(err, io.EOF) { | ||
| return fmt.Errorf("failed to read confirmation: %w", err) | ||
| } | ||
| if strings.TrimSpace(strings.ToLower(input)) != "yes" { | ||
| return fmt.Errorf("aborted: type 'yes' to continue or pass --yes") | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Confusing message. If it is aborted, how can we continue. Aborted sounds like a big error, but it is just a typo / failed confirm |
||
| } | ||
| return nil | ||
| } | ||
|
|
||
| ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM) | ||
| defer stop() | ||
|
|
||
|
|
@@ -100,12 +142,15 @@ func AddInstallOpenBaoCmd(install *cobra.Command, opts *GlobalOptions) { | |
| }, | ||
| Opts: &InstallOpenBaoOpts{GlobalOptions: opts}, | ||
| } | ||
| openbao.cmd.Flags().StringVarP(&openbao.Opts.Namespace, "namespace", "n", installer.DefaultOpenBaoNamespace, "Kubernetes namespace for OpenBao deployment") | ||
| openbao.cmd.Flags().StringVar(&openbao.Opts.SecretsEngineName, "secrets-engine", "cs-secrets-engine", "Name of the KV-v2 secrets engine to provision") | ||
| openbao.cmd.Flags().StringVar(&openbao.Opts.BaoUsername, "bao-user", "admin", "Username for the userpass auth method (ignored on restore, uses DR backup value)") | ||
| openbao.cmd.Flags().StringVar(&openbao.Opts.DRBackupPath, "dr-backup-path", "", "Path for SOPS-encrypted DR backup file (required)") | ||
| openbao.cmd.Flags().IntVar(&openbao.Opts.Replicas, "replicas", 1, "Number of OpenBao replicas (1 for single-node, odd number >= 3 for HA)") | ||
| openbao.cmd.Flags().StringVar(&openbao.Opts.StorageSize, "storage-size", "10Gi", "PVC storage size for each OpenBao replica") | ||
| openbao.cmd.Flags().DurationVar(&openbao.Opts.Timeout, "timeout", 5*time.Minute, "Timeout for waiting on initialization") | ||
| openbao.cmd.Flags().StringVarP(&openbao.Opts.AgeKeyFile, "age-key-file", "k", "", "Path to age private key file for SOPS encryption/decryption (auto-detected if not set)") | ||
| openbao.cmd.Flags().BoolVarP(&openbao.Opts.Yes, "yes", "y", false, "Auto-approve re-initialization of an existing deployment when no DR backup is found") | ||
|
|
||
| util.MarkFlagRequired(openbao.cmd, "dr-backup-path") | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,37 @@ | ||
| // Copyright (c) Codesphere Inc. | ||
| // SPDX-License-Identifier: Apache-2.0 | ||
|
|
||
| package installer | ||
|
|
||
| import ( | ||
| "context" | ||
|
|
||
| corev1 "k8s.io/api/core/v1" | ||
| ) | ||
|
|
||
| // Test helpers — exported only during `go test` so external test packages | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Looks like at least backupUnsealKeys is missing and not tested |
||
| // (package installer_test) can access unexported fields and methods. | ||
|
|
||
| func (o *OpenBaoInstaller) SetCtx(ctx context.Context) { | ||
| o.ctx = ctx | ||
| } | ||
|
|
||
| func (o *OpenBaoInstaller) SetUnsealSecret(secret *corev1.Secret) { | ||
| o.unsealSecret = secret | ||
| } | ||
|
|
||
| func (o *OpenBaoInstaller) SetPassword(password string) { | ||
| o.password = password | ||
| } | ||
|
|
||
| func (o *OpenBaoInstaller) GetDRBackupExists() bool { | ||
| return o.drBackupExists | ||
| } | ||
|
|
||
| func (o *OpenBaoInstaller) GetUnsealSecret() *corev1.Secret { | ||
| return o.unsealSecret | ||
| } | ||
|
|
||
| func (o *OpenBaoInstaller) HasExistingDeployment() (bool, error) { | ||
| return o.hasExistingDeployment() | ||
| } | ||
Uh oh!
There was an error while loading. Please reload this page.