Ctrl K
ComunidadGuías…

internal/checks/pss_test.go

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
package checks

import (
	"strings"
	"testing"

	"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
	psapi "k8s.io/pod-security-admission/api"
	"k8s.io/pod-security-admission/policy"

	"github.com/sophotechlabs/spinoza/internal/api"
)

func reportAt(t *testing.T, serverVersion string, objects ...*unstructured.Unstructured) api.CheckReport {
	t.Helper()
	lister := newLister(objects...)
	lister.facts = Facts{ServerVersion: serverVersion}
	return Run(t.Context(), lister, descriptors(), api.Metrics{}, wholeCluster(), 0)
}

func probing() *unstructured.Unstructured {
	return deployment("api", podSpec(container("app", map[string]any{"livenessProbe": probeAimedAt("10.0.0.9")})))
}

// which upstream controls the registry answers for

func TestEveryUpstreamControlIsAnsweredByExactlyOneRule(t *testing.T) {
	answered := map[policy.CheckID][]string{}
	for _, entry := range registry() {
		if entry.upstream == "" {
			continue
		}
		answered[entry.upstream] = append(answered[entry.upstream], entry.id)
	}
	for _, control := range policy.DefaultChecks() {
		if rules := answered[control.ID]; len(rules) != 1 {
			t.Fatalf("upstream control %s is answered by %v, want exactly one rule", control.ID, rules)
		}
		delete(answered, control.ID)
	}
	for id, rules := range answered {
		t.Fatalf("%v name an upstream control %s that upstream does not ship", rules, id)
	}
}

func TestARuleDecidedUpstreamCarriesTheLabelOfItsLevelFirst(t *testing.T) {
	loaded, err := upstream()
	if err != nil {
		t.Fatal(err)
	}
	found := report(t)
	for _, entry := range registry() {
		if entry.upstream == "" {
			continue
		}
		want := pssLabelOf(loaded.controls[entry.upstream].level)
		group := groupNamed(t, found, entry.id)
		if len(group.Frameworks) == 0 || group.Frameworks[0] != want {
			t.Fatalf("%s carries %v, want %s first from upstream's %s", entry.id, group.Frameworks, want, entry.upstream)
		}
		for _, label := range group.Frameworks[1:] {
			if label == pssBaseline || label == pssRestricted {
				t.Fatalf("%s still carries a hand-typed PSS label %q", entry.id, label)
			}
		}
	}
}

func TestARuleUpstreamAloneKnowsSpeaksInUpstreamsWords(t *testing.T) {
	found := report(t, deployment("api", podSpec(container("app", withSecurity(map[string]any{
		"runAsUser": int64(0),
	})))))

	detail := onlyFinding(t, found, "run-as-user-zero").Detail
	want := `runAsUser=0 (container "app" must not set runAsUser=0)`
	if detail != want {
		t.Fatalf("detail = %q, want %q", detail, want)
	}
}

// what the cluster's version changes

func TestASysctlUpstreamAllowedLaterIsJudgedByTheClusterVersion(t *testing.T) {
	workload := deployment("api", podSpecWith(map[string]any{
		"securityContext": map[string]any{
			"sysctls": []any{map[string]any{"name": "net.ipv4.tcp_rmem", "value": "4096 87380 6291456"}},
		},
	}, container("app", nil)))

	if findingCount(t, reportAt(t, "v1.31.0", workload), "unsafe-sysctls") != 1 {
		t.Fatal("net.ipv4.tcp_rmem was not reported on a 1.31 cluster, where baseline forbids it")
	}
	if findingCount(t, reportAt(t, "v1.32.0", workload), "unsafe-sysctls") != 0 {
		t.Fatal("net.ipv4.tcp_rmem was reported on a 1.32 cluster, where baseline allows it")
	}
}

func TestAnUnmaskedProcMountInsideAUserNamespaceIsAllowedFrom135(t *testing.T) {
	workload := deployment("api", podSpecWith(map[string]any{"hostUsers": false},
		container("app", withSecurity(map[string]any{"procMount": procMountUnmask}))))

	if findingCount(t, reportAt(t, "v1.34.0", workload), "proc-mount-unmasked") != 1 {
		t.Fatal("an unmasked /proc was not reported on 1.34, before upstream relaxed it for user namespaces")
	}
	if findingCount(t, reportAt(t, "v1.35.0", workload), "proc-mount-unmasked") != 0 {
		t.Fatal("an unmasked /proc inside a user namespace was reported on 1.35, where upstream allows it")
	}
	if findingCount(t, reportAt(t, "v1.35.0", workload), "proc-mount-in-user-namespace") != 1 {
		t.Fatal("on 1.35 the restricted rule did not pick up what baseline stopped reporting")
	}
	if findingCount(t, reportAt(t, "v1.34.0", workload), "proc-mount-in-user-namespace") != 0 {
		t.Fatal("the restricted rule fired on 1.34, before upstream ships it")
	}

	plain := deployment("api", podSpec(container("app", withSecurity(map[string]any{"procMount": procMountUnmask}))))
	if findingCount(t, reportAt(t, "v1.35.0", plain), "proc-mount-unmasked") != 1 {
		t.Fatal("outside a user namespace the baseline rule stopped reporting an unmasked /proc")
	}
	if findingCount(t, reportAt(t, "v1.35.0", plain), "proc-mount-in-user-namespace") != 0 {
		t.Fatal("outside a user namespace the restricted rule doubled the baseline finding")
	}
}

func TestAnSELinuxTypeUpstreamAllowedFrom131IsJudgedByTheClusterVersion(t *testing.T) {
	workload := deployment("api", podSpec(container("app", withSecurity(map[string]any{
		"seLinuxOptions": map[string]any{"type": "container_engine_t"},
	}))))

	if findingCount(t, reportAt(t, "v1.30.0", workload), "selinux-options-set") != 1 {
		t.Fatal("container_engine_t was not reported on 1.30, where upstream did not allow it yet")
	}
	if findingCount(t, reportAt(t, "v1.31.0", workload), "selinux-options-set") != 0 {
		t.Fatal("container_engine_t was reported on 1.31, where upstream allows it")
	}
}

func TestAControlUpstreamAppliesLaterStandsDownWithoutItsLabel(t *testing.T) {
	early := groupNamed(t, reportAt(t, "v1.33.0", probing()), "probe-host-set")
	if early.Skipped != "not audited: upstream applies this from v1.34 and this cluster reports v1.33" {
		t.Fatalf("skipped = %q", early.Skipped)
	}
	if len(early.Frameworks) != 0 {
		t.Fatalf("a control that does not apply yet still carries %v", early.Frameworks)
	}

	late := groupNamed(t, reportAt(t, "v1.34.0", probing()), "probe-host-set")
	if late.Skipped != "" || len(late.Findings) != 1 {
		t.Fatalf("on 1.34 skipped = %q with %d findings, want the probe host reported", late.Skipped, len(late.Findings))
	}
	if len(late.Frameworks) != 1 || late.Frameworks[0] != pssBaseline {
		t.Fatalf("on 1.34 the rule carries %v, want %s", late.Frameworks, pssBaseline)
	}
	if !strings.Contains(late.Findings[0].Detail, `"10.0.0.9"`) {
		t.Fatalf("detail = %q, want the host named", late.Findings[0].Detail)
	}
}

func TestAServerVersionNobodyCanReadIsJudgedAtUpstreamsLatest(t *testing.T) {
	if findingCount(t, reportAt(t, "unknown", probing()), "probe-host-set") != 1 {
		t.Fatal("an unreadable server version did not fall back to upstream's latest policy")
	}
}

// what upstream cannot decide

func TestAPodTemplateUpstreamCannotReadIsJudgedByHand(t *testing.T) {
	found := report(t, deployment("api", podSpec(container("app", withSecurity(map[string]any{
		"privileged": true,
		"runAsUser":  "zero",
	})))))

	if onlyFinding(t, found, "privileged-containers").Detail != "securityContext.privileged is true" {
		t.Fatal("a template upstream could not decode lost the hand-written finding")
	}
}

func TestAnUpstreamPolicyThatWillNotLoadStandsTheBackedRulesDown(t *testing.T) {
	broken := policy.DefaultChecks()
	broken = append(broken, broken[0])
	_, err := upstreamFrom(broken)
	if err == nil {
		t.Fatal("a policy with a duplicated control loaded")
	}
	sc := scan{upstream: &upstreamScan{version: psapi.LatestVersion(), err: err, pods: map[string]upstreamPod{}}}

	backed := check{upstream: "privileged"}
	if down := backed.standsDown(sc); !strings.HasPrefix(down, upstreamUnloaded) {
		t.Fatalf("a backed rule stood down with %q", down)
	}
	enforced := check{enforced: true, find: enforcedLevelRejects}
	if down := enforced.standsDown(sc); !strings.HasPrefix(down, upstreamUnloaded) {
		t.Fatalf("the enforced-level rule stood down with %q", down)
	}
	if verdicts := enforced.findings(sc); len(verdicts) != 0 {
		t.Fatalf("an unloaded policy still produced %d findings", len(verdicts))
	}
}

func TestAControlUpstreamDoesNotShipStandsDown(t *testing.T) {
	sc := scan{upstream: newUpstreamScan("v1.36.0")}
	want := "not audited: upstream has no control named no-such-control"
	if down := (check{upstream: "no-such-control"}).standsDown(sc); down != want {
		t.Fatalf("stood down with %q, want %q", down, want)
	}
}

// the level a namespace enforces

func TestTheEnforcedLevelHonoursTheVersionLabel(t *testing.T) {
	pinnedEarly := namespaceObj(testNamespace, map[string]any{
		enforceLabel: profileBaseline, psapi.EnforceVersionLabel: "v1.33",
	})
	if findingCount(t, report(t, pinnedEarly, probing()), "pod-security-would-reject") != 0 {
		t.Fatal("a namespace pinned to baseline v1.33 rejected a probe host that v1.33 allows")
	}

	current := namespaceObj(testNamespace, map[string]any{enforceLabel: profileBaseline})
	detail := onlyFinding(t, report(t, current, probing()), "pod-security-would-reject").Detail
	if detail != "the namespace enforces baseline and this breaks probe or lifecycle host" {
		t.Fatalf("detail = %q", detail)
	}

	pinnedLate := namespaceObj(testNamespace, map[string]any{
		enforceLabel: profileBaseline, psapi.EnforceVersionLabel: "v1.34",
	})
	detail = onlyFinding(t, report(t, pinnedLate, probing()), "pod-security-would-reject").Detail
	if detail != "the namespace enforces baseline as of v1.34 and this breaks probe or lifecycle host" {
		t.Fatalf("detail = %q", detail)
	}
}

func TestALevelLabelUpstreamCannotReadIsEnforcedAsRestricted(t *testing.T) {
	found := report(t,
		namespaceObj(testNamespace, map[string]any{enforceLabel: "strict"}),
		deployment("api", podSpec(container("app", nil))))

	detail := onlyFinding(t, found, "pod-security-would-reject").Detail
	want := "the namespace enforces restricted, which is what upstream falls back to for a label it cannot read, and this breaks "
	if !strings.HasPrefix(detail, want) {
		t.Fatalf("detail = %q, want it to start with %q", detail, want)
	}
}

func TestTheEnforcedLevelNamesEveryControlThePodBreaks(t *testing.T) {
	found := report(t,
		namespaceObj(testNamespace, map[string]any{enforceLabel: profileStrict}),
		deployment("api", podSpec(container("app", nil))))

	detail := onlyFinding(t, found, "pod-security-would-reject").Detail
	want := "the namespace enforces restricted and this breaks allowPrivilegeEscalation != false, " +
		"unrestricted capabilities, runAsNonRoot != true, seccompProfile"
	if detail != want {
		t.Fatalf("detail = %q, want %q", detail, want)
	}
}

// what upstream is more lenient about than the hand-written rule was

func TestABaselineCapabilityAddedIsNotDangerous(t *testing.T) {
	found := report(t, deployment("api", podSpec(container("app", withSecurity(map[string]any{
		"capabilities": map[string]any{"add": []any{"CHOWN"}},
	})))))

	if findingCount(t, found, "dangerous-capabilities") != 0 {
		t.Fatal("CHOWN, which baseline allows, was reported as dangerous")
	}
}

func TestAHostPathLeftToASiblingRuleIsNotReportedTwice(t *testing.T) {
	found := report(t, deployment("api", podSpecWith(map[string]any{
		"volumes": []any{hostPathVolumeNamed("sock", "/var/run/docker.sock")},
	}, container("app", nil))))

	if findingCount(t, found, "host-path-volume") != 0 {
		t.Fatal("upstream's hostPath verdict was added on top of the socket rule's own finding")
	}
	if findingCount(t, found, "runtime-socket-mounted") != 1 {
		t.Fatal("the socket rule stopped reporting the socket")
	}
}