package vault_test 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" ) func TestAddSecretFailsWithMissingPublicKey(t *testing.T) { // Create in-memory filesystem fs := afero.NewMemMapFs() stateDir := "/test/state" // Create a vault directory without a public key (simulating the error condition) vaultDir := filepath.Join(stateDir, "vaults.d", "broken") require.NoError(t, fs.MkdirAll(vaultDir, secret.DirPerms)) // Create currentvault symlink currentVaultPath := filepath.Join(stateDir, "currentvault") require.NoError(t, afero.WriteFile(fs, currentVaultPath, []byte(vaultDir), secret.FilePerms)) // Create vault instance vlt := vault.NewVault(fs, stateDir, "broken") // Try to add a secret - this should fail secretName := "test-secret" value := memguard.NewBufferFromBytes([]byte("test-value")) defer value.Destroy() err := vlt.AddSecret(secretName, value, false) require.Error(t, err, "AddSecret should fail when public key is missing") assert.Contains(t, err.Error(), "failed to read long-term public key") // Verify that the secret directory was NOT created secretDir := filepath.Join(vaultDir, "secrets.d", secretName) exists, _ := afero.DirExists(fs, secretDir) assert.False(t, exists, "Secret directory should not exist after failed AddSecret") // Verify the secrets.d directory is empty or doesn't exist secretsDir := filepath.Join(vaultDir, "secrets.d") if exists, _ := afero.DirExists(fs, secretsDir); exists { entries, err := afero.ReadDir(fs, secretsDir) require.NoError(t, err) assert.Empty(t, entries, "secrets.d directory should be empty after failed AddSecret") } } func TestAddSecretCleansUpOnFailure(t *testing.T) { // Create in-memory filesystem fs := afero.NewMemMapFs() stateDir := "/test/state" // Create a vault directory with public key vaultDir := filepath.Join(stateDir, "vaults.d", "test") require.NoError(t, fs.MkdirAll(vaultDir, secret.DirPerms)) // Create a mock public key that will cause encryption to fail // by using an invalid age public key format pubKeyPath := filepath.Join(vaultDir, "pub.age") require.NoError(t, afero.WriteFile(fs, pubKeyPath, []byte("invalid-public-key"), secret.FilePerms)) // Create currentvault symlink currentVaultPath := filepath.Join(stateDir, "currentvault") require.NoError(t, afero.WriteFile(fs, currentVaultPath, []byte(vaultDir), secret.FilePerms)) // Create vault instance vlt := vault.NewVault(fs, stateDir, "test") // Try to add a secret - this should fail during encryption secretName := "test-secret" value := memguard.NewBufferFromBytes([]byte("test-value")) defer value.Destroy() err := vlt.AddSecret(secretName, value, false) require.Error(t, err, "AddSecret should fail with invalid public key") // Verify that the secret directory was NOT created secretDir := filepath.Join(vaultDir, "secrets.d", secretName) exists, _ := afero.DirExists(fs, secretDir) assert.False(t, exists, "Secret directory should not exist after failed AddSecret") }