package vault import ( "bytes" "os" "path/filepath" "testing" "filippo.io/age" ) func TestStoreEncryptsUpdatesAndDeletesSecrets(t *testing.T) { identity, err := age.GenerateX25519Identity() if err != nil { t.Fatal(err) } path := filepath.Join(t.TempDir(), "vault", "secrets.age") if err := Initialize(path, identity); err != nil { t.Fatal(err) } store := New(path, identity) first, err := store.Set("database_password", []byte("correct horse battery staple")) if err != nil { t.Fatal(err) } record := first.Secrets["database_password"] if record.Revision == "" || string(record.Value) != "correct horse battery staple" { t.Fatalf("record = %#v", record) } encrypted, err := os.ReadFile(path) if err != nil { t.Fatal(err) } if bytes.Contains(encrypted, []byte("correct horse battery staple")) || bytes.Contains(encrypted, []byte("database_password")) { t.Fatal("encrypted file contains plaintext secret material") } unchanged, err := store.Set("database_password", []byte("correct horse battery staple")) if err != nil { t.Fatal(err) } if unchanged.Secrets["database_password"].Revision != record.Revision { t.Fatal("setting the same value changed its revision") } rotated, err := store.Set("database_password", []byte("new value")) if err != nil { t.Fatal(err) } if rotated.Secrets["database_password"].Revision == record.Revision { t.Fatal("rotating a value did not change its revision") } if _, err := store.Delete("database_password"); err != nil { t.Fatal(err) } loaded, err := store.Load() if err != nil { t.Fatal(err) } if len(loaded.Secrets) != 0 { t.Fatalf("secrets = %#v", loaded.Secrets) } } func TestStoreRejectsWrongIdentityAndInvalidValues(t *testing.T) { identity, err := age.GenerateX25519Identity() if err != nil { t.Fatal(err) } path := filepath.Join(t.TempDir(), "secrets.age") if err := Initialize(path, identity); err != nil { t.Fatal(err) } store := New(path, identity) if _, err := store.Set("../unsafe", []byte("value")); err == nil { t.Fatal("Set() accepted unsafe name") } if _, err := store.Set("empty", nil); err == nil { t.Fatal("Set() accepted empty value") } wrongIdentity, err := age.GenerateX25519Identity() if err != nil { t.Fatal(err) } if _, err := New(path, wrongIdentity).Load(); err == nil { t.Fatal("Load() succeeded with wrong identity") } } func TestOpenOrInitializeCreatesReusableEmptyVault(t *testing.T) { identity, err := age.GenerateX25519Identity() if err != nil { t.Fatal(err) } directory := t.TempDir() identityPath := filepath.Join(directory, "identity.txt") if err := os.WriteFile(identityPath, []byte(identity.String()), 0o600); err != nil { t.Fatal(err) } path := filepath.Join(directory, "state", "secrets.age") store, err := OpenOrInitialize(path, identityPath) if err != nil { t.Fatal(err) } snapshot, err := store.Load() if err != nil { t.Fatal(err) } if len(snapshot.Secrets) != 0 { t.Fatalf("initial secrets = %#v", snapshot.Secrets) } if _, err := OpenOrInitialize(path, identityPath); err != nil { t.Fatalf("OpenOrInitialize existing vault: %v", err) } }