From b7b9068f9ca07c05b5dd69cb2de99ec95b52bbcb Mon Sep 17 00:00:00 2001 From: eding Date: Wed, 9 Sep 2026 22:44:57 +0200 Subject: [PATCH] fix: bound OpenBao initialization tools --- internal/openbao/bootstrap.go | 30 +++++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/internal/openbao/bootstrap.go b/internal/openbao/bootstrap.go index edbe209..d3ab2e7 100644 --- a/internal/openbao/bootstrap.go +++ b/internal/openbao/bootstrap.go @@ -36,9 +36,14 @@ type operationalSecrets struct { } var decryptRecovery = func(identityPath, bundlePath string) ([]byte, error) { - cmd := exec.Command("age", "-d", "-i", identityPath, bundlePath) + ctx, cancel := context.WithTimeout(context.Background(), commandTimeout) + defer cancel() + cmd := exec.CommandContext(ctx, "age", "-d", "-i", identityPath, bundlePath) output, err := cmd.Output() if err != nil { + if errors.Is(ctx.Err(), context.DeadlineExceeded) { + return nil, fmt.Errorf("decrypt OpenBao recovery material timed out after %s", commandTimeout) + } return nil, fmt.Errorf("decrypt OpenBao recovery material: %w", err) } return output, nil @@ -70,18 +75,22 @@ func EnsureRecoveryIdentity(identityPath string) (string, error) { } func Initialize(kubeconfig, recipient, identityPath, bundlePath, ageKeyPath, operationalSecretsPath string) (map[string]map[string]string, error) { + fmt.Fprintln(os.Stderr, "OpenBao: validate recovery recipient") if err := validateRecoveryRecipient(recipient, bundlePath); err != nil { return nil, err } + fmt.Fprintln(os.Stderr, "OpenBao: wait for pod") if err := waitForPod(kubeconfig); err != nil { return nil, err } + fmt.Fprintln(os.Stderr, "OpenBao: read status") current, err := getStatus(kubeconfig) if err != nil { return nil, err } var material RecoveryMaterial if !current.Initialized { + fmt.Fprintln(os.Stderr, "OpenBao: initialize") output, err := execInPod(kubeconfig, nil, "bao", "operator", "init", "-format=json") if err != nil { return nil, fmt.Errorf("initialize OpenBao: %w", err) @@ -94,12 +103,14 @@ func Initialize(kubeconfig, recipient, identityPath, bundlePath, ageKeyPath, ope return nil, err } } else { + fmt.Fprintln(os.Stderr, "OpenBao: decrypt recovery material") material, err = ReadRecoveryMaterial(identityPath, bundlePath) if err != nil { return nil, err } } if current.Sealed { + fmt.Fprintln(os.Stderr, "OpenBao: unseal") if err := unseal(kubeconfig, material); err != nil { return nil, err } @@ -108,13 +119,16 @@ func Initialize(kubeconfig, recipient, identityPath, bundlePath, ageKeyPath, ope if err != nil { return nil, fmt.Errorf("create OpenBao Kubernetes token reviewer token: %w", err) } + fmt.Fprintln(os.Stderr, "OpenBao: configure Kubernetes auth") if err := configureKubernetesAuth(kubeconfig, material.RootToken, string(bytes.TrimSpace(reviewerToken))); err != nil { return nil, err } + fmt.Fprintln(os.Stderr, "OpenBao: seed operational secrets") secrets, err := seedOperationalSecrets(kubeconfig, material.RootToken, ageKeyPath, operationalSecretsPath) if err != nil { return nil, err } + fmt.Fprintln(os.Stderr, "OpenBao: refresh External Secrets") if err := refreshExternalSecrets(kubeconfig); err != nil { return nil, err } @@ -122,10 +136,15 @@ func Initialize(kubeconfig, recipient, identityPath, bundlePath, ageKeyPath, ope } func seedOperationalSecrets(kubeconfig, rootToken, ageKeyPath, path string) (map[string]map[string]string, error) { - cmd := exec.Command("sops", "--decrypt", "--output-type", "yaml", path) + ctx, cancel := context.WithTimeout(context.Background(), commandTimeout) + defer cancel() + cmd := exec.CommandContext(ctx, "sops", "--decrypt", "--output-type", "yaml", path) cmd.Env = append(os.Environ(), "SOPS_AGE_KEY_FILE="+ageKeyPath) plaintext, err := cmd.Output() if err != nil { + if errors.Is(ctx.Err(), context.DeadlineExceeded) { + return nil, fmt.Errorf("decrypt operational SOPS secrets timed out after %s", commandTimeout) + } return nil, fmt.Errorf("decrypt operational SOPS secrets: %w", err) } var document operationalSecrets @@ -162,9 +181,14 @@ func validateRecoveryRecipient(recipient, bundlePath string) error { return err } defer os.Remove(probePath) - cmd := exec.Command("age", "-r", recipient, "-o", probePath) + ctx, cancel := context.WithTimeout(context.Background(), commandTimeout) + defer cancel() + cmd := exec.CommandContext(ctx, "age", "-r", recipient, "-o", probePath) cmd.Stdin = bytes.NewReader(nil) if output, err := cmd.CombinedOutput(); err != nil { + if errors.Is(ctx.Err(), context.DeadlineExceeded) { + return fmt.Errorf("validate OpenBao recovery recipient timed out after %s", commandTimeout) + } return fmt.Errorf("validate OpenBao recovery recipient: %w: %s", err, bytes.TrimSpace(output)) } return nil -- 2.43.7