fix: bound OpenBao initialization tools #39

Merged
eding merged 1 commit from fix/openbao-initialization-timeouts into main 2026-09-09 22:46:42 +02:00

View file

@ -36,9 +36,14 @@ type operationalSecrets struct {
} }
var decryptRecovery = func(identityPath, bundlePath string) ([]byte, error) { 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() output, err := cmd.Output()
if err != nil { 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 nil, fmt.Errorf("decrypt OpenBao recovery material: %w", err)
} }
return output, nil 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) { 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 { if err := validateRecoveryRecipient(recipient, bundlePath); err != nil {
return nil, err return nil, err
} }
fmt.Fprintln(os.Stderr, "OpenBao: wait for pod")
if err := waitForPod(kubeconfig); err != nil { if err := waitForPod(kubeconfig); err != nil {
return nil, err return nil, err
} }
fmt.Fprintln(os.Stderr, "OpenBao: read status")
current, err := getStatus(kubeconfig) current, err := getStatus(kubeconfig)
if err != nil { if err != nil {
return nil, err return nil, err
} }
var material RecoveryMaterial var material RecoveryMaterial
if !current.Initialized { if !current.Initialized {
fmt.Fprintln(os.Stderr, "OpenBao: initialize")
output, err := execInPod(kubeconfig, nil, "bao", "operator", "init", "-format=json") output, err := execInPod(kubeconfig, nil, "bao", "operator", "init", "-format=json")
if err != nil { if err != nil {
return nil, fmt.Errorf("initialize OpenBao: %w", err) return nil, fmt.Errorf("initialize OpenBao: %w", err)
@ -94,12 +103,14 @@ func Initialize(kubeconfig, recipient, identityPath, bundlePath, ageKeyPath, ope
return nil, err return nil, err
} }
} else { } else {
fmt.Fprintln(os.Stderr, "OpenBao: decrypt recovery material")
material, err = ReadRecoveryMaterial(identityPath, bundlePath) material, err = ReadRecoveryMaterial(identityPath, bundlePath)
if err != nil { if err != nil {
return nil, err return nil, err
} }
} }
if current.Sealed { if current.Sealed {
fmt.Fprintln(os.Stderr, "OpenBao: unseal")
if err := unseal(kubeconfig, material); err != nil { if err := unseal(kubeconfig, material); err != nil {
return nil, err return nil, err
} }
@ -108,13 +119,16 @@ func Initialize(kubeconfig, recipient, identityPath, bundlePath, ageKeyPath, ope
if err != nil { if err != nil {
return nil, fmt.Errorf("create OpenBao Kubernetes token reviewer token: %w", err) 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 { if err := configureKubernetesAuth(kubeconfig, material.RootToken, string(bytes.TrimSpace(reviewerToken))); err != nil {
return nil, err return nil, err
} }
fmt.Fprintln(os.Stderr, "OpenBao: seed operational secrets")
secrets, err := seedOperationalSecrets(kubeconfig, material.RootToken, ageKeyPath, operationalSecretsPath) secrets, err := seedOperationalSecrets(kubeconfig, material.RootToken, ageKeyPath, operationalSecretsPath)
if err != nil { if err != nil {
return nil, err return nil, err
} }
fmt.Fprintln(os.Stderr, "OpenBao: refresh External Secrets")
if err := refreshExternalSecrets(kubeconfig); err != nil { if err := refreshExternalSecrets(kubeconfig); err != nil {
return nil, err 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) { 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) cmd.Env = append(os.Environ(), "SOPS_AGE_KEY_FILE="+ageKeyPath)
plaintext, err := cmd.Output() plaintext, err := cmd.Output()
if err != nil { 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) return nil, fmt.Errorf("decrypt operational SOPS secrets: %w", err)
} }
var document operationalSecrets var document operationalSecrets
@ -162,9 +181,14 @@ func validateRecoveryRecipient(recipient, bundlePath string) error {
return err return err
} }
defer os.Remove(probePath) 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) cmd.Stdin = bytes.NewReader(nil)
if output, err := cmd.CombinedOutput(); err != 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 fmt.Errorf("validate OpenBao recovery recipient: %w: %s", err, bytes.TrimSpace(output))
} }
return nil return nil