check / check (push) Failing after 2s
Keychain and Secure Enclave unlocker IDs were the creation time to the minute plus the host name, and passphrase unlocker IDs the time to the minute, so two created within one minute shared an ID, and `unlocker select`, `unlocker remove` and the selection after `unlocker add` acted on the older one. Every unlocker's ID is now its directory name, unique in its vault. `vault.ListUnlockers` returns each unlocker's metadata keyed by that name, so `unlocker list` and shell completion no longer find IDs by matching metadata. PGP unlocker IDs were `pgp-<fingerprint>`; a second PGP unlocker for one key is refused by comparing fingerprints in metadata. Model: opus-5-5
100 lines
2.5 KiB
Go
100 lines
2.5 KiB
Go
//go:build !darwin
|
|
|
|
//nolint:testpackage // white-box test asserting unexported sentinel errors
|
|
package secret
|
|
|
|
import (
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/spf13/afero"
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
func TestNewSecureEnclaveUnlocker(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
fs := afero.NewMemMapFs()
|
|
dir := "/tmp/test-se-unlocker"
|
|
metadata := UnlockerMetadata{
|
|
Type: seUnlockerType,
|
|
CreatedAt: time.Date(2026, 1, 15, 10, 30, 0, 0, time.UTC),
|
|
Flags: []string{seUnlockerType, "macos"},
|
|
}
|
|
|
|
unlocker := NewSecureEnclaveUnlocker(fs, dir, metadata)
|
|
require.NotNil(t, unlocker, "NewSecureEnclaveUnlocker should return a valid instance")
|
|
|
|
// Test GetType returns correct type
|
|
assert.Equal(t, seUnlockerType, unlocker.GetType())
|
|
|
|
// Test GetMetadata returns the metadata we passed in
|
|
assert.Equal(t, metadata, unlocker.GetMetadata())
|
|
|
|
// Test GetDirectory returns the directory we passed in
|
|
assert.Equal(t, dir, unlocker.GetDirectory())
|
|
|
|
// Test GetID returns the name of the unlocker's directory
|
|
assert.Equal(t, "test-se-unlocker", unlocker.GetID())
|
|
}
|
|
|
|
func TestSecureEnclaveUnlockerGetIdentityReturnsError(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
fs := afero.NewMemMapFs()
|
|
metadata := UnlockerMetadata{
|
|
Type: seUnlockerType,
|
|
CreatedAt: time.Now().UTC(),
|
|
}
|
|
|
|
unlocker := NewSecureEnclaveUnlocker(fs, "/tmp/test", metadata)
|
|
|
|
identity, err := unlocker.GetIdentity()
|
|
assert.Nil(t, identity)
|
|
require.Error(t, err)
|
|
require.ErrorIs(t, err, errSENotSupported)
|
|
}
|
|
|
|
func TestSecureEnclaveUnlockerRemoveReturnsError(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
fs := afero.NewMemMapFs()
|
|
metadata := UnlockerMetadata{
|
|
Type: seUnlockerType,
|
|
CreatedAt: time.Now().UTC(),
|
|
}
|
|
|
|
unlocker := NewSecureEnclaveUnlocker(fs, "/tmp/test", metadata)
|
|
|
|
err := unlocker.Remove()
|
|
require.Error(t, err)
|
|
require.ErrorIs(t, err, errSENotSupported)
|
|
}
|
|
|
|
func TestCreateSecureEnclaveUnlockerReturnsError(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
fs := afero.NewMemMapFs()
|
|
|
|
unlocker, err := CreateSecureEnclaveUnlocker(fs, "/tmp/test", nil, nil)
|
|
assert.Nil(t, unlocker)
|
|
require.Error(t, err)
|
|
require.ErrorIs(t, err, errSENotSupported)
|
|
}
|
|
|
|
func TestSecureEnclaveUnlockerImplementsInterface(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
fs := afero.NewMemMapFs()
|
|
metadata := UnlockerMetadata{
|
|
Type: seUnlockerType,
|
|
CreatedAt: time.Now().UTC(),
|
|
}
|
|
|
|
unlocker := NewSecureEnclaveUnlocker(fs, "/tmp/test", metadata)
|
|
|
|
// Verify the stub implements the Unlocker interface
|
|
var _ Unlocker = unlocker
|
|
}
|