Skip to content
Closed
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# The doggy-countdown deployment is sourced from a separately published OCI
# artifact and is applied as a ServiceAccount with permission to manage
# HTTPRoutes in this namespace. Keep that publishing path from claiming another
# hostname on the shared, cross-namespace Gateway (and from making external-dns
# publish that claim). Requiring exactly one hostname also rejects a hostname-
# less route, which Gateway API would otherwise match against every hostname.
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: restrict-doggy-countdown-hostnames
annotations:
policies.kyverno.io/title: Restrict Doggy Countdown Hostnames
policies.kyverno.io/category: Security, Gateway API
policies.kyverno.io/severity: high
policies.kyverno.io/subject: HTTPRoute
policies.kyverno.io/minversion: 1.6.0
policies.kyverno.io/description: >-
Restricts HTTPRoutes in the doggy-countdown namespace to the tenant's
assigned simba hostname so its remote manifest source cannot claim other
names on the shared platform Gateway.
spec:
validationFailureAction: Enforce
background: true
rules:
- name: require-doggy-countdown-hostname
match:
any:
- resources:
kinds:
- HTTPRoute
namespaces:
- doggy-countdown
validate:
message: >-
Doggy countdown HTTPRoutes must declare exactly one hostname:
simba.${domain}.
deny:
conditions:
any:
- key: "{{ request.object.spec.hostnames || `[]` }}"
operator: NotEquals
value:
- "simba.${domain}"
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ resources:
- best-practices/disable-default-sa-automount.yaml
- best-practices/disallow-latest-tag.yaml
- best-practices/propagate-reloader-to-flagger-primary.yaml
- best-practices/restrict-doggy-countdown-hostnames.yaml
- best-practices/restrict-tenant-issuer-refs.yaml
- best-practices/restrict-tenant-secret-stores.yaml
- best-practices/validate-host-restrictions.yaml
Expand Down
37 changes: 36 additions & 1 deletion scripts/validate-eks-ci-role-policy/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -363,7 +363,42 @@ const (
// per-resource fingerprint, since the moved documents belong to main's change
// rather than the branch's. Compare like with like before concluding the
// toolchain is at fault.
const expectedRenderedSurfaceSHA = "26e28178117fa9dc0f7d66c8bd526b1b5f000beeedac9f327207b8a674c56755"
//
// Measured against main 44f14fab before approving this value: 524 rendered
// documents on main and 525 on this branch across all five production roots,
// with membership differing by exactly ONE entry and zero removed or renamed
// (set difference in both directions over the complete
// apiVersion|kind|namespace|name identity). The single added entry is
//
// kyverno.io/v1 ClusterPolicy restrict-doggy-countdown-hostnames
//
// and after removing just that entry the remaining 524 documents are
// byte-identical to main's render — checked with a negative control that fired
// on a one-line perturbation, so the identical result is not vacuous. Nothing
// added, removed, or renamed touches a Role, ClusterRole, RoleBinding,
// ClusterRoleBinding, ServiceAccount, or IAM document.
//
// The added policy is selected into the surface only because Kyverno
// ClusterPolicies are indirect authorization policies. It is a single
// `validate.deny` rule matching HTTPRoute in the doggy-countdown namespace and
// requiring exactly the tenant's assigned hostname, with
// validationFailureAction Enforce. It creates no identity, binding, role, or
// policy document and grants nothing to the aws/aws service account; it can
// only refuse admission, so it moves the surface strictly in the restrictive
// direction.
//
// Two independent renderers agree on this value: the required CI job on the
// approved toolchain, and a local render on kubectl v1.36.1 with the same
// embedded kustomize v5.8.1. Agreement across a kubectl patch difference is
// what rules out a renderer-version artifact in the value.
//
// That local corroboration is reachable only through the test path, and the
// reason is worth recording: TestValidateAuthorizationAcceptsCommittedPolicy
// calls validateAuthorization directly, so it never passes through
// validateRendererVersion — only run() does. A local `go run` on v1.36.1 is
// still rejected by design. Do not read a passing `go test` as evidence that
// the local toolchain matches the pin.
const expectedRenderedSurfaceSHA = "e02856de56721b06897d6c151974796b08ecd73c23b461edde4c4f1efb44636b"

// authorizationOverlayPaths lists every independently reconciled production
// layer where an object can grant privileges to the aws/aws service account.
Expand Down
31 changes: 31 additions & 0 deletions tests/restrict-doggy-countdown-hostnames/kyverno-test.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
---
apiVersion: cli.kyverno.io/v1alpha1
kind: Test
metadata:
name: restrict-doggy-countdown-hostnames
policies:
- >-
../../k8s/bases/infrastructure/cluster-policies/best-practices/restrict-doggy-countdown-hostnames.yaml
resources:
- resources.yaml
results:
- policy: restrict-doggy-countdown-hostnames
rule: require-doggy-countdown-hostname
resources:
- doggy-countdown/intended-hostname
kind: HTTPRoute
result: pass
- policy: restrict-doggy-countdown-hostnames
rule: require-doggy-countdown-hostname
resources:
- doggy-countdown/arbitrary-hostname
- doggy-countdown/hostname-less
- doggy-countdown/mixed-hostnames
kind: HTTPRoute
result: fail
- policy: restrict-doggy-countdown-hostnames
rule: require-doggy-countdown-hostname
resources:
- another-tenant/arbitrary-hostname
kind: HTTPRoute
result: skip
44 changes: 44 additions & 0 deletions tests/restrict-doggy-countdown-hostnames/resources.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: intended-hostname
namespace: doggy-countdown
spec:
hostnames:
- "simba.${domain}"
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: arbitrary-hostname
namespace: doggy-countdown
spec:
hostnames:
- login.platform.devantler.tech
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: hostname-less
namespace: doggy-countdown
spec: {}
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: mixed-hostnames
namespace: doggy-countdown
spec:
hostnames:
- "simba.${domain}"
- login.platform.devantler.tech
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: arbitrary-hostname
namespace: another-tenant
spec:
hostnames:
- login.platform.devantler.tech
Loading