check / check (push) Failing after 2s
init and vault create put the mnemonic into the process environment for vault.CreateVault to read back, so every program they ran, gpg included, inherited it, and SB_SECRET_MNEMONIC and SB_UNLOCK_PASSPHRASE were read at 13 places and never unset. Each command that may need them now reads both once, in its RunE, into locked buffers on the CLI Instance, and unsets them at once. The buffers are passed down: vault.CreateVault takes the mnemonic, a Vault carries Mnemonic and UnlockPassphrase, and the PGP, keychain and Secure Enclave unlocker constructors take both. Nothing below the command reads the environment. README warns against both variables. Model: opus-5-5
69 lines
1.9 KiB
Go
69 lines
1.9 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/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 on macOS there is no mnemonic and no current unlocker, and
|
|
// on every other platform it always fails
|
|
// (https://git.eeqj.de/sneak/secret/issues/88).
|
|
//
|
|
//nolint:paralleltest // installFakeGPG uses t.Setenv
|
|
func TestCreatePGPUnlockerFailureWritesNothing(t *testing.T) {
|
|
installFakeGPG(t)
|
|
|
|
base := afero.NewMemMapFs()
|
|
vlt, err := vault.CreateVault(base, testVaultStateDir, testVaultName, 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")))
|
|
}
|