check / check (push) Successful in 1m25s
Deriving keys from passphrases with scrypt, slow on purpose, took most of the test time under -race. secret.ScryptWorkFactor, when not zero, replaces age's work factor when a passphrase encrypts; the tests of internal/secret, internal/vault and internal/cli set it to 1 in TestMain, and the program never sets it. TestGetCommandOutputsToStdout checks that the built binary's passphrase unlocker names age's 18. TestRemovalAsksWithoutHoldingLock and TestFailedCommandReleasesLock time the in-memory lock all tests share, so they no longer run in parallel. TestConcurrentAddsKeepEveryVersion and TestGetCommandOutputsToStdout time nothing and now do. The script/cibuild comment no longer says tests are skipped without its memlock ulimit. Model: opus-5-5
93 lines
3.0 KiB
Go
93 lines
3.0 KiB
Go
package cli_test
|
|
|
|
import (
|
|
"bytes"
|
|
"os/exec"
|
|
"path/filepath"
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
"sneak.berlin/go/secret/internal/secret"
|
|
)
|
|
|
|
// TestGetCommandOutputsToStdout tests that 'secret get' outputs the secret
|
|
// value to stdout, not stderr
|
|
func TestGetCommandOutputsToStdout(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
// Create a temporary directory for our vault; each command is given it
|
|
// in its environment
|
|
tempDir := t.TempDir()
|
|
|
|
// Find the secret binary path
|
|
wd, err := filepath.Abs("../..")
|
|
require.NoError(t, err, "should get working directory")
|
|
|
|
secretPath := filepath.Join(wd, "secret")
|
|
testPassphrase := "test-passphrase"
|
|
|
|
// Initialize vault
|
|
//nolint:gosec // G204: test executes the freshly built secret binary
|
|
cmd := exec.CommandContext(t.Context(), secretPath, "init")
|
|
cmd.Env = []string{
|
|
secret.EnvStateDir + "=" + tempDir,
|
|
secret.EnvMnemonic + "=" + testMnemonic,
|
|
secret.EnvUnlockPassphrase + "=" + testPassphrase,
|
|
"PATH=" + "/usr/bin:/bin",
|
|
}
|
|
|
|
output, err := cmd.CombinedOutput()
|
|
require.NoError(t, err, "init should succeed: %s", string(output))
|
|
|
|
// The binary, unlike these tests, encrypts the passphrase unlocker's key
|
|
// at age's scrypt work factor, 18. age writes the work factor last on the
|
|
// second line of priv.age: "-> scrypt <salt> <work factor>".
|
|
vaultDir := filepath.Join(tempDir, "vaults.d", "default")
|
|
unlockerName := readFile(t, filepath.Join(vaultDir, "current-unlocker"))
|
|
unlockerDir := filepath.Join(vaultDir, "unlockers.d", string(unlockerName))
|
|
privAge := readFile(t, filepath.Join(unlockerDir, "priv.age"))
|
|
header := strings.SplitN(string(privAge), "\n", 3)
|
|
require.Len(t, header, 3, "priv.age should start with an age header")
|
|
assert.Regexp(t, `^-> scrypt \S+ 18$`, header[1],
|
|
"the passphrase unlocker should be encrypted at scrypt work factor 18")
|
|
|
|
// Add a secret
|
|
//nolint:gosec // G204: test executes the freshly built secret binary
|
|
cmd = exec.CommandContext(t.Context(), secretPath, "add", "test/secret")
|
|
cmd.Env = []string{
|
|
secret.EnvStateDir + "=" + tempDir,
|
|
secret.EnvMnemonic + "=" + testMnemonic,
|
|
"PATH=" + "/usr/bin:/bin",
|
|
}
|
|
cmd.Stdin = strings.NewReader("test-secret-value")
|
|
|
|
output, err = cmd.CombinedOutput()
|
|
require.NoError(t, err, "add should succeed: %s", string(output))
|
|
|
|
// Test that 'secret get' outputs to stdout, not stderr
|
|
//nolint:gosec // G204: test executes the freshly built secret binary
|
|
cmd = exec.CommandContext(t.Context(), secretPath, "get", "test/secret")
|
|
cmd.Env = []string{
|
|
secret.EnvStateDir + "=" + tempDir,
|
|
secret.EnvMnemonic + "=" + testMnemonic,
|
|
"PATH=" + "/usr/bin:/bin",
|
|
}
|
|
|
|
var stdout, stderr bytes.Buffer
|
|
|
|
cmd.Stdout = &stdout
|
|
cmd.Stderr = &stderr
|
|
|
|
err = cmd.Run()
|
|
require.NoError(t, err, "get should succeed")
|
|
|
|
// The secret value should be in stdout
|
|
assert.Equal(t, "test-secret-value", strings.TrimSpace(stdout.String()),
|
|
"secret value should be in stdout")
|
|
|
|
// Nothing should be in stderr
|
|
assert.Empty(t, stderr.String(), "stderr should be empty")
|
|
}
|