Files
vaultik/internal/vaultik/restore_malformed_key_test.go
T
sneak 65d4bc572d
check / check (pull_request) Successful in 2m29s
Parse the age identity key once and accept every identity in it (closes #165)
Restore and verify --deep now parse the configured age secret key a
single time through a new internal helper that uses age.ParseIdentities
and hands every identity to age.Decrypt. A key file with several
identities (a whole age-keygen file) is fully accepted, so a blob
encrypted to any of its recipients decrypts, not just the first.

The helper is the first step of both commands, so a missing or
unparseable key now fails before anything is downloaded. Its error names
the configuration source (VAULTIK_AGE_SECRET_KEY or age_secret_key) and
never echoes the key value. config.extractAgeSecretKey and its silent
fallback are removed; the key is stored raw and parsed only where
decryption happens, so backup, list and prune are unaffected.

README, the restore help, and the missing-key error now show the key
read from a file with $(cat ...) rather than typed literally, keeping it
out of shell history, and say the variable may hold the whole key file.

Model: opus-4-8
2026-09-22 13:24:03 +00:00

45 lines
1.2 KiB
Go

package vaultik_test
import (
"context"
"io"
"testing"
"github.com/stretchr/testify/require"
"sneak.berlin/go/vaultik/internal/config"
"sneak.berlin/go/vaultik/internal/ui"
"sneak.berlin/go/vaultik/internal/vaultik"
)
// TestRestoreRejectsMalformedKeyBeforeDownload verifies that a malformed
// age secret key stops restore at the parse step: nothing is fetched from
// the store, and the error does not echo the key value (which is secret).
func TestRestoreRejectsMalformedKeyBeforeDownload(t *testing.T) {
t.Parallel()
const malformed = "this-is-not-a-valid-age-key"
mock := NewMockStorer()
v := &vaultik.Vaultik{
Config: &config.Config{AgeSecretKey: malformed},
Storage: mock,
Stdout: io.Discard,
Stderr: io.Discard,
UI: ui.NewWithColor(io.Discard, false),
}
v.SetContext(context.Background())
err := v.Restore(&vaultik.RestoreOptions{
SnapshotID: "any-snapshot",
TargetDir: t.TempDir(),
})
require.Error(t, err)
require.NotContains(t, err.Error(), malformed,
"error must not echo the key value")
require.Contains(t, err.Error(), "age_secret_key",
"error should name the configuration source")
require.Empty(t, mock.GetCalls(),
"a malformed key must fail before anything is fetched")
}