Secrets management
Where the ISC³ credentials live, who can read them, and where we want to take this.
Current situation
Sensitive values (BMC/iDRAC logins, PDU access, service credentials, …) live in secretzone/ at the root of this repository (ISC³) and in secretzone/calc/ for the CALC@HEI machines — the latter kept as its own subfolder so it can move out with the rest of the CALC documentation. Since 2026-08-10 the folder sits outside both Docusaurus trees, so it can never end up on the published site regardless of configuration (before that, non-publication hung on one exclude line in docusaurus.config.ts; the patterns remain as a guard should a secrets folder reappear under docs/). Access control is simply: whoever can read the private GitHub repository can read the secrets.
Limitations of the current scheme:
- No granularity — repo access is all-or-nothing; there is no way to share one credential without sharing all of them.
- Plaintext in git history — every clone carries every secret ever committed; removing a value from the file does not retract it.
- No audit trail — nobody knows who consulted what, or when.
Target scheme (proposal)
One scheme for everything, human-held and machine-consumed alike: SOPS with age keys, over the files already in secretzone/. Until 2026-08-13 the plan split human-held credentials into a Vaultwarden instance; that split is gone — one system, nothing to run, patch or back up — and the deployed instance was retired on 2026-08-16 without ever holding a shared secret (journal).
- The
secretzone/pages become YAML files whose values sops encrypts in place; structure and non-secret context (hosts, user names, quirks) stay plaintext, so the files remain diffable and reviewable in git. Doc pages reference credentials by file and key name; the encrypted files hold the values. - Each admin holds an age keypair whose private half never leaves their machine. A
.sops.yamlat the repo root maps paths to the public keys allowed to read them, so subfolders act as zones: someone can be given one zone and nothing else, provided they have read access to this (private) repository. - Onboarding is one added public-key line plus
sops updatekeys; offboarding is the removal plus rotating the values in the leaver's zones — nothing stops a former reader from decrypting revisions they already cloned. - A dedicated break-glass keypair is a recipient on every rule; its secret half exists only in the sealed offline copy (below), so the whole store is recoverable from the repo plus that one key.
- The Ansible playbooks read the files through the
community.sopscollection. Preferred overansible-vault, whose single shared passphrase has no per-user identity — one person leaving means rotating for everyone.
What this gives up compared to a password manager: reading a credential takes a laptop with the repo, sops and one's age key — no phone, no browser autofill — and there is still no audit trail of who decrypted what. Accepted 2026-08-13 as the right trade for a small admin team.
Break-glass set
The disaster recovery plan has a bootstrap problem : credentials needed to rebuild the datacenter must not live only in a service running in that datacenter. Keep a sealed offline copy (paper or encrypted USB, in a safe) of:
- BMC / iDRAC access for the core machines
- Hypervisor and storage root access
- The break-glass age secret key — with a repo clone, it decrypts the whole store. It goes on paper, generated and sealed per the break-glass paper procedure; a hardware token is not usable for this role, the page says why.
Migration checklist
- Decide: Vaultwarden on Rumba vs. institutional service — self-hosted on rumba, deployed 2026-08-04; superseded 2026-08-13 by the SOPS-only plan above, instance retired 2026-08-16
- Move
secretzone/out of the docs tree, to the repo root — 2026-08-10, HTTP exposure now structurally impossible instead of resting on anexcludeconfig line - Each admin generates an age keypair; commit
.sops.yaml(zones + the break-glass recipient) andjustrecipes for edit / extract / rekey - Convert the
secretzone/pages to encrypted YAML, rotating each value as it moves — the old values remain in git history and on every clone - Point the provisioning scripts and Ansible (
community.sops) at the encrypted files - Write and seal the break-glass set, including the age secret key on paper
- Retire the plaintext pages (keep the non-secret prose in the regular pages)