Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f4e188c08d |
@@ -442,8 +442,8 @@ A command that changes anything locks the state directory, through its file
|
||||
`lock`, and another such command waits until the lock is released.
|
||||
`secret init`, `secret vault create`, `secret unlocker add`, and `secret add`,
|
||||
`secret import` and `secret generate secret` with `--force`, ask for the
|
||||
mnemonic or passphrase before they take the lock, so a prompt left open in one
|
||||
terminal holds up no command in another.
|
||||
mnemonic or passphrase before they take the lock, so a prompt of theirs left
|
||||
open in one terminal holds up no command in another.
|
||||
|
||||
## Security Features
|
||||
|
||||
|
||||
@@ -627,6 +627,10 @@ func TestCommandsCheckAgainOnceLocked(t *testing.T) {
|
||||
|
||||
mnemonic := testMnemonicBuffer(t)
|
||||
|
||||
otherMnemonic := memguard.NewBufferFromBytes([]byte("legal winner thank " +
|
||||
"year wave sausage worth useful legal winner thank yellow"))
|
||||
t.Cleanup(otherMnemonic.Destroy)
|
||||
|
||||
passphrase := memguard.NewBufferFromBytes([]byte(testPassphrase))
|
||||
t.Cleanup(passphrase.Destroy)
|
||||
|
||||
@@ -658,6 +662,26 @@ func TestCommandsCheckAgainOnceLocked(t *testing.T) {
|
||||
},
|
||||
vault.ErrVaultNotFound,
|
||||
},
|
||||
{
|
||||
"unlocker add, vault created again from another mnemonic",
|
||||
func(cli *Instance) error {
|
||||
cli.Mnemonic, cli.UnlockPassphrase = mnemonic, passphrase
|
||||
|
||||
return cli.UnlockersAdd("passphrase", cli.cmd)
|
||||
},
|
||||
func(fs afero.Fs) error {
|
||||
err := fs.RemoveAll(testStateDir + "/vaults.d/work")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = vault.CreateVault(fs, testStateDir, "work",
|
||||
otherMnemonic, passphrase)
|
||||
|
||||
return err
|
||||
},
|
||||
errVaultCreatedAgain,
|
||||
},
|
||||
{
|
||||
"unlocker add pgp, key added",
|
||||
func(cli *Instance) error {
|
||||
|
||||
@@ -39,6 +39,10 @@ var (
|
||||
// composes "GPG key <id> is already added as an unlocker".
|
||||
errGPGKeyAlreadyUnlocker = errors.New(
|
||||
"is already added as an unlocker")
|
||||
// errVaultCreatedAgain carries only the message tail; the caller
|
||||
// composes "vault '<name>' was removed and created again ...".
|
||||
errVaultCreatedAgain = errors.New("was removed and created again " +
|
||||
"with another key while it was being unlocked; nothing was added")
|
||||
)
|
||||
|
||||
// UnlockerInfo represents unlocker information for display
|
||||
@@ -424,8 +428,11 @@ func (cli *Instance) UnlockersAdd(unlockerType string, cmd *cobra.Command) error
|
||||
// command waits while the user answers. Once the lock is held, it fails if
|
||||
// another command has removed the vault in the meantime, since writing the
|
||||
// unlocker would create the vault's directory again, holding nothing else.
|
||||
// It also fails if the vault was removed and created again with another
|
||||
// long-term key, which the unlocker would then hold instead of the new
|
||||
// vault's own.
|
||||
func (cli *Instance) unlockThenLock(vlt *vault.Vault) (func(), error) {
|
||||
_, err := vlt.GetOrDeriveLongTermKey()
|
||||
ltIdentity, err := vlt.GetOrDeriveLongTermKey()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get long-term key: %w", err)
|
||||
}
|
||||
@@ -442,6 +449,21 @@ func (cli *Instance) unlockThenLock(vlt *vault.Vault) (func(), error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
vaultDir, _ := vlt.GetDirectory()
|
||||
|
||||
ltPubKey, err := afero.ReadFile(cli.fs, filepath.Join(vaultDir, "pub.age"))
|
||||
if err != nil {
|
||||
release()
|
||||
|
||||
return nil, fmt.Errorf("failed to read long-term public key: %w", err)
|
||||
}
|
||||
|
||||
if string(ltPubKey) != ltIdentity.Recipient().String() {
|
||||
release()
|
||||
|
||||
return nil, fmt.Errorf("vault '%s' %w", vlt.GetName(), errVaultCreatedAgain)
|
||||
}
|
||||
|
||||
return release, nil
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user