All checks were successful
release-tag / release-image (push) Successful in 2m43s
104 lines
3.9 KiB
Go
104 lines
3.9 KiB
Go
package sourceagent
|
|
|
|
import (
|
|
"context"
|
|
"net/url"
|
|
"path/filepath"
|
|
"testing"
|
|
)
|
|
|
|
func TestNormalizeControllerPolicySecureDefaultsAndRoots(t *testing.T) {
|
|
p, err := normalizeControllerPolicy(defaultControllerPolicy())
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if p.Enabled || p.AutonomousEnabled || !p.DryRun || p.AllowDestructive {
|
|
t.Fatalf("unsafe default controller policy: %+v", p)
|
|
}
|
|
if p.MaxConcurrentJobs != 1 || p.MaxJobDuration <= 0 {
|
|
t.Fatalf("unexpected limits: %+v", p)
|
|
}
|
|
|
|
root := t.TempDir()
|
|
p.AllowedComposeRoots = []string{root, root}
|
|
p, err = normalizeControllerPolicy(p)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if len(p.AllowedComposeRoots) != 1 || !filepath.IsAbs(p.AllowedComposeRoots[0]) {
|
|
t.Fatalf("compose roots were not normalized: %#v", p.AllowedComposeRoots)
|
|
}
|
|
}
|
|
|
|
func TestValidateControllerJobAutonomyAndDestructivePolicy(t *testing.T) {
|
|
base := ControllerPolicy{Enabled: true, AutonomousEnabled: true, AllowDestructive: false}
|
|
for _, kind := range []string{"evidence_http_probe", "health_recovery", "compute_capacity_compose", "compose_smoke_test"} {
|
|
if err := validateControllerJob(ControllerJob{Kind: kind, Autonomous: true}, base); err != nil {
|
|
t.Fatalf("%s: %v", kind, err)
|
|
}
|
|
}
|
|
if err := validateControllerJob(ControllerJob{Kind: "container_create", Autonomous: true}, base); err == nil {
|
|
t.Fatal("autonomous arbitrary container creation must be denied")
|
|
}
|
|
if err := validateControllerJob(ControllerJob{Kind: "container_remove"}, base); err == nil {
|
|
t.Fatal("destructive removal must require policy")
|
|
}
|
|
base.AllowDestructive = true
|
|
if err := validateControllerJob(ControllerJob{Kind: "container_remove"}, base); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
base.AutonomousEnabled = false
|
|
if err := validateControllerJob(ControllerJob{Kind: "evidence_http_probe", Autonomous: true}, base); err == nil {
|
|
t.Fatal("autonomous off must deny autonomous jobs")
|
|
}
|
|
}
|
|
|
|
func TestControllerImageAllowlistDoesNotUseAmbiguousPrefix(t *testing.T) {
|
|
allowed := []string{"curlimages/curl:", "registry.example/team/", "exact/tool:1"}
|
|
good := []string{"curlimages/curl:8.11.1", "registry.example/team/worker:2", "exact/tool:1"}
|
|
bad := []string{"curlimages/curl-malicious:8", "registry.example/team-malicious/worker:2", "exact/tool:10"}
|
|
for _, image := range good {
|
|
if !imageAllowed(image, allowed) {
|
|
t.Fatalf("expected allowed: %s", image)
|
|
}
|
|
}
|
|
for _, image := range bad {
|
|
if imageAllowed(image, allowed) {
|
|
t.Fatalf("unexpected allow: %s", image)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestSplitDockerImageReferenceHandlesRegistryPortsAndDigests(t *testing.T) {
|
|
cases := []struct{ in, repo, tag string }{
|
|
{"curlimages/curl:8.11.1", "curlimages/curl", "8.11.1"},
|
|
{"registry.example:5000/team/tool:2", "registry.example:5000/team/tool", "2"},
|
|
{"registry.example:5000/team/tool", "registry.example:5000/team/tool", ""},
|
|
{"tool@sha256:012345", "tool@sha256:012345", ""},
|
|
}
|
|
for _, tc := range cases {
|
|
repo, tag := splitDockerImageReference(tc.in)
|
|
if repo != tc.repo || tag != tc.tag {
|
|
t.Fatalf("%s => %s/%s, want %s/%s", tc.in, repo, tag, tc.repo, tc.tag)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestControllerJobHistoryRejectsInlineSecrets(t *testing.T) {
|
|
if err := validateControllerParametersForStorage(ControllerJob{Kind: "container_create", Parameters: map[string]any{"env": []string{"MODE=test", "API_TOKEN=secret"}}}); err == nil {
|
|
t.Fatal("expected inline secret to be rejected")
|
|
}
|
|
if err := validateControllerParametersForStorage(ControllerJob{Kind: "container_create", Parameters: map[string]any{"env": []string{"MODE=test", "LOG_LEVEL=debug"}}}); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
}
|
|
|
|
func TestEvidenceProbeBlocksLocalTargets(t *testing.T) {
|
|
for _, raw := range []string{"http://127.0.0.1/x", "http://10.1.2.3/x", "http://[::1]/x", "http://localhost/x"} {
|
|
u, _ := url.Parse(raw)
|
|
if err := validateEvidenceProbeTarget(context.Background(), u); err == nil {
|
|
t.Fatalf("expected local target rejection: %s", raw)
|
|
}
|
|
}
|
|
}
|