Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -413,7 +413,7 @@ jobs:
- 'scripts/tests/test-validate-image-verifier-liveness.sh'
# Stages exact admission and pull-time signer routes before the
# compatibility-image workloads consume them.
- 'scripts/tests/test-coroot-image-verifier-prerequisite.sh'
- 'scripts/tests/test-compatibility-image-verifier-prerequisite.sh'
# The trigger-set test for the liveness WORKFLOW (listed above), so a
# PR that edits only the test still runs it.
- 'scripts/tests/test-validate-image-verifier-liveness-workflow.sh'
Expand Down Expand Up @@ -2550,11 +2550,11 @@ jobs:
bash scripts/tests/test-validate-image-verifier-liveness.sh
bash scripts/tests/test-validate-image-verifier-liveness-workflow.sh

- name: 🔏 Validate Coroot compatibility-image verifier prerequisite
- name: 🔏 Validate compatibility-image verifier prerequisites
if: needs.changes.outputs.k8s == 'true'
run: |
shellcheck scripts/tests/test-coroot-image-verifier-prerequisite.sh
bash scripts/tests/test-coroot-image-verifier-prerequisite.sh
shellcheck scripts/tests/test-compatibility-image-verifier-prerequisite.sh
bash scripts/tests/test-compatibility-image-verifier-prerequisite.sh

- name: 🔏 Validate image-signature enforcement probe
if: needs.changes.outputs.k8s == 'true'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ metadata:
publish-app for app images, the platform's dedicated compatibility-image
publishers, each Crossplane provider's own package workflow, KSail's
publish-ksail-analysis-runner.yaml workflow, the mail bootstrap publisher,
the dedicated customer identity publisher, the source-built Dex
publisher, and KSail's release workflow.
the dedicated customer identity, Dex and Longhorn migration publishers,
and KSail's release workflow.
Each class is verified only against its own identity;
third-party images admit unverified.
spec:
Expand Down Expand Up @@ -112,6 +112,18 @@ spec:
identities:
- issuer: https://token.actions.githubusercontent.com
subjectRegExp: ^https://github\.com/devantler-tech/platform/\.github/workflows/publish-coroot-checkpoint-hotfix\.yaml@refs/heads/main$
- name: publishlonghornretirement
cosign:
keyless:
identities:
- issuer: https://token.actions.githubusercontent.com
subjectRegExp: ^https://github\.com/devantler-tech/platform/\.github/workflows/publish-longhorn-v1-retirement\.yaml@refs/heads/main$
- name: publishlonghornv2
cosign:
keyless:
identities:
- issuer: https://token.actions.githubusercontent.com
subjectRegExp: ^https://github\.com/devantler-tech/platform/\.github/workflows/publish-longhorn-v2-only\.yaml@refs/heads/main$
# The reports-controller repair is signed only by its dedicated publisher.
- name: publishkyvernoreports
cosign:
Expand Down Expand Up @@ -235,6 +247,12 @@ spec:
image != 'ghcr.io/devantler-tech/platform-dex' &&
!image.startsWith('ghcr.io/devantler-tech/platform-dex:') &&
!image.startsWith('ghcr.io/devantler-tech/platform-dex@') &&
image != 'ghcr.io/devantler-tech/platform-longhorn-instance-manager' &&
!image.startsWith('ghcr.io/devantler-tech/platform-longhorn-instance-manager:') &&
!image.startsWith('ghcr.io/devantler-tech/platform-longhorn-instance-manager@') &&
image != 'ghcr.io/devantler-tech/platform-longhorn-manager' &&
!image.startsWith('ghcr.io/devantler-tech/platform-longhorn-manager:') &&
!image.startsWith('ghcr.io/devantler-tech/platform-longhorn-manager@') &&
image != 'ghcr.io/devantler-tech/platform-kubescape-storage' &&
!image.startsWith('ghcr.io/devantler-tech/platform-kubescape-storage:') &&
!image.startsWith('ghcr.io/devantler-tech/platform-kubescape-storage@') &&
Expand Down Expand Up @@ -348,6 +366,28 @@ spec:
message: >-
Coroot node-agent compatibility image is not signed by the platform
repository's dedicated main-branch publisher (keyless cosign)
- expression: |-
(images.containers + images.initContainers + images.ephemeralContainers)
.filter(image,
image == 'ghcr.io/devantler-tech/platform-longhorn-instance-manager' ||
image.startsWith('ghcr.io/devantler-tech/platform-longhorn-instance-manager:') ||
image.startsWith('ghcr.io/devantler-tech/platform-longhorn-instance-manager@'))
.map(image, verifyImageSignatures(image, [attestors.publishlonghornretirement]))
.all(e, e > 0)
message: >-
The Longhorn V1 retirement image must be signed by its dedicated
main-branch publisher.
- expression: |-
(images.containers + images.initContainers + images.ephemeralContainers)
.filter(image,
image == 'ghcr.io/devantler-tech/platform-longhorn-manager' ||
image.startsWith('ghcr.io/devantler-tech/platform-longhorn-manager:') ||
image.startsWith('ghcr.io/devantler-tech/platform-longhorn-manager@'))
.map(image, verifyImageSignatures(image, [attestors.publishlonghornv2]))
.all(e, e > 0)
message: >-
The Longhorn V2-only manager image must be signed by its dedicated
main-branch publisher.
- expression: |-
(images.containers + images.initContainers + images.ephemeralContainers)
.filter(image,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
---
apiVersion: admissionregistration.k8s.io/v1
kind: MutatingAdmissionPolicyBinding
metadata:
name: longhorn-v1-benchmark-runtime
spec:
policyName: longhorn-v1-benchmark-runtime
matchResources:
matchPolicy: Exact
namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: longhorn-system
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
---
apiVersion: admissionregistration.k8s.io/v1
kind: MutatingAdmissionPolicy
metadata:
name: longhorn-v1-benchmark-runtime
spec:
failurePolicy: Fail
reinvocationPolicy: IfNeeded
matchConstraints:
matchPolicy: Exact
resourceRules:
- apiGroups: [""]
apiVersions: [v1]
operations: [CREATE]
resources: [pods]
scope: Namespaced
matchConditions:
- name: longhorn-controller
expression: |-
request.namespace == 'longhorn-system' &&
request.userInfo.username == 'system:serviceaccount:longhorn-system:longhorn-service-account' &&
object.metadata.namespace == request.namespace &&
object.spec.serviceAccountName == 'longhorn-service-account'
- name: native-v1-manager
expression: |-
has(object.metadata.labels) &&
object.metadata.name.matches('^instance-manager-[a-f0-9]{32}$') &&
'longhorn.io/component' in object.metadata.labels &&
object.metadata.labels['longhorn.io/component'] == 'instance-manager' &&
'longhorn.io/instance-manager-type' in object.metadata.labels &&
object.metadata.labels['longhorn.io/instance-manager-type'] == 'aio' &&
'longhorn.io/data-engine' in object.metadata.labels &&
object.metadata.labels['longhorn.io/data-engine'] == 'v1' &&
'longhorn.io/managed-by' in object.metadata.labels &&
object.metadata.labels['longhorn.io/managed-by'] == 'longhorn-manager'
- name: instance-manager-owner
expression: |-
has(object.metadata.ownerReferences) &&
size(object.metadata.ownerReferences) == 1 &&
object.metadata.ownerReferences.all(owner,
owner.apiVersion == 'longhorn.io/v1beta2' &&
owner.kind == 'InstanceManager' &&
owner.name == object.metadata.name &&
owner.uid.matches('^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$') &&
has(owner.controller) && owner.controller)
- name: approved-privileged-container
expression: |-
object.spec.restartPolicy == 'Never' &&
(!has(object.spec.initContainers) || size(object.spec.initContainers) == 0) &&
size(object.spec.containers) == 1 &&
object.spec.containers.all(container,
container.name == 'instance-manager' &&
container.image == 'ghcr.io/devantler-tech/platform-longhorn-instance-manager:v1.13.0-retirement.1-725bb1d09517c84f8b73ff2c0cf175421df351f1-1@sha256:93cfc83d8bab91f9b6fbffe20bf9bdaca28e877d91d7b740cae003bf6853059f' &&
has(container.securityContext) &&
has(container.securityContext.privileged) && container.securityContext.privileged &&
!has(container.securityContext.runAsUser) && !has(container.securityContext.runAsGroup) &&
(!has(container.securityContext.runAsNonRoot) || !container.securityContext.runAsNonRoot))
- name: no-pod-identity-override
expression: |-
!has(object.spec.securityContext) ||
(!has(object.spec.securityContext.runAsUser) && !has(object.spec.securityContext.runAsGroup) &&
(!has(object.spec.securityContext.runAsNonRoot) || !object.spec.securityContext.runAsNonRoot))
mutations:
- patchType: JSONPatch
jsonPatch:
expression: |-
[
JSONPatch{op: 'add', path: '/spec/containers/0/securityContext/runAsUser', value: 0},
JSONPatch{op: 'add', path: '/spec/containers/0/securityContext/runAsGroup', value: 0}
]
3 changes: 3 additions & 0 deletions k8s/providers/hetzner/infrastructure/kustomization.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,9 @@ resources:
# runtime-generated DaemonSet. Both are exact and version-coupled (#3931).
- cluster-policies/remove-longhorn-registrar-prestop.yaml
- cluster-policies/remove-existing-longhorn-registrar-prestop.yaml
# Keep the existing root identity for the exact temporary V1 benchmark runtime.
- cluster-policies/mutating-admission-policy-longhorn-v1-benchmark-runtime.yaml
- cluster-policies/mutating-admission-policy-binding-longhorn-v1-benchmark-runtime.yaml
# Prod-only: retrofit the two non-privilege C-0211 fields onto the four
# Longhorn CSI sidecar Deployments that predate the longhorn-system
# baseline-context opt-in. mutate-existing only -- nothing writes those
Expand Down
15 changes: 9 additions & 6 deletions scripts/guard-consumer-discovery-conservation.sh
Original file line number Diff line number Diff line change
Expand Up @@ -769,16 +769,18 @@ while IFS=$'\t' read -r file label; do
refuse "production render $label holds consumer generation or cloning that cannot be accounted for by a static build, so its consumers are UNKNOWN"
done <<<"$generated"
# Admit only complete reviewed apiVersion/kind/spec surfaces: the two
# HelmRelease defaults (#5357) and the native Gateway peer policy. The latter
# changes only physical-peer fields and its ownership marker on one fixed
# CiliumEnvoyConfig; neither carries a publication consumer or constructor.
# Its complete spec fingerprint includes every scope, variable and patch.
# HelmRelease defaults (#5357), the native Gateway peer policy, and the V1
# benchmark runtime policy (#5665). The Gateway policy changes peer fields
# on one fixed CiliumEnvoyConfig. The benchmark policy sets container UID
# and GID only on CREATE of an exact Longhorn Pod shape. Neither kind carries
# a publication consumer or constructor. The fingerprint includes every
# scope, variable and patch.
# A larger or changed policy cannot inherit approval from its name or paths.
# Canonical JSON includes every CEL expression,
# selector, operation and evaluation field, without whitespace normalization
# inside strings. An altered expression or added field cannot inherit an
# approval from the policy's name or its mutation paths. These patches touch
# only fixed defaults or Gateway peer fields, never chart values or consumers.
# only fixed defaults, Gateway peer fields or a Pod security context.
if ! yq -o=json -I=0 '.. | select(type == "!!map" and (.kind == "MutatingPolicy" or .kind == "MutatingAdmissionPolicy"))
| {"apiVersion": .apiVersion, "kind": .kind, "spec": .spec}' "$file" |
jq -cS . >"$work/reviewed-mutation-candidates.jsonl"; then
Expand All @@ -794,7 +796,8 @@ while IFS=$'\t' read -r file label; do
case "${candidate_digest%% *}" in
43b7eaf13a1b754ed0449239ce9e337de6881751fd009c738efb46e367524824 | \
691bf7d05ed9d87ae261f34d51e7cd062d345a6af8f6bb2dcf1ec1aeb3dade17 | \
92dc171d2b1e73eec7679ae3f74e806a3fc8472f7ed3445bfca1541c3d27941d)
92dc171d2b1e73eec7679ae3f74e806a3fc8472f7ed3445bfca1541c3d27941d | \
55d0841bf6699a0cbf7bb40bcf2b154facc2305cae538b9f75b71774651895d3)
reviewed_cel_surfaces="$(jq -ce --argjson candidate "$candidate" '. + [$candidate]' <<<"$reviewed_cel_surfaces")" ||
refuse 'could not record the complete reviewed mutation policy'
;;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ require (
k8s.io/apimachinery v0.36.4
k8s.io/apiserver v0.36.4
k8s.io/client-go v0.36.4
sigs.k8s.io/yaml v1.6.0
)

require (
Expand Down Expand Up @@ -80,5 +81,4 @@ require (
sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730 // indirect
sigs.k8s.io/randfill v1.0.0 // indirect
sigs.k8s.io/structured-merge-diff/v6 v6.3.3 // indirect
sigs.k8s.io/yaml v1.6.0 // indirect
)
Loading
Loading