ce7cb702218693d08ea6d83464d2457c9250027c

This commit is contained in:
ms2k 2026-11-12 20:46:28 +09:00
commit 34c5f8963c
71 changed files with 145336 additions and 0 deletions

View file

@ -0,0 +1,7 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- quay-operator.yaml
- smartctl-exporter-host-smart.yaml
- zfs-exporter-host-zfs.yaml
- node-exporter-host-metrics.yaml

View file

@ -0,0 +1,30 @@
apiVersion: kyverno.io/v2
kind: PolicyException
metadata:
name: node-exporter-host-metrics
namespace: kyverno
annotations:
policies.kyverno.io/reason: >-
Node exporter needs hostNetwork and hostPath mounts for node metrics.
Privileged is already avoided; host access is residual for this DaemonSet.
quorate.internal/exception-owner: platform
quorate.internal/exception-review-by: "2026-10-11"
spec:
exceptions:
- policyName: restrict-pod-host-access
ruleNames:
- deny-host-namespaces
- deny-hostpath-volumes
- autogen-deny-host-namespaces
- autogen-deny-hostpath-volumes
match:
any:
- resources:
kinds:
- Pod
- DaemonSet
- ReplicaSet
namespaces:
- node-exporter
names:
- node-exporter*

View file

@ -0,0 +1,41 @@
apiVersion: kyverno.io/v2
kind: PolicyException
metadata:
name: quay-operator
namespace: kyverno
annotations:
policies.kyverno.io/reason: >-
Quay Operator CSV does not expose pod template labels or a strict
securityContext for the operator deployment. Prefer exception over
forked CSV until operator supports these fields.
quorate.internal/exception-owner: platform
quorate.internal/exception-review-by: "2026-10-11"
spec:
exceptions:
- policyName: require-app-labels
ruleNames:
- require-app-name-and-instance
- autogen-require-app-name-and-instance
- policyName: require-drop-all-capabilities
ruleNames:
- require-capabilities-drop-all
- autogen-require-capabilities-drop-all
- policyName: require-allow-privilege-escalation-false
ruleNames:
- require-allow-privilege-escalation-false
- autogen-require-allow-privilege-escalation-false
- policyName: require-resource-requests
ruleNames:
- require-cpu-memory-requests
- autogen-require-cpu-memory-requests
match:
any:
- resources:
kinds:
- Pod
- Deployment
- ReplicaSet
namespaces:
- quay
names:
- quay-operator-tng*

View file

@ -0,0 +1,43 @@
apiVersion: kyverno.io/v2
kind: PolicyException
metadata:
name: smartctl-exporter-host-smart
namespace: kyverno
annotations:
policies.kyverno.io/reason: >-
Host SMART metrics require privileged access to /dev on this cluster;
least-privilege (SYS_RAWIO alone) failed open-device EPERM. Track for
runtime controls (e.g. Tetragon) rather than silent privileged sprawl.
quorate.internal/exception-owner: platform
quorate.internal/exception-review-by: "2026-10-11"
spec:
exceptions:
- policyName: deny-privileged
ruleNames:
- deny-privileged-containers
- autogen-deny-privileged-containers
- policyName: require-drop-all-capabilities
ruleNames:
- require-capabilities-drop-all
- autogen-require-capabilities-drop-all
- policyName: require-allow-privilege-escalation-false
ruleNames:
- require-allow-privilege-escalation-false
- autogen-require-allow-privilege-escalation-false
- policyName: restrict-pod-host-access
ruleNames:
- deny-host-namespaces
- deny-hostpath-volumes
- autogen-deny-host-namespaces
- autogen-deny-hostpath-volumes
match:
any:
- resources:
kinds:
- Pod
- DaemonSet
- ReplicaSet
namespaces:
- smartctl-exporter
names:
- smartctl-exporter*

View file

@ -0,0 +1,43 @@
apiVersion: kyverno.io/v2
kind: PolicyException
metadata:
name: zfs-exporter-host-zfs
namespace: kyverno
annotations:
policies.kyverno.io/reason: >-
Host ZFS metrics need chart-level privileged + host root path for libzfs
under chroot on this cluster; least-privilege probes failed. Track for
runtime controls (e.g. Tetragon).
quorate.internal/exception-owner: platform
quorate.internal/exception-review-by: "2026-10-11"
spec:
exceptions:
- policyName: deny-privileged
ruleNames:
- deny-privileged-containers
- autogen-deny-privileged-containers
- policyName: require-drop-all-capabilities
ruleNames:
- require-capabilities-drop-all
- autogen-require-capabilities-drop-all
- policyName: require-allow-privilege-escalation-false
ruleNames:
- require-allow-privilege-escalation-false
- autogen-require-allow-privilege-escalation-false
- policyName: restrict-pod-host-access
ruleNames:
- deny-host-namespaces
- deny-hostpath-volumes
- autogen-deny-host-namespaces
- autogen-deny-hostpath-volumes
match:
any:
- resources:
kinds:
- Pod
- DaemonSet
- ReplicaSet
namespaces:
- zfs-exporter
names:
- zfs-exporter*

View file

@ -0,0 +1,211 @@
apiVersion: helm.toolkit.fluxcd.io/v2
kind: HelmRelease
metadata:
name: kyverno
namespace: kyverno
spec:
interval: 15m
releaseName: kyverno
targetNamespace: kyverno
chart:
spec:
chart: kyverno
version: 3.9.2
sourceRef:
kind: HelmRepository
name: kyverno
namespace: flux-system
install:
remediation:
retries: 3
upgrade:
remediation:
retries: 3
values:
config:
resourceFiltersExcludeNamespaces:
- kube-system
webhooks:
namespaceSelector:
matchExpressions: []
matchConditions:
- name: system-secrets
expression: '!has(request.namespace) || request.namespace != "kube-system" || request.resource.resource == "secrets"'
crds:
install: true
features:
forceFailurePolicyIgnore:
enabled: false
policyExceptions:
enabled: true
namespace: kyverno
admissionController:
replicas: 3
initContainer:
image:
tag: v1.19.2@sha256:27f3cc52e628559b56d08363b85316819802086c9808606914f7805a244148f4
container:
image:
tag: v1.19.2@sha256:c8c4dd09e720d2cd7fd24ca73ac28e46651001372f988e0cba3f2f612f04b955
rbac:
clusterRole:
extraResources:
- apiGroups:
- cilium.io
resources:
- ciliumnetworkpolicies
verbs:
- get
- list
- watch
- apiGroups:
- gateway.networking.k8s.io
resources:
- gateways
- httproutes
- tcproutes
- referencegrants
- grpcroutes
verbs:
- get
- list
- watch
- apiGroups:
- rbac.authorization.k8s.io
resources:
- roles
- clusterroles
verbs:
- get
- list
- watch
podDisruptionBudget:
enabled: true
minAvailable: 1
antiAffinity:
enabled: true
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app.kubernetes.io/component
operator: In
values:
- admission-controller
topologyKey: kubernetes.io/hostname
backgroundController:
replicas: 3
image:
tag: v1.19.2@sha256:c46e124f21ef8a6bb4b48de57106808b1007edcd5ddd4ff7df5d23b9efa60ce2
rbac:
clusterRole:
extraResources:
- apiGroups:
- apps
resources:
- deployments
- daemonsets
- statefulsets
verbs:
- update
- apiGroups:
- ""
resources:
- secrets
verbs:
- get
- list
- watch
- apiGroups:
- gateway.networking.k8s.io
resources:
- gateways
- httproutes
- tcproutes
- referencegrants
- grpcroutes
verbs:
- get
- list
- watch
- apiGroups:
- rbac.authorization.k8s.io
resources:
- roles
- clusterroles
verbs:
- get
- list
- watch
podDisruptionBudget:
enabled: true
minAvailable: 1
antiAffinity:
enabled: true
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app.kubernetes.io/component
operator: In
values:
- background-controller
topologyKey: kubernetes.io/hostname
cleanupController:
replicas: 2
image:
tag: v1.19.2@sha256:d7340aa7c9315080c3dafa7b765d090ced37353e89e5cd7a3f9ac69e8fb532b2
podDisruptionBudget:
enabled: true
minAvailable: 1
reportsController:
replicas: 2
image:
tag: v1.19.2@sha256:5fb6d3e738050dbce84f60ecabaede7665fbe0578d07c1e8c912443b035e79c3
resources:
limits:
memory: 256Mi
rbac:
clusterRole:
extraResources:
- apiGroups:
- ""
resources:
- secrets
verbs:
- get
- list
- watch
- apiGroups:
- cilium.io
resources:
- ciliumnetworkpolicies
- ciliumclusterwidenetworkpolicies
verbs:
- get
- list
- watch
- apiGroups:
- gateway.networking.k8s.io
resources:
- gateways
- httproutes
- tcproutes
- referencegrants
- grpcroutes
verbs:
- get
- list
- watch
- apiGroups:
- rbac.authorization.k8s.io
resources:
- roles
- clusterroles
verbs:
- get
- list
- watch
podDisruptionBudget:
enabled: true
minAvailable: 1

View file

@ -0,0 +1,7 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- namespace.yaml
- helm-release.yaml
- network-policies.yaml
- exceptions

View file

@ -0,0 +1,4 @@
apiVersion: v1
kind: Namespace
metadata:
name: kyverno

View file

@ -0,0 +1,214 @@
---
apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
name: kyverno-admission-controller
namespace: kyverno
spec:
endpointSelector:
matchLabels:
app.kubernetes.io/component: admission-controller
app.kubernetes.io/instance: kyverno
ingress:
- fromEntities:
- kube-apiserver
- host
- remote-node
toPorts:
- ports:
- port: "9443"
protocol: TCP
- fromEntities:
- host
toPorts:
- ports:
- port: "8000"
protocol: TCP
egress:
- toEntities:
- kube-apiserver
toPorts:
- ports:
- port: "6443"
protocol: TCP
- toEndpoints:
- matchLabels:
k8s:io.kubernetes.pod.namespace: kube-system
k8s-app: kube-dns
toPorts:
- ports:
- port: "53"
protocol: UDP
- port: "53"
protocol: TCP
- toServices:
- k8sService:
namespace: kube-system
serviceName: kube-dns
toPorts:
- ports:
- port: "53"
protocol: UDP
- port: "53"
protocol: TCP
---
apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
name: kyverno-background-controller
namespace: kyverno
spec:
endpointSelector:
matchLabels:
app.kubernetes.io/component: background-controller
app.kubernetes.io/instance: kyverno
ingress:
- fromEntities:
- host
toPorts:
- ports:
- port: "8000"
protocol: TCP
egress:
- toEntities:
- kube-apiserver
toPorts:
- ports:
- port: "6443"
protocol: TCP
- toEndpoints:
- matchLabels:
k8s:io.kubernetes.pod.namespace: kube-system
k8s-app: kube-dns
toPorts:
- ports:
- port: "53"
protocol: UDP
- port: "53"
protocol: TCP
- toServices:
- k8sService:
namespace: kube-system
serviceName: kube-dns
toPorts:
- ports:
- port: "53"
protocol: UDP
- port: "53"
protocol: TCP
---
apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
name: kyverno-cleanup-controller
namespace: kyverno
spec:
endpointSelector:
matchLabels:
app.kubernetes.io/component: cleanup-controller
app.kubernetes.io/instance: kyverno
ingress:
- fromEntities:
- kube-apiserver
- host
- remote-node
toPorts:
- ports:
- port: "9443"
protocol: TCP
- fromEntities:
- host
toPorts:
- ports:
- port: "8000"
protocol: TCP
egress:
- toEntities:
- kube-apiserver
toPorts:
- ports:
- port: "6443"
protocol: TCP
- toEndpoints:
- matchLabels:
k8s:io.kubernetes.pod.namespace: kube-system
k8s-app: kube-dns
toPorts:
- ports:
- port: "53"
protocol: UDP
- port: "53"
protocol: TCP
- toServices:
- k8sService:
namespace: kube-system
serviceName: kube-dns
toPorts:
- ports:
- port: "53"
protocol: UDP
- port: "53"
protocol: TCP
---
apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
name: kyverno-reports-controller
namespace: kyverno
spec:
endpointSelector:
matchLabels:
app.kubernetes.io/component: reports-controller
app.kubernetes.io/instance: kyverno
ingress:
- fromEntities:
- host
toPorts:
- ports:
- port: "8000"
protocol: TCP
egress:
- toEntities:
- kube-apiserver
toPorts:
- ports:
- port: "6443"
protocol: TCP
- toEndpoints:
- matchLabels:
k8s:io.kubernetes.pod.namespace: kube-system
k8s-app: kube-dns
toPorts:
- ports:
- port: "53"
protocol: UDP
- port: "53"
protocol: TCP
- toServices:
- k8sService:
namespace: kube-system
serviceName: kube-dns
toPorts:
- ports:
- port: "53"
protocol: UDP
- port: "53"
protocol: TCP
---
apiVersion: cilium.io/v2
kind: CiliumClusterwideNetworkPolicy
metadata:
name: host-egress-kyverno
spec:
nodeSelector: {}
egress:
- toEndpoints:
- matchLabels:
k8s:io.kubernetes.pod.namespace: kyverno
app.kubernetes.io/instance: kyverno
toPorts:
- ports:
- port: "9443"
protocol: TCP
- port: "8000"
protocol: TCP

View file

@ -0,0 +1,87 @@
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: audit-gateway-api-rbac
annotations:
policies.kyverno.io/title: Audit Gateway API mutating RBAC
policies.kyverno.io/category: Gateway API
policies.kyverno.io/severity: medium
policies.kyverno.io/description: >-
Report ClusterRoles and Roles that grant create/update/patch/delete on
gateway.networking.k8s.io resources outside the approved controller set.
spec:
validationFailureAction: Audit
background: true
rules:
- name: flag-unapproved-gateway-api-mutation
match:
any:
- resources:
kinds:
- ClusterRole
- Role
exclude:
any:
- resources:
names:
- cluster-admin
- admin
- edit
- system:*
- cilium-*
- cert-manager-*
- grafana-operator*
- victoriametrics-operator*
- flux-*
- cluster-reconciler-flux-system
- crd-controller-flux-system
- agentgateway-agentgateway-system
# Kyverno * does not match '.' — use olm.og* not olm.og.*
- olm.og*
- aggregate-olm*
# Count rules that explicitly mutate Gateway API kinds (no foreach — wildcard
# AnyIn on * false-positived every Role).
preconditions:
all:
- key: >-
{{ (request.object.rules || `[]`)[?
apiGroups != null &&
contains(apiGroups, 'gateway.networking.k8s.io') &&
(
contains(verbs, 'create') ||
contains(verbs, 'update') ||
contains(verbs, 'patch') ||
contains(verbs, 'delete') ||
contains(verbs, 'deletecollection') ||
contains(verbs, '*')
) &&
resources != null &&
(
contains(resources, 'gateways') ||
contains(resources, 'gateways/status') ||
contains(resources, 'httproutes') ||
contains(resources, 'httproutes/status') ||
contains(resources, 'httproutes/finalizers') ||
contains(resources, 'grpcroutes') ||
contains(resources, 'referencegrants') ||
contains(resources, 'tlsroutes') ||
contains(resources, 'tcproutes') ||
contains(resources, 'gatewayclasses') ||
contains(resources, 'gatewayclasses/status')
)
] | length(@) }}
operator: GreaterThan
value: 0
validate:
message: >-
Role grants mutating verbs on gateway.networking.k8s.io resources
outside the approved controller set. Review and narrow or add to the
policy allowlist.
deny:
conditions:
any:
- key: "{{ request.object.kind }}"
operator: AnyIn
value:
- Role
- ClusterRole

View file

@ -0,0 +1,109 @@
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: canonical-cilium-cidrs
annotations:
policies.kyverno.io/title: Canonical Cilium CIDRs
policies.kyverno.io/category: Network Security
policies.kyverno.io/severity: high
policies.kyverno.io/description: >-
Require canonical, non-redundant Cilium CIDRs and reject generic RFC1918
ranges in favor of explicit routed subnets.
spec:
validationFailureAction: Enforce
background: true
rules:
- name: require-canonical-cidrs
match:
any:
- resources:
kinds:
- CiliumNetworkPolicy
- CiliumClusterwideNetworkPolicy
operations:
- CREATE
- UPDATE
validate:
cel:
variables:
- name: policySpecs
expression: "has(object.spec) ? [object.spec] : object.specs"
- name: genericPrivateRanges
expression: "['10.0.0.0/8', '172.16.0.0/12', '192.168.0.0/16']"
expressions:
- expression: >-
variables.policySpecs.all(policy,
(!has(policy.ingress) || policy.ingress.all(rule,
(!has(rule.fromCIDR) || rule.fromCIDR.all(value,
isCIDR(value) && value == string(cidr(value).masked())
)) &&
(!has(rule.fromCIDRSet) || rule.fromCIDRSet.all(entry,
(!has(entry.cidr) || (isCIDR(entry.cidr) &&
entry.cidr == string(cidr(entry.cidr).masked()) &&
(!has(entry.except) || entry.except.all(value,
isCIDR(value) && value == string(cidr(value).masked())
))))
))
)) &&
(!has(policy.egress) || policy.egress.all(rule,
(!has(rule.toCIDR) || rule.toCIDR.all(value,
isCIDR(value) && value == string(cidr(value).masked())
)) &&
(!has(rule.toCIDRSet) || rule.toCIDRSet.all(entry,
(!has(entry.cidr) || (isCIDR(entry.cidr) &&
entry.cidr == string(cidr(entry.cidr).masked()) &&
(!has(entry.except) || entry.except.all(value,
isCIDR(value) && value == string(cidr(value).masked())
))))
))
))
)
message: Cilium policy CIDRs must use canonical network prefixes.
- expression: >-
variables.policySpecs.all(policy,
(!has(policy.ingress) || policy.ingress.all(rule,
!has(rule.fromCIDR) ||
rule.fromCIDR.all(value,
rule.fromCIDR.filter(other, other == value).size() == 1 &&
!rule.fromCIDR.exists(other,
other != value && cidr(other).containsCIDR(cidr(value))
)
)
)) &&
(!has(policy.egress) || policy.egress.all(rule,
!has(rule.toCIDR) ||
rule.toCIDR.all(value,
rule.toCIDR.filter(other, other == value).size() == 1 &&
!rule.toCIDR.exists(other,
other != value && cidr(other).containsCIDR(cidr(value))
)
)
))
)
message: >-
Cilium fromCIDR and toCIDR lists must not contain duplicate or
redundant ranges.
- expression: >-
variables.policySpecs.all(policy,
(!has(policy.ingress) || policy.ingress.all(rule,
(!has(rule.fromCIDR) || rule.fromCIDR.all(value,
!variables.genericPrivateRanges.exists(block, block == value)
)) &&
(!has(rule.fromCIDRSet) || rule.fromCIDRSet.all(entry,
!has(entry.cidr) ||
!variables.genericPrivateRanges.exists(block, block == entry.cidr)
))
)) &&
(!has(policy.egress) || policy.egress.all(rule,
(!has(rule.toCIDR) || rule.toCIDR.all(value,
!variables.genericPrivateRanges.exists(block, block == value)
)) &&
(!has(rule.toCIDRSet) || rule.toCIDRSet.all(entry,
!has(entry.cidr) ||
!variables.genericPrivateRanges.exists(block, block == entry.cidr)
))
))
)
message: >-
Cilium policies must use explicit routed subnets instead of
generic RFC1918 ranges.

View file

@ -0,0 +1,56 @@
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: cilium-networkpolicy-coverage
annotations:
policies.kyverno.io/title: CiliumNetworkPolicy namespace coverage
policies.kyverno.io/category: Network Security
policies.kyverno.io/severity: medium
policies.kyverno.io/description: >-
Audit namespaces that lack any CiliumNetworkPolicy. Stays Audit forever;
never promote to Enforce (onboarding must not block on CNP admission).
spec:
validationFailureAction: Audit
background: true
rules:
- name: require-namespaced-cilium-networkpolicy
match:
any:
- resources:
kinds:
- Namespace
exclude:
any:
- resources:
names:
- default
- kube-system
- kube-public
- kube-node-lease
- flux-system
- flux-canary
- kyverno
- cert-manager
- cilium-secrets
- olm
- operators
- longhorn
- openebs
- intel-system
- nfd
context:
- name: cnpcount
apiCall:
urlPath: "/apis/cilium.io/v2/namespaces/{{ request.object.metadata.name }}/ciliumnetworkpolicies"
jmesPath: "items | length(@)"
validate:
message: >-
Namespace {{ request.object.metadata.name }} has no CiliumNetworkPolicy
resources. Add at least one namespaced CNP (clusterwide policies are not
counted by this rule yet).
deny:
conditions:
any:
- key: "{{ cnpcount }}"
operator: Equals
value: 0

View file

@ -0,0 +1,49 @@
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: deny-latest-tag
annotations:
policies.kyverno.io/title: Deny latest image tags
policies.kyverno.io/category: Best Practices
policies.kyverno.io/severity: medium
policies.kyverno.io/description: >-
Deny containers that pull the :latest tag.
spec:
validationFailureAction: Enforce
background: true
rules:
- name: deny-latest-images
match:
any:
- resources:
kinds:
- Pod
exclude:
any:
- resources:
namespaces:
- kube-system
- kube-public
- kube-node-lease
- flux-system
- flux-canary
- kyverno
- cert-manager
- cilium-secrets
- olm
- operators
- longhorn
- openebs
- intel-system
- nfd
validate:
message: >-
Containers must not use the :latest tag. Pin a version or digest.
pattern:
spec:
=(initContainers):
- image: "!*:latest"
=(ephemeralContainers):
- image: "!*:latest"
containers:
- image: "!*:latest"

View file

@ -0,0 +1,51 @@
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: deny-privileged
annotations:
policies.kyverno.io/title: Deny privileged containers
policies.kyverno.io/category: Pod Security
policies.kyverno.io/severity: high
policies.kyverno.io/description: >-
Flag containers with privileged: true. Host storage exporters should use
narrow capabilities instead of full privileged where possible.
spec:
validationFailureAction: Enforce
background: true
rules:
- name: deny-privileged-containers
match:
any:
- resources:
kinds:
- Pod
exclude:
any:
- resources:
namespaces:
- kube-system
- kube-public
- kube-node-lease
- flux-system
- flux-canary
- kyverno
- cert-manager
- cilium-secrets
- olm
- operators
- longhorn
- openebs
- intel-system
- nfd
validate:
message: >-
Containers must not set privileged: true. Prefer drop ALL plus the
minimal capabilities and hostPaths required for the workload.
foreach:
- list: "request.object.spec.[initContainers, ephemeralContainers, containers][]"
deny:
conditions:
any:
- key: "{{ element.securityContext.privileged || false }}"
operator: Equals
value: true

View file

@ -0,0 +1,29 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- canonical-cilium-cidrs.yaml
- require-app-labels.yaml
- quay-job-labels.yaml
- deny-latest-tag.yaml
- cilium-networkpolicy-coverage.yaml
- deny-privileged.yaml
- require-drop-all-capabilities.yaml
- require-allow-privilege-escalation-false.yaml
- require-resource-requests.yaml
- min-replicas.yaml
- require-public-runtime-gvisor.yaml
# Track C Gateway (Audit)
- require-gateway-route-selectors.yaml
- restrict-route-parentrefs.yaml
- restrict-route-backends.yaml
- restrict-referencegrants.yaml
- protect-shared-gateways.yaml
- audit-gateway-api-rbac.yaml
- restrict-gateway-client-label.yaml
# 2b expanded Audit
- restrict-image-registries.yaml
- restrict-zot-image-pulls.yaml
- restrict-pod-host-access.yaml
- require-vso-secret-labels.yaml
- tls-activation.yaml
- tls-rollout.yaml

View file

@ -0,0 +1,32 @@
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: min-replicas
annotations:
policies.kyverno.io/title: Ban single-replica Deployments
policies.kyverno.io/category: Best Practices
policies.kyverno.io/severity: medium
policies.kyverno.io/description: >-
Audit Deployments whose effective replica count is exactly one. Stopped
Deployments may use zero, and available Deployments must use at least two
unless a resource-specific exception is approved.
spec:
validationFailureAction: Audit
background: true
rules:
- name: min-replicas
match:
any:
- resources:
kinds:
- Deployment
validate:
message: >-
Deployment replica count must be zero or at least two. A single
replica requires a resource-specific PolicyException.
deny:
conditions:
all:
- key: "{{ request.object.spec.replicas || `1` }}"
operator: Equals
value: 1

View file

@ -0,0 +1,54 @@
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: protect-shared-gateways
annotations:
policies.kyverno.io/title: Protect shared Gateway specs
policies.kyverno.io/category: Gateway API
policies.kyverno.io/severity: high
policies.kyverno.io/description: >-
Shared Gateways (internal, relay, and short) may only have their spec mutated
by Flux GitOps service accounts. Cilium status updates that do not change
spec are not evaluated. Admission-only (userInfo is not available in
background scans).
spec:
validationFailureAction: Audit
background: false
rules:
- name: shared-gateway-spec-gitops-only
match:
any:
- resources:
kinds:
- Gateway
names:
- gateway-internal
- gateway-relay
- gateway-short
namespaces:
- kube-system
operations:
- CREATE
- UPDATE
preconditions:
any:
- key: "{{ request.operation }}"
operator: Equals
value: CREATE
- key: "{{ request.object.spec }}"
operator: NotEquals
value: "{{ request.oldObject.spec }}"
validate:
message: >-
Shared Gateway specs may only be created or changed by Flux
(flux-system kustomize-controller / helm-controller). Other callers
fail this audit until reviewed.
deny:
conditions:
all:
- key: "{{ request.userInfo.username }}"
operator: AnyNotIn
value:
- system:serviceaccount:flux-system:kustomize-controller
- system:serviceaccount:flux-system:helm-controller
- system:serviceaccount:flux-system:flux-operator

View file

@ -0,0 +1,28 @@
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: quay-job-labels
spec:
rules:
- name: migration
match:
any:
- resources:
kinds:
- Job
namespaces:
- quay
names:
- quay-registry-quay-app-upgrade
selector:
matchLabels:
quay-component: quay-app-upgrade
quay-operator/quayregistry: quay-registry
mutate:
patchStrategicMerge:
spec:
template:
metadata:
labels:
app.kubernetes.io/name: quay
app.kubernetes.io/instance: quay-registry

View file

@ -0,0 +1,54 @@
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: require-allow-privilege-escalation-false
annotations:
policies.kyverno.io/title: Require allowPrivilegeEscalation false
policies.kyverno.io/category: Pod Security
policies.kyverno.io/severity: medium
policies.kyverno.io/description: >-
Require every container to set allowPrivilegeEscalation: false (unset is a
fail).
spec:
validationFailureAction: Enforce
background: true
rules:
- name: require-allow-privilege-escalation-false
match:
any:
- resources:
kinds:
- Pod
exclude:
any:
- resources:
namespaces:
- kube-system
- kube-public
- kube-node-lease
- flux-system
- flux-canary
- kyverno
- cert-manager
- cilium-secrets
- olm
- operators
- longhorn
- openebs
- intel-system
- nfd
validate:
message: >-
Containers must set securityContext.allowPrivilegeEscalation: false
(leaving the field unset is not sufficient).
pattern:
spec:
=(initContainers):
- securityContext:
allowPrivilegeEscalation: false
=(ephemeralContainers):
- securityContext:
allowPrivilegeEscalation: false
containers:
- securityContext:
allowPrivilegeEscalation: false

View file

@ -0,0 +1,70 @@
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: require-app-labels
annotations:
policies.kyverno.io/title: Require application identity labels
policies.kyverno.io/category: Best Practices
policies.kyverno.io/severity: medium
policies.kyverno.io/description: >-
Require application name and instance labels, accepting Dragonfly's native
app identity in its namespace.
spec:
validationFailureAction: Enforce
background: true
rules:
- name: require-app-name-and-instance
match:
any:
- resources:
kinds:
- Pod
exclude:
any:
- resources:
namespaces:
- kube-system
- kube-public
- kube-node-lease
- flux-system
- flux-canary
- kyverno
- cert-manager
- cilium-secrets
- olm
- operators
- longhorn
- openebs
- intel-system
- nfd
- dragonfly
validate:
message: >-
Pod must have non-empty labels app.kubernetes.io/name and
app.kubernetes.io/instance for Cilium and operational selectors.
pattern:
metadata:
labels:
app.kubernetes.io/name: "?*"
app.kubernetes.io/instance: "?*"
- name: dragonfly-identity
match:
any:
- resources:
kinds:
- Pod
namespaces:
- dragonfly
validate:
message: >-
Pods require name and instance labels; Dragonfly cache Pods may use
their native app label as the instance identity.
anyPattern:
- metadata:
labels:
app.kubernetes.io/name: "?*"
app.kubernetes.io/instance: "?*"
- metadata:
labels:
app.kubernetes.io/name: dragonfly
app: "?*"

Some files were not shown because too many files have changed in this diff Show more