check / check (push) Waiting to run
CreatePGPUnlocker got the vault's long-term key from the keychain unlocker's helper, which on every platform but macOS is a stub that always fails. It now calls the vault's GetOrDeriveLongTermKey, as adding a passphrase unlocker does: from the mnemonic, checked against the vault, or else from the current unlocker. That method joins VaultInterface. The test GPG key gains an encryption subkey, and a new test adds a PGP unlocker with the long-term key from the mnemonic and from a passphrase unlocker, then reads a secret through it. Model: opus-5-5
106 lines
3.3 KiB
Go
106 lines
3.3 KiB
Go
//nolint:testpackage // white-box test of unexported internals
|
|
package cli
|
|
|
|
import (
|
|
"path/filepath"
|
|
"testing"
|
|
|
|
"git.eeqj.de/sneak/secret/internal/secret"
|
|
"git.eeqj.de/sneak/secret/internal/vault"
|
|
"github.com/awnumar/memguard"
|
|
"github.com/spf13/afero"
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
// unknownTestGPGUserID is a GPG user ID that no key in the test keyring has.
|
|
const unknownTestGPGUserID = "not-in-keyring@example.com"
|
|
|
|
// The secret TestAddPGPUnlocker stores, then reads through the new unlocker.
|
|
const (
|
|
addTestSecretName = "api-key"
|
|
addTestSecretValue = "value"
|
|
)
|
|
|
|
// TestAddPGPUnlocker adds a PGP unlocker for a throwaway GPG key to a vault
|
|
// with a passphrase unlocker, getting the vault's long-term key from the
|
|
// mnemonic or, with the mnemonic unset, from the passphrase unlocker. It
|
|
// then reads a secret with neither the mnemonic nor the passphrase set, so
|
|
// through the new unlocker, which the add selects.
|
|
func TestAddPGPUnlocker(t *testing.T) {
|
|
newTestGPGKey(t)
|
|
|
|
tests := []struct {
|
|
name string
|
|
// mnemonic is the mnemonic set while the unlocker is added.
|
|
mnemonic string
|
|
}{
|
|
{"long-term key from the mnemonic", testMnemonic},
|
|
{"long-term key from the current unlocker", ""},
|
|
}
|
|
|
|
for _, test := range tests {
|
|
t.Run(test.name, func(t *testing.T) {
|
|
t.Setenv(secret.EnvMnemonic, testMnemonic)
|
|
t.Setenv(secret.EnvUnlockPassphrase, testPassphrase)
|
|
|
|
fs := afero.NewMemMapFs()
|
|
vlt, err := vault.CreateVault(fs, listTestStateDir, listTestVaultName)
|
|
require.NoError(t, err)
|
|
|
|
err = vlt.AddSecret(addTestSecretName,
|
|
memguard.NewBufferFromBytes([]byte(addTestSecretValue)), false)
|
|
require.NoError(t, err)
|
|
|
|
_, err = vlt.CreatePassphraseUnlocker(
|
|
memguard.NewBufferFromBytes([]byte(testPassphrase)))
|
|
require.NoError(t, err)
|
|
|
|
t.Setenv(secret.EnvMnemonic, test.mnemonic)
|
|
|
|
instance, cmd := newTestInstance(fs)
|
|
cmd.Flags().String("keyid", unreadableTestGPGUserID, "")
|
|
require.NoError(t, instance.UnlockersAdd(unlockerTypePGP, cmd))
|
|
|
|
t.Setenv(secret.EnvMnemonic, "")
|
|
t.Setenv(secret.EnvUnlockPassphrase, "")
|
|
|
|
reopened := vault.NewVault(fs, listTestStateDir, listTestVaultName)
|
|
|
|
current, err := reopened.GetCurrentUnlocker()
|
|
require.NoError(t, err)
|
|
assert.Equal(t, unlockerTypePGP, current.GetType())
|
|
|
|
value, err := reopened.GetSecret(addTestSecretName)
|
|
require.NoError(t, err)
|
|
|
|
defer value.Destroy()
|
|
|
|
assert.Equal(t, addTestSecretValue, value.String())
|
|
})
|
|
}
|
|
}
|
|
|
|
// TestAddPGPUnlockerUnknownKey asserts that adding a PGP unlocker for a key
|
|
// the keyring does not hold fails at looking up the key's fingerprint and
|
|
// leaves no new unlocker directory. The error must come from the lookup: a
|
|
// lookup moved after anything is written would also come after getting the
|
|
// vault's long-term key, which fails first here: this vault's unlockers hold
|
|
// no keys.
|
|
//
|
|
//nolint:paralleltest // t.Setenv (GNUPGHOME) forbids parallel tests
|
|
func TestAddPGPUnlockerUnknownKey(t *testing.T) {
|
|
newTestGPGKey(t)
|
|
|
|
base := newListTestVault(t, 1)
|
|
instance, cmd := newTestInstance(base)
|
|
cmd.Flags().String("keyid", unknownTestGPGUserID, "")
|
|
|
|
err := instance.addPGPUnlocker(cmd)
|
|
|
|
require.ErrorContains(t, err, "failed to resolve GPG key fingerprint")
|
|
assertDirEntries(t, base,
|
|
filepath.Join(testVaultDir(listTestVaultName), listTestUnlockersDirName),
|
|
listTestUnlockerDirOne)
|
|
}
|