69 lines
2.2 KiB
Go
69 lines
2.2 KiB
Go
package preflight
|
|
|
|
import (
|
|
"github.com/aritmolab/thothii/tools/tht/internal/safeio"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
func TestPlanBindsInputsAndDetectsCredentialRotationWithoutPublicSecretHashes(t *testing.T) {
|
|
root, _ := filepath.EvalSymlinks(t.TempDir())
|
|
if err := safeio.ProtectPrivateDirectory(root); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
input := filepath.Join(root, "descriptor.yaml")
|
|
secret := filepath.Join(root, "credential")
|
|
for path, data := range map[string]string{input: "schemaVersion: 2\n", secret: "PRIVATE_SENTINEL"} {
|
|
if err := safeio.WriteCanonicalNewPrivateFile(path, []byte(data), 0o600); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
}
|
|
plan := Plan{SchemaVersion: 1, ValidatorProtocol: Protocol, Inputs: []string{input, secret}, WorkspaceRevision: "content-snapshot", Report: NewReport()}
|
|
output := filepath.Join(root, "plan.json")
|
|
if err := WritePlan(output, &plan); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
data, _ := os.ReadFile(output)
|
|
if strings.Contains(string(data), "PRIVATE_SENTINEL") {
|
|
t.Fatal("secret in plan")
|
|
}
|
|
if err := VerifyPlanInputs(output); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := WritePlan(output, &plan); err == nil {
|
|
t.Fatal("existing plan replaced")
|
|
}
|
|
if err := os.WriteFile(secret, []byte("rotated"), 0o600); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := VerifyPlanInputs(output); err == nil {
|
|
t.Fatal("credential rotation did not invalidate plan")
|
|
}
|
|
if err := os.WriteFile(secret, []byte("PRIVATE_SENTINEL"), 0o600); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := os.WriteFile(input, []byte("schemaVersion: 3\n"), 0o600); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := VerifyPlanInputs(output); err == nil {
|
|
t.Fatal("document change did not invalidate plan")
|
|
}
|
|
if err := os.WriteFile(input, []byte("schemaVersion: 2\n"), 0o600); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
absent := filepath.Join(root, "transport-override.yaml")
|
|
plan.AbsentInputs = []string{absent}
|
|
second := filepath.Join(root, "second-plan.json")
|
|
if err := WritePlan(second, &plan); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := safeio.WriteCanonicalNewPrivateFile(absent, []byte("services: {}\n"), 0o600); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if VerifyPlanInputs(second) == nil {
|
|
t.Fatal("newly appearing override did not invalidate plan")
|
|
}
|
|
}
|