Say the mnemonic still opens a vault its unlocker cannot (closes #47)
check / check (push) Failing after 2s
check / check (push) Failing after 2s
When the vault cannot be opened through its current unlocker, the error now ends by saying that the vault still opens with its mnemonic, and that 'secret unlocker add passphrase' run with SB_SECRET_MNEMONIC set gives it a new unlocker; only when the vault metadata records the key the mnemonic derives. 'secret encrypt' and 'secret decrypt' read the key secret through vault.GetSecret, as 'secret get' does, so they say it too. An unreadable 'current' file's error names 'secret version list' and 'secret version promote'. Causes stay wrapped. Model: opus-5-5
This commit is contained in:
+22
-2
@@ -98,7 +98,8 @@ func (v *Vault) GetOrDeriveLongTermKey() (*age.X25519Identity, error) {
|
||||
if err != nil {
|
||||
secret.Debug("Failed to get current unlocker", "error", err, "vault_name", v.Name)
|
||||
|
||||
return nil, fmt.Errorf("failed to get current unlocker: %w", err)
|
||||
return nil, v.withMnemonicAdvice(
|
||||
fmt.Errorf("failed to get current unlocker: %w", err))
|
||||
}
|
||||
|
||||
secret.DebugWith("Retrieved current unlocker for vault unlock",
|
||||
@@ -112,7 +113,7 @@ func (v *Vault) GetOrDeriveLongTermKey() (*age.X25519Identity, error) {
|
||||
// Other unlockers return their own identity, used to decrypt longterm.age.
|
||||
ltIdentity, err := v.unlockLongTermKey(unlocker)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, v.withMnemonicAdvice(err)
|
||||
}
|
||||
|
||||
secret.DebugWith("Successfully obtained long-term identity via unlocker",
|
||||
@@ -295,3 +296,22 @@ func (v *Vault) unlockLongTermKey(
|
||||
|
||||
return ltIdentity, nil
|
||||
}
|
||||
|
||||
// withMnemonicAdvice returns err, a failure to get the long-term key through
|
||||
// the current unlocker, with advice added: that the mnemonic still opens the
|
||||
// vault, and how to give it a new unlocker. The advice is added only when the
|
||||
// vault metadata records the key that the mnemonic derives; a vault created
|
||||
// without a mnemonic records none, and without its metadata the key cannot
|
||||
// be derived.
|
||||
func (v *Vault) withMnemonicAdvice(err error) error {
|
||||
vaultDir, _ := v.GetDirectory()
|
||||
|
||||
metadata, metadataErr := LoadVaultMetadata(v.fs, vaultDir)
|
||||
if metadataErr != nil || metadata.PublicKeyHash == "" {
|
||||
return err
|
||||
}
|
||||
|
||||
return fmt.Errorf("%w; the vault still opens with its mnemonic: run "+
|
||||
"'secret unlocker add passphrase' with %s set to the mnemonic "+
|
||||
"to give it a new unlocker", err, secret.EnvMnemonic)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user