mirror of
https://github.com/rcourtman/Pulse.git
synced 2026-05-06 16:16:26 +00:00
113 lines
3 KiB
Go
113 lines
3 KiB
Go
package installtests
|
|
|
|
import (
|
|
"os"
|
|
"os/exec"
|
|
"path/filepath"
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
func TestDockerEntrypointSkipsImmutableOwnershipPaths(t *testing.T) {
|
|
repoRoot := repoRoot(t)
|
|
entrypointPath := filepath.Join(repoRoot, "docker-entrypoint.sh")
|
|
|
|
entrypoint, err := os.ReadFile(entrypointPath)
|
|
if err != nil {
|
|
t.Fatalf("read docker-entrypoint.sh: %v", err)
|
|
}
|
|
|
|
const marker = "# Only adjust permissions if running as root"
|
|
prefix, _, found := strings.Cut(string(entrypoint), marker)
|
|
if !found {
|
|
t.Fatalf("docker-entrypoint.sh missing marker %q", marker)
|
|
}
|
|
|
|
root := filepath.Join(t.TempDir(), "etc", "pulse")
|
|
secretsDir := filepath.Join(root, "secrets")
|
|
if err := os.MkdirAll(secretsDir, 0o755); err != nil {
|
|
t.Fatalf("mkdir secrets dir: %v", err)
|
|
}
|
|
|
|
immutablePaths := []string{
|
|
filepath.Join(secretsDir, "handoff.key"),
|
|
filepath.Join(root, ".cloud_handoff_key"),
|
|
}
|
|
mutablePaths := []string{
|
|
filepath.Join(root, "billing.json"),
|
|
filepath.Join(root, "system.json"),
|
|
filepath.Join(root, ".env"),
|
|
}
|
|
for _, path := range append(append([]string{}, immutablePaths...), mutablePaths...) {
|
|
if err := os.WriteFile(path, []byte("test"), 0o600); err != nil {
|
|
t.Fatalf("write fixture %s: %v", path, err)
|
|
}
|
|
}
|
|
|
|
binDir := filepath.Join(t.TempDir(), "bin")
|
|
if err := os.MkdirAll(binDir, 0o755); err != nil {
|
|
t.Fatalf("mkdir bin dir: %v", err)
|
|
}
|
|
chownLog := filepath.Join(t.TempDir(), "chown.log")
|
|
chownStub := filepath.Join(binDir, "chown")
|
|
chownScript := `#!/bin/sh
|
|
set -eu
|
|
printf '%s\n' "$*" >> "$CHOWN_LOG"
|
|
for arg in "$@"; do
|
|
case ":$PULSE_IMMUTABLE_OWNERSHIP_PATHS:" in
|
|
*:"$arg":*)
|
|
echo "immutable path should not be chowned: $arg" >&2
|
|
exit 44
|
|
;;
|
|
esac
|
|
done
|
|
exit 0
|
|
`
|
|
if err := os.WriteFile(chownStub, []byte(chownScript), 0o755); err != nil {
|
|
t.Fatalf("write chown stub: %v", err)
|
|
}
|
|
|
|
shell := prefix + `
|
|
set -eu
|
|
root="` + root + `"
|
|
export PULSE_IMMUTABLE_OWNERSHIP_PATHS="` + strings.Join(immutablePaths, ":") + `"
|
|
export CHOWN_LOG="` + chownLog + `"
|
|
export PATH="` + binDir + `:$PATH"
|
|
chown_tree_skipping_immutable_paths pulse:pulse "$root"
|
|
`
|
|
|
|
cmd := exec.Command("sh", "-c", shell)
|
|
out, err := cmd.CombinedOutput()
|
|
if err != nil {
|
|
t.Fatalf("run helper: %v\n%s", err, out)
|
|
}
|
|
|
|
logData, err := os.ReadFile(chownLog)
|
|
if err != nil {
|
|
t.Fatalf("read chown log: %v", err)
|
|
}
|
|
logText := string(logData)
|
|
for _, immutablePath := range immutablePaths {
|
|
if strings.Contains(logText, immutablePath) {
|
|
t.Fatalf("immutable path was chowned: %s\nlog:\n%s", immutablePath, logText)
|
|
}
|
|
}
|
|
for _, mutablePath := range mutablePaths {
|
|
if !strings.Contains(logText, mutablePath) {
|
|
t.Fatalf("mutable path missing from chown log: %s\nlog:\n%s", mutablePath, logText)
|
|
}
|
|
}
|
|
if !strings.Contains(logText, root) {
|
|
t.Fatalf("root directory missing from chown log:\n%s", logText)
|
|
}
|
|
}
|
|
|
|
func repoRoot(t *testing.T) string {
|
|
t.Helper()
|
|
|
|
cwd, err := os.Getwd()
|
|
if err != nil {
|
|
t.Fatalf("getwd: %v", err)
|
|
}
|
|
return filepath.Clean(filepath.Join(cwd, "..", ".."))
|
|
}
|