Derive declared credentials' recipients from the rotation registry so declare writes no secrets.nix line #46
Labels
No labels
blocked
bug
decision
duplicate
enhancement
handoff
help wanted
invalid
landed?
question
ready-to-merge
stale
wontfix
bug
duplicate
enhancement
help wanted
invalid
question
wontfix
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
allod/secrets#46
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
secrets.nixcomputes the recipients of every declared credential fromrotation-registry.jsonandmachine-host-keys.json, the way it already computes them for forge keys, VM host keys and Pi credentials, soallod secret declarestops appending a hand-written recipient line and a deployment fork's own name for its hypervisor keys never has to match the tool's. Half of this is a handoff: the public template and the tool change here, and each deployment fork adopts the derivation in its own secrets repo.Primary goals:
lib/registry-recipients.nixbesidelib/pi-credential-recipients.nix, parameterised the same way over the registry,machineHostKeysand an orderedhypervisorPublicKeyslist, maps each group'scredentials[].secret_pathto the hypervisor keys plusvmKeysof every target whosekindis notnixos-host.secrets.nixmerges its result like the other four maps.checks/proves the mapping for a VM target, a host-only target and a shared group, and a sabotage fixture whose target names a machine absent frommachine-host-keys.jsonfails naming the credential and the machine.declarewrites two files, not three — theallod/toolshalf drops thesecrets.nixinsertion, its collision check and the balanced-brace check on that file, and updates its help,docs/allod-secret.mdand the public memory'sage.mdparagraph that lists three insertions.createkeeps reading recipients by evaluatingsecrets.nixfor the path, so it sees the derived set with no change.publicKeyslist evaluates to the same keys per path before and after, then thecredential-inventorycheck passes.declarederives. The criterion a reader can check: that fork'ssecrets.nixhas no top-level"secrets/<name>.age".publicKeysline left. Breaking the order fails loudly rather than badly:createrefuses withsecrets.nix in <checkout> does not declare '<path>', and no ciphertext is written to the wrong recipients.Current state and specifics
The template's
secrets.nixis already fully derived:agentTokenRecipients,forgeKeyRecipients,vmHostKeyRecipientsandpiCredentialRecipientsare merged and no top-level"secrets/<name>.age".publicKeysline remains.declareneeds one to insert after and refuses the template today withsecrets.nix: no existing publicKeys line to insert after(allod/toolscmd/allod/secret_declare.go,declareInsertSecretsLine); in a fork that has such lines it writes the template's literal[ hostKey ], which a fork binding its keys under another name cannot evaluate (allod/tools#271, closed in favour of this issue; allod/tools#275, a parser for the fork's name, closed unmerged because the line it parses should not exist).The registry carries what the derivation needs. Each group lists
credentials[].secret_pathandcredentials[].targets[].systemand.kind;declarederiveskindfrom the inventory's machine type and writesnixos-hostfor the hypervisor, which contributes novmKeyscall because the hypervisor keys already cover it. The host keys per VM aremachineHostKeys.<system>.activeand.staged, whichvmKeysinsecrets.nixalready resolves.checks/credential-inventory.nixresolves everypublicKeyslistsecrets.nixproduces (map (s: s.publicKeys) (builtins.attrValues secretsNix)), so an unresolved key in the derived map already fails there; the sabotage fixture above is for the missing-machine case, which must name what is missing rather than fail on an attribute lookup.The public memory's
age.mdstates the rule this completes under "secrets.nix owns the recipient list": a hand-written recipient list is a second source of truth that drifts silently. The declared-credential line was the last hand-written one.Fork half
A deployment fork whose
secrets.nixcarries hand-written declared lines does, in its own repo: copylib/registry-recipients.nix; add the derived map to its merge; delete each hand-written line the map now produces; pass its hypervisor key list where the template passesidentity.hostPublicKeys. The witness is derivation equality on the recipient sets: evaluatebuiltins.mapAttrs (_: s: s.publicKeys)ofsecrets.nixbefore and after and diff the two, then run the repo's checks. Its receipts live in the fork's own tracker; this issue records only that the step exists and gates the tool change.Scope
In, this repository: the lib file, the
secrets.nixmap, the fixtures and sabotage check, and the READMElibrow. Tracked elsewhere: theallod/toolschange, filed as its own issue when this one merges and landing on hosts by lock bump only once the order criterion above holds; each fork's adoption, in that fork's tracker; the shape of the hypervisor key binding inside a fork, which stays the fork's choice.All three steps have landed. The derivation: allod/secrets#47. The fork adoption: done and merged in the deployment's private secrets repo, per the owner's report; this tracker cannot read it. The tool: allod/tools#279, with the memory paragraph in allod/memory#84. The order criterion held before the tool change merged. What remains is operational and outside this issue: the host picks up the new declare at the next deploy lock bump of allod-tools.