Files
claude-foundations/best-practices/secrets-management.md
Paul O'Reilly e0f8e6471c Add best-practices library, knowledge distillation pipeline settings, and first session log
- best-practices/: 11 topic files + INDEX.md extracted from cluster-bootstrap
  and custom-claude-skills (validation, k8s, helm, ansible, secrets, debugging, etc.)
- settings.yaml: pipeline config (log retention, tracked projects, max logs per run)
- CLAUDE.md: updated with best-practices loading and pipeline documentation
- memory/log/: first session log demonstrating the format

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 23:39:06 +13:00

2.0 KiB

Secrets Management

SOPS + age

SOPS with age encryption is the standard across all projects. A single .sops.yaml at the repo root defines path-based encryption rules.

File Naming

  • .sops.yaml path-based rules match specific filename patterns (e.g., **/*secret*.yaml)
  • Non-secret files must NOT contain secret in their name, or the pre-commit hook will encrypt them
  • KSOPS generator files should be named ksops-generator.yaml, not secret-generator.yaml

encrypted_regex Gotcha

When using encrypted_regex for selective field encryption (e.g., Ansible group_vars), variable names must contain a keyword that matches the regex (e.g., password|private_key|api_key|secret|token). Arbitrary key names are silently left unencrypted.

SOPS Vars Plugin

Each Ansible project needs vars_plugins_enabled = host_group_vars,community.sops.sops in ansible.cfg. Files in group_vars/ must be named after a group (e.g., all.sops.yaml), not arbitrary names.

Interactive Editor Pitfalls

  • sops <file> opens an interactive editor — fails in non-interactive sessions
  • sops -e /tmp/file fails when the temp path doesn't match .sops.yaml rules
  • Multiple sops --set calls can corrupt files — use the interactive editor for multi-field edits

Credential Handling

  • Never pass secrets via command-line arguments — visible in ps output
  • Use @file references, environment variables sourced at runtime, or stdin
  • For Ansible, use temp files with trap rm cleanup: -e "@${tmpfile}"
  • Read secrets at execution time and use them ephemerally — never cache or persist values
  • Reference the existence of a secret file in docs, never its contents

Bootstrap Secrets

Some secrets are chicken-and-egg (e.g., the age decryption key for ArgoCD's KSOPS). These must be created manually as a bootstrap step and documented clearly.

Backup Considerations

Backup plans must include encryption keys (age private keys, etc.) so that encrypted data in Git repos remains recoverable.