Refuse a relative index_path at config load (closes #430)
check / check (push) Successful in 11m12s
check / check (push) Successful in 11m12s
A relative index_path resolved against the working directory, so a backup run from another directory started from an empty index. Validate now refuses it, naming the value, with the same wording as the file:// storage_url check. ~ is still expanded first. The check sees the final value, so a relative VAULTIK_INDEX_PATH is refused too; an explicitly empty index_path is refused as well. Model: opus-5-5
This commit is contained in:
1 parent
d8d13d1c8b
commit
75a9ef0889
4 files changed
+73
-1
No files matched your search
@@ -165,6 +165,7 @@ func TestValidateBlobSizeLimit(t *testing.T) {
|
||||
AgeRecipients: []string{testSneakAgePublicKey},
|
||||
Snapshots: map[string]SnapshotConfig{"test": {Paths: []string{"/tmp/src"}}},
|
||||
StorageURL: "file:///tmp/vaultik-test-store",
|
||||
IndexPath: "/tmp/vaultik-test-index.sqlite",
|
||||
ChunkSize: chunkSize,
|
||||
BlobSizeLimit: blobLimit,
|
||||
CompressionLevel: 3,
|
||||
@@ -510,6 +511,65 @@ func TestLoadRejectsRelativeFileURL(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// TestLoadIndexPath checks that a relative index_path fails at load, naming
|
||||
// the value. Accepted, it would resolve against the working directory, so a
|
||||
// backup run from another directory would start from an empty index. A path
|
||||
// starting with ~ is expanded and loads.
|
||||
func TestLoadIndexPath(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
home, err := os.UserHomeDir()
|
||||
if err != nil {
|
||||
t.Fatalf("home directory: %v", err)
|
||||
}
|
||||
|
||||
load := func(t *testing.T, indexPath string) (*Config, error) {
|
||||
t.Helper()
|
||||
|
||||
data := "snapshots:\n" +
|
||||
" test:\n" +
|
||||
" paths: [/tmp/vaultik-test-source]\n" +
|
||||
"storage_url: file:///tmp/vaultik-test-storage\n" +
|
||||
"index_path: " + indexPath + "\n"
|
||||
|
||||
path := filepath.Join(t.TempDir(), "config.yml")
|
||||
|
||||
err := os.WriteFile(path, []byte(data), 0o600)
|
||||
if err != nil {
|
||||
t.Fatalf("write config: %v", err)
|
||||
}
|
||||
|
||||
return Load(path)
|
||||
}
|
||||
|
||||
t.Run("relative path is rejected", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
_, err := load(t, "relative/index.sqlite")
|
||||
if !errors.Is(err, errIndexPathNotAbsolute) {
|
||||
t.Fatalf("Load() error = %v, want errIndexPathNotAbsolute", err)
|
||||
}
|
||||
|
||||
if !strings.Contains(err.Error(), `"relative/index.sqlite"`) {
|
||||
t.Errorf("error %q does not name the value", err.Error())
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("path starting with ~ is expanded", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
cfg, err := load(t, "~/vaultik/index.sqlite")
|
||||
if err != nil {
|
||||
t.Fatalf("Load() unexpected error: %v", err)
|
||||
}
|
||||
|
||||
want := filepath.Join(home, "vaultik", "index.sqlite")
|
||||
if cfg.IndexPath != want {
|
||||
t.Errorf("IndexPath = %q, want %q", cfg.IndexPath, want)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// TestValidateAgeRecipients checks that recipients are parsed at config load
|
||||
// (a bad entry fails immediately, not mid-backup) and that no invalid entry —
|
||||
// least of all a pasted secret key — is echoed in the error. An empty list
|
||||
@@ -522,6 +582,7 @@ func TestValidateAgeRecipients(t *testing.T) {
|
||||
AgeRecipients: recipients,
|
||||
Snapshots: map[string]SnapshotConfig{"test": {Paths: []string{"/tmp/src"}}},
|
||||
StorageURL: "file:///tmp/vaultik-test-store",
|
||||
IndexPath: "/tmp/vaultik-test-index.sqlite",
|
||||
ChunkSize: Size(10 * 1024 * 1024),
|
||||
BlobSizeLimit: Size(10 * 1024 * 1024 * 1024),
|
||||
CompressionLevel: 3,
|
||||
|
||||
Reference in new issue
Block a user