Replace symlinks with plain files containing relative paths
- Remove all symlink creation and resolution in favor of plain files - currentvault file now contains relative path like "vaults.d/default" - current-unlocker file now contains relative path like "unlockers.d/passphrase" - current version file now contains relative path like "versions/20231215.001" - Simplify path resolution to just read file contents and join with parent dir - Update all tests to read files instead of using os.Readlink
This commit is contained in:
@@ -332,16 +332,12 @@ func test01Initialize(t *testing.T, tempDir, testMnemonic, testPassphrase string
|
||||
defaultVaultDir := filepath.Join(vaultsDir, "default")
|
||||
verifyFileExists(t, defaultVaultDir)
|
||||
|
||||
// Check currentvault symlink - it may be absolute or relative
|
||||
currentVaultLink := filepath.Join(tempDir, "currentvault")
|
||||
target, err := os.Readlink(currentVaultLink)
|
||||
require.NoError(t, err, "should be able to read currentvault symlink")
|
||||
// Check if it points to the right place (handle both absolute and relative)
|
||||
if filepath.IsAbs(target) {
|
||||
assert.Equal(t, filepath.Join(tempDir, "vaults.d/default"), target)
|
||||
} else {
|
||||
assert.Equal(t, "vaults.d/default", target)
|
||||
}
|
||||
// Check currentvault file contains the relative path
|
||||
currentVaultFile := filepath.Join(tempDir, "currentvault")
|
||||
targetBytes, err := os.ReadFile(currentVaultFile)
|
||||
require.NoError(t, err, "should be able to read currentvault file")
|
||||
target := string(targetBytes)
|
||||
assert.Equal(t, "vaults.d/default", target, "currentvault should contain relative path")
|
||||
|
||||
// Verify vault structure
|
||||
pubKeyFile := filepath.Join(defaultVaultDir, "pub.age")
|
||||
@@ -366,22 +362,12 @@ func test01Initialize(t *testing.T, tempDir, testMnemonic, testPassphrase string
|
||||
encryptedLTPubKey := filepath.Join(passphraseUnlockerDir, "pub.age")
|
||||
verifyFileExists(t, encryptedLTPubKey)
|
||||
|
||||
// Check current-unlocker file
|
||||
// Check current-unlocker file contains the relative path
|
||||
currentUnlockerFile := filepath.Join(defaultVaultDir, "current-unlocker")
|
||||
verifyFileExists(t, currentUnlockerFile)
|
||||
|
||||
// Read the current-unlocker symlink to see what it points to
|
||||
symlinkTarget, err := os.Readlink(currentUnlockerFile)
|
||||
if err != nil {
|
||||
t.Logf("DEBUG: failed to read symlink %s: %v", currentUnlockerFile, err)
|
||||
// Fallback to reading as file if it's not a symlink
|
||||
currentUnlockerContent := readFile(t, currentUnlockerFile)
|
||||
t.Logf("DEBUG: current-unlocker file content: %q", string(currentUnlockerContent))
|
||||
assert.Contains(t, string(currentUnlockerContent), "passphrase", "current unlocker should be passphrase type")
|
||||
} else {
|
||||
t.Logf("DEBUG: current-unlocker symlink points to: %q", symlinkTarget)
|
||||
assert.Contains(t, symlinkTarget, "passphrase", "current unlocker should be passphrase type")
|
||||
}
|
||||
currentUnlockerContent := readFile(t, currentUnlockerFile)
|
||||
assert.Contains(t, string(currentUnlockerContent), "passphrase", "current unlocker should point to passphrase type")
|
||||
|
||||
// Verify vault-metadata.json in vault
|
||||
vaultMetadata := filepath.Join(defaultVaultDir, "vault-metadata.json")
|
||||
@@ -472,17 +458,12 @@ func test03CreateVault(t *testing.T, tempDir string, runSecret func(...string) (
|
||||
workVaultDir := filepath.Join(tempDir, "vaults.d", "work")
|
||||
verifyFileExists(t, workVaultDir)
|
||||
|
||||
// Check currentvault symlink was updated
|
||||
currentVaultLink := filepath.Join(tempDir, "currentvault")
|
||||
target, err := os.Readlink(currentVaultLink)
|
||||
require.NoError(t, err, "should be able to read currentvault symlink")
|
||||
|
||||
// The symlink should now point to work vault
|
||||
if filepath.IsAbs(target) {
|
||||
assert.Equal(t, filepath.Join(tempDir, "vaults.d/work"), target)
|
||||
} else {
|
||||
assert.Equal(t, "vaults.d/work", target)
|
||||
}
|
||||
// Check currentvault file was updated
|
||||
currentVaultFile := filepath.Join(tempDir, "currentvault")
|
||||
targetBytes, err := os.ReadFile(currentVaultFile)
|
||||
require.NoError(t, err, "should be able to read currentvault file")
|
||||
target := string(targetBytes)
|
||||
assert.Equal(t, "vaults.d/work", target, "currentvault should contain relative path to work")
|
||||
|
||||
// Verify work vault has basic structure
|
||||
unlockersDir := filepath.Join(workVaultDir, "unlockers.d")
|
||||
@@ -608,15 +589,16 @@ func test05AddSecret(t *testing.T, tempDir, testMnemonic string, runSecret func(
|
||||
metadataFile := filepath.Join(versionDir, "metadata.age")
|
||||
verifyFileExists(t, metadataFile)
|
||||
|
||||
// Check current symlink
|
||||
// Check current file
|
||||
currentLink := filepath.Join(secretDir, "current")
|
||||
verifyFileExists(t, currentLink)
|
||||
|
||||
// Verify symlink points to the version directory
|
||||
target, err := os.Readlink(currentLink)
|
||||
require.NoError(t, err, "should read current symlink")
|
||||
// Verify current file contains the version path
|
||||
targetBytes, err := os.ReadFile(currentLink)
|
||||
require.NoError(t, err, "should read current file")
|
||||
target := string(targetBytes)
|
||||
expectedTarget := filepath.Join("versions", versionName)
|
||||
assert.Equal(t, expectedTarget, target, "current symlink should point to version")
|
||||
assert.Equal(t, expectedTarget, target, "current file should point to version")
|
||||
|
||||
// Verify we can retrieve the secret
|
||||
getOutput, err := runSecretWithEnv(map[string]string{
|
||||
@@ -698,12 +680,13 @@ func test07AddSecretVersion(t *testing.T, tempDir, testMnemonic string, runSecre
|
||||
verifyFileExists(t, filepath.Join(versionDir, "metadata.age"))
|
||||
}
|
||||
|
||||
// Check current symlink points to new version
|
||||
// Check current file points to new version
|
||||
currentLink := filepath.Join(secretDir, "current")
|
||||
target, err := os.Readlink(currentLink)
|
||||
require.NoError(t, err, "should read current symlink")
|
||||
targetBytes, err := os.ReadFile(currentLink)
|
||||
require.NoError(t, err, "should read current file")
|
||||
target := string(targetBytes)
|
||||
expectedTarget := filepath.Join("versions", newVersion)
|
||||
assert.Equal(t, expectedTarget, target, "current symlink should point to new version")
|
||||
assert.Equal(t, expectedTarget, target, "current file should point to new version")
|
||||
|
||||
// Verify we get the new value when retrieving the secret
|
||||
getOutput, err := runSecretWithEnv(map[string]string{
|
||||
@@ -815,8 +798,9 @@ func test10PromoteVersion(t *testing.T, tempDir, testMnemonic string, runSecret
|
||||
|
||||
// Before promotion, current should point to .002 (from test 07)
|
||||
currentLink := filepath.Join(defaultVaultDir, "secrets.d", "database%password", "current")
|
||||
target, err := os.Readlink(currentLink)
|
||||
require.NoError(t, err, "should read current symlink")
|
||||
targetBytes, err := os.ReadFile(currentLink)
|
||||
require.NoError(t, err, "should read current file")
|
||||
target := string(targetBytes)
|
||||
assert.Equal(t, filepath.Join("versions", version002), target, "current should initially point to .002")
|
||||
|
||||
// Promote the old version
|
||||
@@ -828,11 +812,12 @@ func test10PromoteVersion(t *testing.T, tempDir, testMnemonic string, runSecret
|
||||
assert.Contains(t, output, "Promoted version", "should confirm promotion")
|
||||
assert.Contains(t, output, version001, "should mention the promoted version")
|
||||
|
||||
// Verify symlink was updated
|
||||
newTarget, err := os.Readlink(currentLink)
|
||||
require.NoError(t, err, "should read current symlink after promotion")
|
||||
// Verify current file was updated
|
||||
newTargetBytes, err := os.ReadFile(currentLink)
|
||||
require.NoError(t, err, "should read current file after promotion")
|
||||
newTarget := string(newTargetBytes)
|
||||
expectedTarget := filepath.Join("versions", version001)
|
||||
assert.Equal(t, expectedTarget, newTarget, "current symlink should now point to .001")
|
||||
assert.Equal(t, expectedTarget, newTarget, "current file should now point to .001")
|
||||
|
||||
// Verify we now get the old value when retrieving the secret
|
||||
getOutput, err := runSecretWithEnv(map[string]string{
|
||||
@@ -1251,27 +1236,21 @@ func test14SwitchVault(t *testing.T, tempDir string, runSecret func(...string) (
|
||||
require.NoError(t, err, "vault select default should succeed")
|
||||
|
||||
// Verify current vault is default
|
||||
currentVaultLink := filepath.Join(tempDir, "currentvault")
|
||||
target, err := os.Readlink(currentVaultLink)
|
||||
require.NoError(t, err, "should read currentvault symlink")
|
||||
if filepath.IsAbs(target) {
|
||||
assert.Contains(t, target, "vaults.d/default")
|
||||
} else {
|
||||
assert.Contains(t, target, "default")
|
||||
}
|
||||
currentVaultFile := filepath.Join(tempDir, "currentvault")
|
||||
targetBytes, err := os.ReadFile(currentVaultFile)
|
||||
require.NoError(t, err, "should read currentvault file")
|
||||
target := string(targetBytes)
|
||||
assert.Equal(t, "vaults.d/default", target, "currentvault should point to default")
|
||||
|
||||
// Switch to work vault
|
||||
_, err = runSecret("vault", "select", "work")
|
||||
require.NoError(t, err, "vault select work should succeed")
|
||||
|
||||
// Verify current vault is now work
|
||||
target, err = os.Readlink(currentVaultLink)
|
||||
require.NoError(t, err, "should read currentvault symlink")
|
||||
if filepath.IsAbs(target) {
|
||||
assert.Contains(t, target, "vaults.d/work")
|
||||
} else {
|
||||
assert.Contains(t, target, "work")
|
||||
}
|
||||
targetBytes, err = os.ReadFile(currentVaultFile)
|
||||
require.NoError(t, err, "should read currentvault file")
|
||||
target = string(targetBytes)
|
||||
assert.Equal(t, "vaults.d/work", target, "currentvault should point to work")
|
||||
|
||||
// Switch back to default
|
||||
_, err = runSecret("vault", "select", "default")
|
||||
@@ -2006,26 +1985,28 @@ func test28VaultMetadata(t *testing.T, tempDir string) {
|
||||
}
|
||||
|
||||
func test29SymlinkHandling(t *testing.T, tempDir, secretPath, testMnemonic string) {
|
||||
// Test currentvault symlink
|
||||
currentVaultLink := filepath.Join(tempDir, "currentvault")
|
||||
verifyFileExists(t, currentVaultLink)
|
||||
// Test currentvault file
|
||||
currentVaultFile := filepath.Join(tempDir, "currentvault")
|
||||
verifyFileExists(t, currentVaultFile)
|
||||
|
||||
// Read the symlink
|
||||
target, err := os.Readlink(currentVaultLink)
|
||||
require.NoError(t, err, "should read currentvault symlink")
|
||||
// Read the file
|
||||
targetBytes, err := os.ReadFile(currentVaultFile)
|
||||
require.NoError(t, err, "should read currentvault file")
|
||||
target := string(targetBytes)
|
||||
assert.Contains(t, target, "vaults.d", "should point to vaults.d directory")
|
||||
|
||||
// Test version current symlink
|
||||
// Test version current file
|
||||
defaultVaultDir := filepath.Join(tempDir, "vaults.d", "default")
|
||||
secretDir := filepath.Join(defaultVaultDir, "secrets.d", "database%password")
|
||||
currentLink := filepath.Join(secretDir, "current")
|
||||
|
||||
verifyFileExists(t, currentLink)
|
||||
target, err = os.Readlink(currentLink)
|
||||
require.NoError(t, err, "should read current version symlink")
|
||||
targetBytes, err = os.ReadFile(currentLink)
|
||||
require.NoError(t, err, "should read current version file")
|
||||
target = string(targetBytes)
|
||||
assert.Contains(t, target, "versions", "should point to versions directory")
|
||||
|
||||
// Test that symlinks update properly
|
||||
// Test that current file updates properly
|
||||
// Add new version
|
||||
cmd := exec.Command(secretPath, "add", "database/password", "--force")
|
||||
cmd.Env = []string{
|
||||
@@ -2038,11 +2019,12 @@ func test29SymlinkHandling(t *testing.T, tempDir, secretPath, testMnemonic strin
|
||||
_, err = cmd.CombinedOutput()
|
||||
require.NoError(t, err, "add new version should succeed")
|
||||
|
||||
// Check that symlink was updated
|
||||
newTarget, err := os.Readlink(currentLink)
|
||||
require.NoError(t, err, "should read updated symlink")
|
||||
assert.NotEqual(t, target, newTarget, "symlink should point to new version")
|
||||
assert.Contains(t, newTarget, "versions", "new symlink should still point to versions directory")
|
||||
// Check that current file was updated
|
||||
newTargetBytes, err := os.ReadFile(currentLink)
|
||||
require.NoError(t, err, "should read updated current file")
|
||||
newTarget := string(newTargetBytes)
|
||||
assert.NotEqual(t, target, newTarget, "current file should point to new version")
|
||||
assert.Contains(t, newTarget, "versions", "new current file should still point to versions directory")
|
||||
}
|
||||
|
||||
func test30BackupRestore(t *testing.T, tempDir, secretPath, testMnemonic string, runSecretWithEnv func(map[string]string, ...string) (string, error)) {
|
||||
@@ -2078,18 +2060,11 @@ func test30BackupRestore(t *testing.T, tempDir, secretPath, testMnemonic string,
|
||||
err = copyDir(filepath.Join(tempDir, "vaults.d"), filepath.Join(backupDir, "vaults.d"))
|
||||
require.NoError(t, err, "backup vaults should succeed")
|
||||
|
||||
// Also backup the currentvault symlink/file
|
||||
// Also backup the currentvault file
|
||||
currentVaultSrc := filepath.Join(tempDir, "currentvault")
|
||||
currentVaultDst := filepath.Join(backupDir, "currentvault")
|
||||
if target, err := os.Readlink(currentVaultSrc); err == nil {
|
||||
// It's a symlink, recreate it
|
||||
err = os.Symlink(target, currentVaultDst)
|
||||
require.NoError(t, err, "backup currentvault symlink should succeed")
|
||||
} else {
|
||||
// It's a regular file, copy it
|
||||
data := readFile(t, currentVaultSrc)
|
||||
writeFile(t, currentVaultDst, data)
|
||||
}
|
||||
data := readFile(t, currentVaultSrc)
|
||||
writeFile(t, currentVaultDst, data)
|
||||
|
||||
// Add more secrets after backup
|
||||
cmd := exec.Command(secretPath, "add", "post-backup/secret", "--force")
|
||||
@@ -2119,13 +2094,8 @@ func test30BackupRestore(t *testing.T, tempDir, secretPath, testMnemonic string,
|
||||
|
||||
// Restore currentvault
|
||||
os.Remove(currentVaultSrc)
|
||||
if target, err := os.Readlink(currentVaultDst); err == nil {
|
||||
err = os.Symlink(target, currentVaultSrc)
|
||||
require.NoError(t, err, "restore currentvault symlink should succeed")
|
||||
} else {
|
||||
data := readFile(t, currentVaultDst)
|
||||
writeFile(t, currentVaultSrc, data)
|
||||
}
|
||||
restoredData := readFile(t, currentVaultDst)
|
||||
writeFile(t, currentVaultSrc, restoredData)
|
||||
|
||||
// Verify original secrets are restored
|
||||
output, err = runSecretWithEnv(map[string]string{
|
||||
@@ -2267,18 +2237,7 @@ func copyDir(src, dst string) error {
|
||||
srcPath := filepath.Join(src, entry.Name())
|
||||
dstPath := filepath.Join(dst, entry.Name())
|
||||
|
||||
// Check if it's a symlink
|
||||
if info, err := os.Lstat(srcPath); err == nil && info.Mode()&os.ModeSymlink != 0 {
|
||||
// It's a symlink - read and recreate it
|
||||
target, err := os.Readlink(srcPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = os.Symlink(target, dstPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else if entry.IsDir() {
|
||||
if entry.IsDir() {
|
||||
err = copyDir(srcPath, dstPath)
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
Reference in New Issue
Block a user