check / check (push) Failing after 2s
vault.CreateVault takes the unlocker passphrase and writes the vault directory, its metadata, long-term public key and passphrase unlocker into a temporary directory, renames that into vaults.d once complete, and only then makes the vault current. secret init and secret vault create call it once instead of adding the unlocker afterwards, so a kill part-way leaves either no vault, whose temporary directory the next command that takes the lock deletes, or a complete one. A test records the state directory before every change the call makes and checks each state, and the command run again from it. Model: opus-5-5
105 lines
3.2 KiB
Go
105 lines
3.2 KiB
Go
package secret_test
|
|
|
|
import (
|
|
"os"
|
|
"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"
|
|
)
|
|
|
|
// The GPG key ID and fingerprint passed to CreatePGPUnlocker.
|
|
const (
|
|
testGPGKeyID = "0123456789ABCDEF"
|
|
testGPGFingerprint = "0123456789ABCDEF0123456789ABCDEF01234567"
|
|
)
|
|
|
|
// fakeGPGScript is a gpg for which `gpg --version` succeeds and anything
|
|
// else fails.
|
|
const fakeGPGScript = `#!/bin/sh
|
|
[ "$*" = --version ]
|
|
`
|
|
|
|
// installFakeGPG makes fakeGPGScript the only gpg on PATH for the test.
|
|
func installFakeGPG(t *testing.T) {
|
|
t.Helper()
|
|
|
|
dir := t.TempDir()
|
|
|
|
//nolint:gosec // G306: the script must be executable
|
|
err := os.WriteFile(filepath.Join(dir, "gpg"), []byte(fakeGPGScript), 0o700)
|
|
require.NoError(t, err)
|
|
|
|
t.Setenv("PATH", dir)
|
|
}
|
|
|
|
// TestCreatePGPUnlockerFailureWritesNothing makes CreatePGPUnlocker fail at
|
|
// getting the vault's long-term key, which used to come after part of the
|
|
// unlocker was written, and asserts that nothing is written. Getting the key
|
|
// fails because there is no mnemonic and no current unlocker.
|
|
//
|
|
//nolint:paralleltest // installFakeGPG uses t.Setenv
|
|
func TestCreatePGPUnlockerFailureWritesNothing(t *testing.T) {
|
|
installFakeGPG(t)
|
|
|
|
base := afero.NewMemMapFs()
|
|
vlt, err := vault.CreateVault(base, testVaultStateDir, testVaultName, nil, nil)
|
|
require.NoError(t, err)
|
|
|
|
fs := hookFs{Fs: base, before: func(_, path string) error {
|
|
t.Errorf("changed %s", path)
|
|
|
|
return nil
|
|
}}
|
|
|
|
_, err = secret.CreatePGPUnlocker(
|
|
fs, testVaultStateDir, testGPGKeyID, testGPGFingerprint, nil, nil)
|
|
require.Error(t, err)
|
|
|
|
vaultDir, err := vlt.GetDirectory()
|
|
require.NoError(t, err)
|
|
assert.Empty(t, dirNames(t, base, filepath.Join(vaultDir, "unlockers.d")))
|
|
}
|
|
|
|
// TestPGPUnlockerAddedTwiceKeepsFirst adds two PGP unlockers one right after
|
|
// the other, so on the same host and day, and checks that the second gets a
|
|
// directory of its own and leaves the first one's files as they were.
|
|
// CreatePGPUnlocker does not check whether the GPG key already has an
|
|
// unlocker, so the test key serves for both.
|
|
//
|
|
//nolint:paralleltest // installFakeGPG uses t.Setenv
|
|
func TestPGPUnlockerAddedTwiceKeepsFirst(t *testing.T) {
|
|
installFakeGPG(t)
|
|
|
|
original := secret.GPGEncryptFunc
|
|
|
|
t.Cleanup(func() { secret.GPGEncryptFunc = original })
|
|
|
|
// Stands in for gpg, which the test does not have: "encrypts" by copying
|
|
secret.GPGEncryptFunc = func(data *memguard.LockedBuffer, _ string) ([]byte, error) {
|
|
return []byte(data.String()), nil
|
|
}
|
|
|
|
fs := afero.NewMemMapFs()
|
|
mnemonic := testMnemonicBuffer(t)
|
|
_, err := vault.CreateVault(fs, testVaultStateDir, testVaultName, mnemonic, nil)
|
|
require.NoError(t, err)
|
|
|
|
first, err := secret.CreatePGPUnlocker(
|
|
fs, testVaultStateDir, testGPGKeyID, testGPGFingerprint, mnemonic, nil)
|
|
require.NoError(t, err)
|
|
|
|
firstFiles := dirFiles(t, fs, first.GetDirectory())
|
|
|
|
second, err := secret.CreatePGPUnlocker(
|
|
fs, testVaultStateDir, testGPGKeyID, testGPGFingerprint, mnemonic, nil)
|
|
require.NoError(t, err)
|
|
assert.NotEqual(t, first.GetDirectory(), second.GetDirectory())
|
|
assert.Equal(t, firstFiles, dirFiles(t, fs, first.GetDirectory()))
|
|
}
|