Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4ebae029cb |
@@ -219,8 +219,6 @@ func (v *Vault) addVersion(
|
||||
name, secretDir string, value *memguard.LockedBuffer,
|
||||
previousVersion *secret.Version,
|
||||
) error {
|
||||
now := time.Now()
|
||||
|
||||
// Unlock the vault before writing anything, so that a wrong passphrase
|
||||
// or mnemonic leaves the secret as it was
|
||||
err := v.loadPreviousVersionMetadata(previousVersion)
|
||||
@@ -228,6 +226,10 @@ func (v *Vault) addVersion(
|
||||
return err
|
||||
}
|
||||
|
||||
// Taken after the unlock, which can wait for the user to type the
|
||||
// passphrase, so that the new version starts when it is created
|
||||
now := time.Now()
|
||||
|
||||
// Create the new version and save the encrypted value
|
||||
versionName, err := v.createAndSaveVersion(
|
||||
name, secretDir, value, previousVersion, &now)
|
||||
|
||||
@@ -10,6 +10,8 @@
|
||||
// version
|
||||
// - TestVaultVersionTimestamps: Tests timestamp logic (notBefore/notAfter)
|
||||
// across versions
|
||||
// - TestVaultVersionTimestampsAfterUnlock: Tests that those timestamps are
|
||||
// taken after AddSecret unlocks the vault
|
||||
// - TestVaultGetNonExistentVersion: Tests error handling for invalid versions
|
||||
// - TestUpdateVersionMetadata: Tests metadata update functionality
|
||||
//
|
||||
@@ -295,6 +297,70 @@ func TestVaultVersionTimestamps(t *testing.T) {
|
||||
assert.Nil(t, secondVersion.Metadata.NotAfter) // Current version
|
||||
}
|
||||
|
||||
// longTermKeyReadFs records when longterm.age, the last file an unlock
|
||||
// reads, was last opened.
|
||||
type longTermKeyReadFs struct {
|
||||
afero.Fs
|
||||
|
||||
readAt time.Time
|
||||
}
|
||||
|
||||
//nolint:ireturn // afero.File is the interface required by afero.Fs
|
||||
func (f *longTermKeyReadFs) Open(name string) (afero.File, error) {
|
||||
if filepath.Base(name) == "longterm.age" {
|
||||
f.readAt = time.Now()
|
||||
}
|
||||
|
||||
return f.Fs.Open(name)
|
||||
}
|
||||
|
||||
// TestVaultVersionTimestampsAfterUnlock checks that when AddSecret has to
|
||||
// unlock the vault to replace a version, the new version's notBefore and the
|
||||
// replaced version's notAfter are taken after the unlock, which can wait for
|
||||
// the user to type the passphrase.
|
||||
func TestVaultVersionTimestampsAfterUnlock(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
fs := &longTermKeyReadFs{Fs: afero.NewMemMapFs()}
|
||||
|
||||
mnemonic := memguard.NewBufferFromBytes([]byte(testMnemonic))
|
||||
defer mnemonic.Destroy()
|
||||
|
||||
passphrase := memguard.NewBufferFromBytes([]byte("test-passphrase"))
|
||||
defer passphrase.Destroy()
|
||||
|
||||
created, err := CreateVault(fs, testStateDir, "test", mnemonic, passphrase)
|
||||
require.NoError(t, err)
|
||||
|
||||
addTestSecretToVault(t, created, testSecretPath, []byte("version-1"), false)
|
||||
|
||||
// A new instance is locked; AddSecret unlocks it with the passphrase
|
||||
vault := NewVault(fs, testStateDir, "test")
|
||||
vault.SetUnlockPassphrase(passphrase)
|
||||
|
||||
addTestSecretToVault(t, vault, testSecretPath, []byte("version-2"), true)
|
||||
require.False(t, fs.readAt.IsZero(), "AddSecret did not unlock the vault")
|
||||
|
||||
ltIdentity, err := vault.GetOrDeriveLongTermKey()
|
||||
require.NoError(t, err)
|
||||
|
||||
vaultDir, _ := vault.GetDirectory()
|
||||
secretDir := filepath.Join(vaultDir, "secrets.d", "test%secret")
|
||||
|
||||
versions, err := secret.ListVersions(fs, secretDir)
|
||||
require.NoError(t, err)
|
||||
require.Len(t, versions, 2)
|
||||
|
||||
newVersion := secret.NewVersion(vault, testSecretPath, versions[0])
|
||||
require.NoError(t, newVersion.LoadMetadata(ltIdentity))
|
||||
|
||||
replacedVersion := secret.NewVersion(vault, testSecretPath, versions[1])
|
||||
require.NoError(t, replacedVersion.LoadMetadata(ltIdentity))
|
||||
|
||||
assert.False(t, newVersion.Metadata.NotBefore.Before(fs.readAt))
|
||||
assert.False(t, replacedVersion.Metadata.NotAfter.Before(fs.readAt))
|
||||
}
|
||||
|
||||
func TestVaultGetNonExistentVersion(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user