Files
pikasTech-unidesk/scripts/src/platform-infra-pac-provenance.test.ts
T

250 lines
15 KiB
TypeScript

import { expect, test } from "bun:test";
import { readFileSync } from "node:fs";
import { createRequire } from "node:module";
import { resolve } from "node:path";
import { resolveAgentRunLaneTarget } from "./agentrun-lanes";
import { renderAgentRunPipelineManifest } from "./agentrun-manifests";
import { renderPlatformInfraGiteaDesiredFragments } from "./platform-infra-gitea-desired-fragments";
import { pacConsumerRbacDesiredIdentity, renderPacConsumerRbacDesiredFragment } from "./platform-infra-pac-consumer-rbac";
import { parsePacAdmissionContract, readPacAdmissionContract, renderPacAdmissionDesiredFragment } from "./platform-infra-pac-provenance";
import { pacDebugFixtureDisclosure } from "./platform-infra-pipelines-as-code";
const root = resolve(import.meta.dir, "../..");
const evaluator = createRequire(import.meta.url)("../native/cicd/pac-status-evaluator.cjs") as {
evaluatePacAdmissionState: (input: Record<string, unknown>) => Record<string, any>;
evaluatePacStatus: (input: Record<string, unknown>) => Record<string, any>;
extractPacArtifactEvidence: (records: unknown[], logText: string) => Record<string, any>;
taskTerminalRecord: (taskRun: Record<string, unknown>) => Record<string, any> | null;
runPacStatusFixtureChecks: () => { ok: boolean; checks: Array<{ id: string; ok: boolean }> };
};
function documents(value: string): any[] {
return value.split(/^---\s*$/mu).map((item) => item.trim()).filter(Boolean).map((item) => Bun.YAML.parse(item));
}
test("admission contract rejects malformed required declarations instead of silently downgrading", () => {
const source = Bun.YAML.parse(readFileSync(resolve(root, "config/platform-infra/pipelines-as-code.yaml"), "utf8")) as any;
const consumer = source.consumers.find((item: any) => item.deliveryProvenance !== undefined);
consumer.deliveryProvenance.required = "true";
expect(() => parsePacAdmissionContract(source)).toThrow("deliveryProvenance.required must be boolean true or false");
});
test("versioned admission desired state protects controller proof, candidate identity, params, and execution SA", () => {
const contract = readPacAdmissionContract();
const owningYaml = Bun.YAML.parse(readFileSync(resolve(root, "config/platform-infra/pipelines-as-code.yaml"), "utf8")) as any;
expect(owningYaml.deliveryProvenance.terminalRoles).toBeUndefined();
expect(contract.policyName).toEndWith("-v1");
expect(contract.bindingName).toEndWith("-v1");
expect(contract.child.enabled).toBe(false);
expect(contract.consumers.map((item) => item.id)).toEqual(["agentrun-nc01-v02"]);
const items = documents(renderPacAdmissionDesiredFragment("NC01"));
expect(items.map((item) => item.kind)).toEqual(["ValidatingAdmissionPolicy", "ValidatingAdmissionPolicyBinding"]);
const policy = items[0];
const expressions = policy.spec.validations.map((item: any) => item.expression).join("\n");
const messages = policy.spec.validations.map((item: any) => item.message).join("\n");
expect(policy.spec.failurePolicy).toBe("Fail");
expect(policy.spec.matchConstraints.matchPolicy).toBe("Equivalent");
expect(items[1].spec.validationActions).toEqual(["Deny"]);
expect(policy.metadata.annotations["argocd.argoproj.io/sync-wave"]).toBe("0");
expect(items[1].metadata.annotations["argocd.argoproj.io/sync-wave"]).toBe("1");
expect(expressions).toContain("request.userInfo.username");
expect(expressions).toContain("spec.pipelineRef.name");
expect(expressions).toContain("spec.params == oldObject.spec.params");
expect(expressions).toContain("object.spec.pipelineRef == oldObject.spec.pipelineRef");
expect(expressions).toContain("object.spec == oldObject.spec");
expect(expressions).toContain("taskRunTemplate.serviceAccountName == oldObject.spec.taskRunTemplate.serviceAccountName");
expect(expressions).toContain("object.metadata.name.startsWith");
expect(expressions).toContain('object.metadata.labels["tekton.dev/pipeline"]');
expect(expressions).toContain("agentrun-nc01-v02-tekton-runner");
expect(messages).toContain("execution ServiceAccount");
expect(expressions).toContain(contract.child.parentUidAnnotation);
expect(expressions).toContain("oldObject");
expect(JSON.stringify(items)).not.toContain('"kind":"ServiceAccount"');
const specGuard = policy.spec.validations.find((item: any) => item.message.includes("PipelineRun spec is immutable"));
const oldRun = { spec: { pipelineSpec: { tasks: [{ name: "plan-artifacts" }] }, workspaces: [], timeouts: { pipeline: "1h" } } };
const mutatedRun = structuredClone(oldRun);
mutatedRun.spec.pipelineSpec.tasks[0].name = "forged-task";
expect(specGuard.expression).toMatch(/object\.spec == oldObject\.spec/u);
expect(mutatedRun.spec).not.toEqual(oldRun.spec);
});
test("required consumer default RBAC has one automatic desired owner and no Tekton mutation verbs", () => {
const rbac = documents(renderPacConsumerRbacDesiredFragment("NC01"));
expect(rbac.map((item) => item.kind)).toEqual(["Role", "RoleBinding"]);
const role = rbac[0];
expect(role.metadata.annotations["argocd.argoproj.io/sync-wave"]).toBe("-1");
expect(role.metadata.annotations["unidesk.ai/effective-config-sha256"]).toBe(pacConsumerRbacDesiredIdentity("NC01").configSha256);
const verbs = role.rules.flatMap((rule: any) => rule.verbs);
for (const verb of ["create", "patch", "update", "delete", "deletecollection"]) expect(verbs).not.toContain(verb);
const desiredKinds = documents(renderPlatformInfraGiteaDesiredFragments("NC01")).map((item) => item.kind);
expect(desiredKinds).toEqual(["Role", "RoleBinding", "ValidatingAdmissionPolicy", "ValidatingAdmissionPolicyBinding"]);
});
test("live admission evaluator requires exact desired hashes, observed generation, default-SA loss, and a new resource epoch", () => {
const contract = readPacAdmissionContract();
const admission = documents(renderPacAdmissionDesiredFragment("NC01"));
const rbac = documents(renderPacConsumerRbacDesiredFragment("NC01"));
const policy = { ...admission[0], metadata: { ...admission[0].metadata, uid: "policy-uid", generation: 2, creationTimestamp: "2026-01-01T00:00:00Z" }, status: { observedGeneration: 2, typeChecking: { expressionWarnings: [] } } };
const binding = { ...admission[1], metadata: { ...admission[1].metadata, uid: "binding-uid", creationTimestamp: "2026-01-01T00:00:01Z" } };
const expected = {
targetId: "NC01",
policyName: contract.policyName,
bindingName: contract.bindingName,
version: contract.version,
controllerIdentity: contract.controllerUsername,
configSha256: policy.metadata.annotations["unidesk.ai/effective-config-sha256"],
rbacConfigSha256: rbac[0].metadata.annotations["unidesk.ai/effective-config-sha256"],
};
const input = { policy, binding, role: rbac[0], roleBinding: rbac[1], namespace: "agentrun-ci", defaultCanMutate: false, expected };
expect(evaluator.evaluatePacAdmissionState(input)).toMatchObject({ ready: true, activeAfter: "2026-01-01T00:00:01Z", defaultCanMutate: false });
expect(evaluator.evaluatePacAdmissionState({ ...input, defaultCanMutate: true })).toMatchObject({ ready: false, reasons: expect.arrayContaining(["default-serviceaccount-can-mutate-tekton-runs"]) });
expect(evaluator.evaluatePacAdmissionState({ ...input, defaultCanMutate: null })).toMatchObject({ ready: false, defaultCanMutate: null, reasons: expect.arrayContaining(["default-serviceaccount-mutation-probe-unavailable"]) });
expect(evaluator.evaluatePacAdmissionState({ ...input, role: { ...rbac[0], rules: [rbac[0].rules[0]] } })).toMatchObject({ ready: false, reasons: expect.arrayContaining(["default-role-rules-mismatch"]) });
expect(evaluator.evaluatePacAdmissionState({ ...input, expected: { ...expected, configSha256: `sha256:${"0".repeat(64)}` } })).toMatchObject({ ready: false, reasons: expect.arrayContaining(["policy-config-sha256-mismatch"]) });
const mutatedPolicy = {
...policy,
spec: {
...policy.spec,
validations: policy.spec.validations.map((item: any, index: number) => index === 0 ? { ...item, expression: "true" } : item),
},
};
expect(evaluator.evaluatePacAdmissionState({ ...input, policy: mutatedPolicy })).toMatchObject({
ready: false,
reasons: expect.arrayContaining(["admission-live-spec-sha256-mismatch"]),
});
expect(evaluator.evaluatePacAdmissionState({
...input,
policy: { ...policy, spec: { ...policy.spec, matchConditions: [{ name: "disable-enforcement", expression: "false" }] } },
})).toMatchObject({ ready: false, reasons: expect.arrayContaining(["admission-live-spec-sha256-mismatch"]) });
expect(evaluator.evaluatePacAdmissionState({
...input,
binding: { ...binding, spec: { ...binding.spec, matchResources: { namespaceSelector: { matchLabels: { disabled: "true" } } } } },
})).toMatchObject({ ready: false, reasons: expect.arrayContaining(["admission-live-spec-sha256-mismatch"]) });
});
test("AgentRun owning renderer emits ordered terminal roles over the shared workspace without changing build and publish steps", () => {
const spec = resolveAgentRunLaneTarget({ node: "NC01", lane: "nc01-v02" }).spec;
const pipeline = renderAgentRunPipelineManifest(spec) as any;
const tasks = pipeline.spec.tasks;
expect(tasks.map((item: any) => item.name)).toEqual(["plan-artifacts", "collect-artifacts", "gitops-promote"]);
expect(tasks[0].runAfter).toBeUndefined();
expect(tasks[1].runAfter).toEqual(["plan-artifacts"]);
expect(tasks[2].runAfter).toEqual(["collect-artifacts"]);
for (const task of tasks) expect(task.workspaces).toEqual([{ name: "source", workspace: "source" }]);
expect(tasks[0].taskSpec.steps.map((item: any) => item.name)).toEqual(["source-checkout", "probe-env-image"]);
expect(tasks[1].taskSpec.steps.map((item: any) => item.name)).toEqual(["build-env-image"]);
expect(tasks[2].taskSpec.steps.map((item: any) => item.name)).toEqual(["publish-gitops"]);
expect(tasks[0].taskSpec.steps[1].script).toContain('"event":"pac-delivery-plan"');
expect(tasks[1].taskSpec.steps[0].script).toContain("buildctl-daemonless.sh");
expect(tasks[2].taskSpec.steps[0].script).toContain("gitops-publish");
});
test("AgentRun rendered delivery plan and real TaskRun terminals close the status evaluator gate", () => {
const spec = resolveAgentRunLaneTarget({ node: "NC01", lane: "nc01-v02" }).spec;
const pipeline = renderAgentRunPipelineManifest(spec) as any;
const tasks = pipeline.spec.tasks as any[];
const sourceCommit = "c".repeat(40);
const gitopsCommit = "b".repeat(40);
const digest = `sha256:${"a".repeat(64)}`;
const planPrintf = String(tasks[0].taskSpec.steps[1].script)
.split("\n")
.find((line) => line.startsWith("printf '{\"event\":\"pac-delivery-plan\""));
expect(planPrintf).toBeDefined();
const planResult = Bun.spawnSync({
cmd: ["sh", "-c", `build_services='["agentrun-mgr"]'; reused_services='[]'; ${planPrintf!.replaceAll("$(params.revision)", sourceCommit)}`],
stdout: "pipe",
stderr: "pipe",
});
expect(planResult.exitCode).toBe(0);
const plan = JSON.parse(planResult.stdout.toString().trim());
expect(plan).toMatchObject({ event: "pac-delivery-plan", sourceCommitId: sourceCommit, buildServices: ["agentrun-mgr"] });
const terminals = tasks.map((task) => evaluator.taskTerminalRecord({
apiVersion: "tekton.dev/v1",
kind: "TaskRun",
metadata: {
name: `fixture-${task.name}`,
labels: { "tekton.dev/pipelineTask": task.name },
},
status: {
conditions: [{ type: "Succeeded", status: "True", reason: "Succeeded" }],
results: [],
},
}));
expect(terminals).not.toContain(null);
const publish = {
ok: true,
status: "succeeded",
phase: "gitops-publish",
gitopsCommit,
sourceCommit,
imageStatus: "built",
digest,
valuesPrinted: false,
};
const artifact = evaluator.extractPacArtifactEvidence([plan, ...terminals, publish], "");
expect(artifact.sourceObservation).toMatchObject({
contract: "pac-delivery-plan-v1",
mode: "delivery",
valid: true,
terminal: {
planArtifacts: "succeeded",
collectArtifacts: "succeeded",
gitopsPromote: "succeeded",
},
terminalSources: {
planArtifacts: { markerSource: "pac-delivery-plan-structured-log" },
},
});
expect(evaluator.evaluatePacStatus({
sourceCommit,
artifact,
registryPresent: true,
argo: {
sync: "Synced",
health: "Healthy",
revision: gitopsCommit,
revisionRelation: { relation: "exact", expectedRevision: gitopsCommit, observedRevision: gitopsCommit },
},
runtime: { image: `registry/agentrun-mgr@${digest}`, digest, replicas: 1, readyReplicas: 1 },
})).toMatchObject({ ok: true, code: "pac-ready-gitops-exact" });
});
test("provenance fixtures fail closed for pre-bootstrap, forged marker, wrong SA, and policy mismatch", () => {
const result = evaluator.runPacStatusFixtureChecks();
expect(result.ok).toBe(true);
for (const id of ["admission-provenance-verified", "pre-bootstrap-run-fails-closed", "forged-name-candidate-fails-closed", "forged-label-candidate-fails-closed", "forged-pipeline-ref-candidate-fails-closed", "wrong-service-account-fails-closed", "policy-identity-mismatch-fails-closed"]) {
expect(result.checks.find((item) => item.id === id)?.ok).toBe(true);
}
});
test("history evaluates admission and default RBAC in each consumer namespace", () => {
const remote = readFileSync(resolve(root, "scripts/src/platform-infra-pipelines-as-code-remote.sh"), "utf8");
expect(remote).toContain("consumer.admissionState = admissionStateForConsumer(consumer)");
expect(remote).toContain("kubectlJson(['-n', consumer.namespace, 'get', 'role', 'unidesk-pac-consumer-runner'");
expect(remote).toContain("kubectlJson(['-n', consumer.namespace, 'get', 'rolebinding', 'unidesk-pac-consumer-runner-default'");
expect(remote).toContain("defaultCanMutate(consumer.namespace)");
expect(remote).toContain("for verb in create patch update delete deletecollection; do");
expect(remote).toContain('timeout "$UNIDESK_PAC_WAIT_TIMEOUT_SECONDS" kubectl auth can-i');
expect(remote).toContain("for (const verb of ['create', 'patch', 'update', 'delete', 'deletecollection'])");
const defaultMutationProbe = remote.slice(remote.indexOf("function defaultCanMutate(namespace)"), remote.indexOf("function admissionStateForConsumer(consumer)"));
expect(defaultMutationProbe).toContain("timeout: waitTimeoutSeconds * 1000");
expect(defaultMutationProbe).not.toContain("timeout: 12000");
expect(remote).toContain("'delivery plan structured evidence is missing'");
expect(remote).toContain("'delivery plan source commit does not match the selected PipelineRun'");
expect(remote).not.toContain("'g14-ci-plan structured evidence is missing'");
expect(remote).not.toContain("for (const consumer of consumers) consumer.admissionState = admissionState");
});
test("id-specific PaC debug keeps fixture failures but does not dump every passing check", () => {
const passing = Array.from({ length: 23 }, (_, index) => ({ id: `pass-${index}`, ok: true }));
expect(pacDebugFixtureDisclosure(passing, "agentrun-run")).toMatchObject({
fixtureGate: { ok: true, total: 23, passed: 23, failed: 0, disclosure: "failed-checks-only-for-id-specific-debug" },
checks: [],
});
const withFailure = [...passing, { id: "failed", ok: false }];
expect(pacDebugFixtureDisclosure(withFailure, "agentrun-run").checks).toEqual([{ id: "failed", ok: false }]);
expect(pacDebugFixtureDisclosure(passing, null).checks).toHaveLength(23);
});