Problem
Removing a secret from config.yml leaves it behind, and keysafe gives no easy way to clean it up.
Steps to reproduce:
- A profile has
OLD_TOKEN (kind env), and it is loaded in a shell with keysafe load -p personal.
- Delete the
OLD_TOKEN entry from config.yml.
keysafe unload -p personal unsets every configured secret but leaves OLD_TOKEN exported in the shell.
keysafe unload -p personal OLD_TOKEN fails with "unknown secret", because names are resolved against the current config.
keysafe load -p personal rewrites <profile>.metadata from the current config (Cache::save), so keysafe loses its record that OLD_TOKEN was ever loaded.
- The cached value stays in the keychain under
keysafe.personal until the user happens to run keysafe profile clear personal.
The same happens to file secrets, whose files stay in the runtime dir, and to ssh keys, which stay in ssh-agent until they expire.
profile clear already handles this for the keychain, because it enumerates the service's accounts (#31). The other commands don't.
Where
src/app/exec.rs: UnloadCommand::execute builds its list from profile.secrets (config) only.
src/vault/cache.rs: Cache::save overwrites the metadata with the current config, so names that were removed are dropped.
- No command prunes keychain items under
keysafe.<profile> that the config no longer names.
Proposal
unload uses what was recorded, not just the config. Unset the union of configured names and names recorded in the profile metadata. Allow unload <NAME> for names that are recorded but not configured, and delete their files and agent keys too.
load prunes stale secrets. After a successful full-profile load, delete keychain items under keysafe.<profile> whose names aren't in the config, and print e.g. Pruned 2 stale secrets from personal. Also unset previously recorded names that are no longer configured, so open shells don't keep stale variables. Do this before save() replaces the metadata.
status / doctor report orphans. List keychain items, metadata entries and agent keys that the config no longer names, and suggest keysafe unload or keysafe profile clear.
Related: config validation message
A half-deleted entry (a - kind: env line left without name/path) produces:
invalid config file …/config.yml: secret at profile 'personal' index 3 missing 'name' field
It would be easier to fix with the line number and the fields that are present, e.g.
secret #4 in profile 'personal' (line 17, kind: env) is missing 'name' and 'path'.
Problem
Removing a secret from
config.ymlleaves it behind, and keysafe gives no easy way to clean it up.Steps to reproduce:
OLD_TOKEN(kindenv), and it is loaded in a shell withkeysafe load -p personal.OLD_TOKENentry fromconfig.yml.keysafe unload -p personalunsets every configured secret but leavesOLD_TOKENexported in the shell.keysafe unload -p personal OLD_TOKENfails with "unknown secret", because names are resolved against the current config.keysafe load -p personalrewrites<profile>.metadatafrom the current config (Cache::save), so keysafe loses its record thatOLD_TOKENwas ever loaded.keysafe.personaluntil the user happens to runkeysafe profile clear personal.The same happens to
filesecrets, whose files stay in the runtime dir, and tosshkeys, which stay in ssh-agent until they expire.profile clearalready handles this for the keychain, because it enumerates the service's accounts (#31). The other commands don't.Where
src/app/exec.rs:UnloadCommand::executebuilds its list fromprofile.secrets(config) only.src/vault/cache.rs:Cache::saveoverwrites the metadata with the current config, so names that were removed are dropped.keysafe.<profile>that the config no longer names.Proposal
unloaduses what was recorded, not just the config. Unset the union of configured names and names recorded in the profile metadata. Allowunload <NAME>for names that are recorded but not configured, and delete their files and agent keys too.loadprunes stale secrets. After a successful full-profile load, delete keychain items underkeysafe.<profile>whose names aren't in the config, and print e.g.Pruned 2 stale secrets from personal. Also unset previously recorded names that are no longer configured, so open shells don't keep stale variables. Do this beforesave()replaces the metadata.status/doctorreport orphans. List keychain items, metadata entries and agent keys that the config no longer names, and suggestkeysafe unloadorkeysafe profile clear.Related: config validation message
A half-deleted entry (a
- kind: envline left withoutname/path) produces:It would be easier to fix with the line number and the fields that are present, e.g.
secret #4 in profile 'personal' (line 17, kind: env) is missing 'name' and 'path'.