70 lines
1.7 KiB
Go
70 lines
1.7 KiB
Go
//go:build !windows
|
|
|
|
package backup
|
|
|
|
import (
|
|
"os"
|
|
"path/filepath"
|
|
"syscall"
|
|
"testing"
|
|
)
|
|
|
|
const restoreRuntimeUID = 10001
|
|
|
|
func TestReplaceRestoreFilePreservesExistingOwner(t *testing.T) {
|
|
requireRootForRestoreOwnershipTest(t)
|
|
|
|
target := filepath.Join(t.TempDir(), "trust.json")
|
|
if err := os.WriteFile(target, []byte("before"), 0o600); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := os.Chown(target, restoreRuntimeUID, restoreRuntimeUID); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
if err := replaceRestoreFile(target, []byte("after"), 0o600); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
assertRestoreOwner(t, target, restoreRuntimeUID, restoreRuntimeUID)
|
|
}
|
|
|
|
func TestReplaceRestoreFileUsesParentOwnerForNewTarget(t *testing.T) {
|
|
requireRootForRestoreOwnershipTest(t)
|
|
|
|
parent := filepath.Join(t.TempDir(), "agent")
|
|
if err := os.Mkdir(parent, 0o700); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := os.Chown(parent, restoreRuntimeUID, restoreRuntimeUID); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
target := filepath.Join(parent, "trust.json")
|
|
|
|
if err := replaceRestoreFile(target, []byte("restored"), 0o600); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
assertRestoreOwner(t, target, restoreRuntimeUID, restoreRuntimeUID)
|
|
}
|
|
|
|
func requireRootForRestoreOwnershipTest(t *testing.T) {
|
|
t.Helper()
|
|
if os.Geteuid() != 0 {
|
|
t.Skip("numeric ownership assertions require root")
|
|
}
|
|
}
|
|
|
|
func assertRestoreOwner(t *testing.T, path string, uid, gid uint32) {
|
|
t.Helper()
|
|
info, err := os.Stat(path)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
status, ok := info.Sys().(*syscall.Stat_t)
|
|
if !ok {
|
|
t.Fatal("restored file has no Unix stat metadata")
|
|
}
|
|
if status.Uid != uid || status.Gid != gid {
|
|
t.Fatalf("restored owner = %d:%d, want %d:%d", status.Uid, status.Gid, uid, gid)
|
|
}
|
|
}
|