mirror of
https://github.com/ghndrx/homelab-gitops.git
synced 2026-02-10 06:44:57 +00:00
feat(kyverno): add policy engine with security baseline
- Kyverno 3.3.4 via Helm (HA config: 3 admission, 2 background replicas) - Validation policies: - disallow-privileged-containers (Enforce) - require-resource-limits (Enforce) - require-labels (Audit - standard k8s labels) - require-run-as-non-root (Audit) - disallow-latest-tag (Enforce - GitOps reproducibility) - Mutating policy: - add-default-securitycontext (seccomp, drop caps, read-only fs) - System namespaces excluded (kube-system, kyverno, istio-system) - Auto-discovered by ArgoCD ApplicationSet Reference: CIS Kubernetes Benchmark, Pod Security Standards
This commit is contained in:
62
infrastructure/kyverno/kustomization.yaml
Normal file
62
infrastructure/kyverno/kustomization.yaml
Normal file
@@ -0,0 +1,62 @@
|
||||
# infrastructure/kyverno/kustomization.yaml
|
||||
# Kyverno Policy Engine - GitOps-native Kubernetes policy enforcement
|
||||
# CNCF Graduated project, integrates seamlessly with ArgoCD
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
|
||||
namespace: kyverno
|
||||
|
||||
resources:
|
||||
- namespace.yaml
|
||||
- policies/
|
||||
|
||||
# Kyverno deployment via Helm
|
||||
helmCharts:
|
||||
- name: kyverno
|
||||
repo: https://kyverno.github.io/kyverno/
|
||||
version: "3.3.4"
|
||||
releaseName: kyverno
|
||||
namespace: kyverno
|
||||
valuesInline:
|
||||
# Admission controller replicas for HA
|
||||
admissionController:
|
||||
replicas: 3
|
||||
resources:
|
||||
limits:
|
||||
memory: 512Mi
|
||||
requests:
|
||||
cpu: 100m
|
||||
memory: 256Mi
|
||||
# Background controller for generate/mutate policies
|
||||
backgroundController:
|
||||
replicas: 2
|
||||
resources:
|
||||
limits:
|
||||
memory: 256Mi
|
||||
requests:
|
||||
cpu: 50m
|
||||
memory: 128Mi
|
||||
# Reports controller for policy reports
|
||||
reportsController:
|
||||
replicas: 2
|
||||
# Cleanup controller
|
||||
cleanupController:
|
||||
replicas: 2
|
||||
# Enable policy exception support
|
||||
features:
|
||||
policyExceptions:
|
||||
enabled: true
|
||||
namespace: "kyverno"
|
||||
# Webhooks config
|
||||
config:
|
||||
webhooks:
|
||||
# Exclude system namespaces from validation
|
||||
- namespaceSelector:
|
||||
matchExpressions:
|
||||
- key: kubernetes.io/metadata.name
|
||||
operator: NotIn
|
||||
values:
|
||||
- kube-system
|
||||
- kube-public
|
||||
- kube-node-lease
|
||||
- kyverno
|
||||
10
infrastructure/kyverno/namespace.yaml
Normal file
10
infrastructure/kyverno/namespace.yaml
Normal file
@@ -0,0 +1,10 @@
|
||||
# infrastructure/kyverno/namespace.yaml
|
||||
apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
name: kyverno
|
||||
labels:
|
||||
app.kubernetes.io/name: kyverno
|
||||
app.kubernetes.io/component: policy-engine
|
||||
# Exempt from Pod Security Standards (Kyverno needs privileges)
|
||||
pod-security.kubernetes.io/enforce: privileged
|
||||
@@ -0,0 +1,68 @@
|
||||
# infrastructure/kyverno/policies/add-default-securitycontext.yaml
|
||||
# Mutating policy: adds secure defaults to pods missing securityContext
|
||||
# Implements defense-in-depth by setting secure defaults
|
||||
apiVersion: kyverno.io/v1
|
||||
kind: ClusterPolicy
|
||||
metadata:
|
||||
name: add-default-securitycontext
|
||||
annotations:
|
||||
policies.kyverno.io/title: Add Default Security Context
|
||||
policies.kyverno.io/category: Best Practices
|
||||
policies.kyverno.io/severity: low
|
||||
policies.kyverno.io/subject: Pod
|
||||
policies.kyverno.io/description: >-
|
||||
Mutating policy that adds secure default securityContext to pods
|
||||
that don't specify one. Reduces attack surface by dropping
|
||||
capabilities and making filesystem read-only where possible.
|
||||
pod-policies.kyverno.io/autogen-controllers: DaemonSet,Deployment,Job,StatefulSet,ReplicaSet
|
||||
spec:
|
||||
# Mutate rules apply during admission
|
||||
rules:
|
||||
- name: add-pod-security-context
|
||||
match:
|
||||
any:
|
||||
- resources:
|
||||
kinds:
|
||||
- Pod
|
||||
exclude:
|
||||
any:
|
||||
- resources:
|
||||
namespaces:
|
||||
- kube-system
|
||||
- kyverno
|
||||
- istio-system
|
||||
mutate:
|
||||
patchStrategicMerge:
|
||||
spec:
|
||||
# Add pod-level securityContext if missing
|
||||
+(securityContext):
|
||||
seccompProfile:
|
||||
type: RuntimeDefault
|
||||
# Don't allow privilege escalation by default
|
||||
runAsNonRoot: true
|
||||
- name: add-container-security-context
|
||||
match:
|
||||
any:
|
||||
- resources:
|
||||
kinds:
|
||||
- Pod
|
||||
exclude:
|
||||
any:
|
||||
- resources:
|
||||
namespaces:
|
||||
- kube-system
|
||||
- kyverno
|
||||
- istio-system
|
||||
mutate:
|
||||
foreach:
|
||||
- list: "request.object.spec.containers"
|
||||
patchStrategicMerge:
|
||||
spec:
|
||||
containers:
|
||||
- name: "{{ element.name }}"
|
||||
+(securityContext):
|
||||
allowPrivilegeEscalation: false
|
||||
capabilities:
|
||||
drop:
|
||||
- ALL
|
||||
readOnlyRootFilesystem: true
|
||||
60
infrastructure/kyverno/policies/disallow-latest-tag.yaml
Normal file
60
infrastructure/kyverno/policies/disallow-latest-tag.yaml
Normal file
@@ -0,0 +1,60 @@
|
||||
# infrastructure/kyverno/policies/disallow-latest-tag.yaml
|
||||
# Prevents use of 'latest' image tag for reproducibility
|
||||
# GitOps best practice: always use explicit image versions
|
||||
apiVersion: kyverno.io/v1
|
||||
kind: ClusterPolicy
|
||||
metadata:
|
||||
name: disallow-latest-tag
|
||||
annotations:
|
||||
policies.kyverno.io/title: Disallow Latest Tag
|
||||
policies.kyverno.io/category: Best Practices
|
||||
policies.kyverno.io/severity: medium
|
||||
policies.kyverno.io/subject: Pod
|
||||
policies.kyverno.io/description: >-
|
||||
The 'latest' tag is mutable and can change unexpectedly, making
|
||||
deployments non-reproducible. This policy requires explicit
|
||||
image tags for GitOps traceability.
|
||||
spec:
|
||||
validationFailureAction: Enforce
|
||||
background: true
|
||||
rules:
|
||||
- name: require-image-tag
|
||||
match:
|
||||
any:
|
||||
- resources:
|
||||
kinds:
|
||||
- Pod
|
||||
exclude:
|
||||
any:
|
||||
- resources:
|
||||
namespaces:
|
||||
- kube-system
|
||||
- kyverno
|
||||
validate:
|
||||
message: "Images must use an explicit tag (not 'latest'). Specify a version tag like ':v1.2.3' or SHA digest."
|
||||
pattern:
|
||||
spec:
|
||||
containers:
|
||||
- image: "*:*"
|
||||
=(initContainers):
|
||||
- image: "*:*"
|
||||
- name: validate-not-latest
|
||||
match:
|
||||
any:
|
||||
- resources:
|
||||
kinds:
|
||||
- Pod
|
||||
exclude:
|
||||
any:
|
||||
- resources:
|
||||
namespaces:
|
||||
- kube-system
|
||||
- kyverno
|
||||
validate:
|
||||
message: "The 'latest' tag is not allowed. Use a specific version tag."
|
||||
pattern:
|
||||
spec:
|
||||
containers:
|
||||
- image: "!*:latest"
|
||||
=(initContainers):
|
||||
- image: "!*:latest"
|
||||
47
infrastructure/kyverno/policies/disallow-privileged.yaml
Normal file
47
infrastructure/kyverno/policies/disallow-privileged.yaml
Normal file
@@ -0,0 +1,47 @@
|
||||
# infrastructure/kyverno/policies/disallow-privileged.yaml
|
||||
# Prevents pods from running as privileged containers
|
||||
# Security baseline: CIS Benchmark 5.2.1
|
||||
apiVersion: kyverno.io/v1
|
||||
kind: ClusterPolicy
|
||||
metadata:
|
||||
name: disallow-privileged-containers
|
||||
annotations:
|
||||
policies.kyverno.io/title: Disallow Privileged Containers
|
||||
policies.kyverno.io/category: Pod Security Standards (Baseline)
|
||||
policies.kyverno.io/severity: high
|
||||
policies.kyverno.io/subject: Pod
|
||||
policies.kyverno.io/description: >-
|
||||
Privileged containers have all Linux capabilities and can access
|
||||
host resources. This policy prevents privileged containers from
|
||||
being created except in system namespaces.
|
||||
spec:
|
||||
validationFailureAction: Enforce
|
||||
background: true
|
||||
rules:
|
||||
- name: privileged-containers
|
||||
match:
|
||||
any:
|
||||
- resources:
|
||||
kinds:
|
||||
- Pod
|
||||
exclude:
|
||||
any:
|
||||
- resources:
|
||||
namespaces:
|
||||
- kube-system
|
||||
- kyverno
|
||||
- istio-system
|
||||
- cert-manager
|
||||
validate:
|
||||
message: "Privileged containers are not allowed. Set securityContext.privileged to false."
|
||||
pattern:
|
||||
spec:
|
||||
containers:
|
||||
- securityContext:
|
||||
privileged: "false"
|
||||
=(initContainers):
|
||||
- securityContext:
|
||||
privileged: "false"
|
||||
=(ephemeralContainers):
|
||||
- securityContext:
|
||||
privileged: "false"
|
||||
12
infrastructure/kyverno/policies/kustomization.yaml
Normal file
12
infrastructure/kyverno/policies/kustomization.yaml
Normal file
@@ -0,0 +1,12 @@
|
||||
# infrastructure/kyverno/policies/kustomization.yaml
|
||||
# Security policies for cluster-wide enforcement
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
|
||||
resources:
|
||||
- disallow-privileged.yaml
|
||||
- require-resource-limits.yaml
|
||||
- require-labels.yaml
|
||||
- require-non-root.yaml
|
||||
- disallow-latest-tag.yaml
|
||||
- add-default-securitycontext.yaml
|
||||
69
infrastructure/kyverno/policies/require-labels.yaml
Normal file
69
infrastructure/kyverno/policies/require-labels.yaml
Normal file
@@ -0,0 +1,69 @@
|
||||
# infrastructure/kyverno/policies/require-labels.yaml
|
||||
# Enforces standard labeling for all workloads
|
||||
# Enables proper resource organization and cost tracking
|
||||
apiVersion: kyverno.io/v1
|
||||
kind: ClusterPolicy
|
||||
metadata:
|
||||
name: require-labels
|
||||
annotations:
|
||||
policies.kyverno.io/title: Require Labels
|
||||
policies.kyverno.io/category: Best Practices
|
||||
policies.kyverno.io/severity: medium
|
||||
policies.kyverno.io/subject: Pod, Deployment, StatefulSet, DaemonSet
|
||||
policies.kyverno.io/description: >-
|
||||
Labels are essential for organizing, filtering, and managing
|
||||
Kubernetes resources. This policy requires standard labels on
|
||||
all workloads.
|
||||
spec:
|
||||
validationFailureAction: Audit # Start in audit mode
|
||||
background: true
|
||||
rules:
|
||||
- name: check-deployment-labels
|
||||
match:
|
||||
any:
|
||||
- resources:
|
||||
kinds:
|
||||
- Deployment
|
||||
- StatefulSet
|
||||
- DaemonSet
|
||||
exclude:
|
||||
any:
|
||||
- resources:
|
||||
namespaces:
|
||||
- kube-system
|
||||
- kyverno
|
||||
validate:
|
||||
message: "Workloads must have 'app.kubernetes.io/name' and 'app.kubernetes.io/part-of' labels."
|
||||
pattern:
|
||||
metadata:
|
||||
labels:
|
||||
app.kubernetes.io/name: "?*"
|
||||
app.kubernetes.io/part-of: "?*"
|
||||
- name: check-pod-labels
|
||||
match:
|
||||
any:
|
||||
- resources:
|
||||
kinds:
|
||||
- Pod
|
||||
exclude:
|
||||
any:
|
||||
- resources:
|
||||
namespaces:
|
||||
- kube-system
|
||||
- kyverno
|
||||
# Exclude pods created by controllers (they inherit parent labels)
|
||||
selector:
|
||||
matchLabels:
|
||||
app.kubernetes.io/managed-by: "*"
|
||||
preconditions:
|
||||
all:
|
||||
# Only check standalone pods (not owned by ReplicaSet, etc.)
|
||||
- key: "{{ request.object.metadata.ownerReferences[] || `[]` | length(@) }}"
|
||||
operator: Equals
|
||||
value: 0
|
||||
validate:
|
||||
message: "Pods must have 'app.kubernetes.io/name' label."
|
||||
pattern:
|
||||
metadata:
|
||||
labels:
|
||||
app.kubernetes.io/name: "?*"
|
||||
54
infrastructure/kyverno/policies/require-non-root.yaml
Normal file
54
infrastructure/kyverno/policies/require-non-root.yaml
Normal file
@@ -0,0 +1,54 @@
|
||||
# infrastructure/kyverno/policies/require-non-root.yaml
|
||||
# Requires containers to run as non-root user
|
||||
# Security baseline: CIS Benchmark 5.2.6
|
||||
apiVersion: kyverno.io/v1
|
||||
kind: ClusterPolicy
|
||||
metadata:
|
||||
name: require-run-as-non-root
|
||||
annotations:
|
||||
policies.kyverno.io/title: Require Run As Non-Root
|
||||
policies.kyverno.io/category: Pod Security Standards (Restricted)
|
||||
policies.kyverno.io/severity: high
|
||||
policies.kyverno.io/subject: Pod
|
||||
policies.kyverno.io/description: >-
|
||||
Running as root inside a container is a security risk. If a
|
||||
container breakout occurs, root in the container could become
|
||||
root on the host. This policy requires containers to run as
|
||||
a non-root user.
|
||||
spec:
|
||||
validationFailureAction: Audit # Audit first, Enforce after baseline
|
||||
background: true
|
||||
rules:
|
||||
- name: run-as-non-root
|
||||
match:
|
||||
any:
|
||||
- resources:
|
||||
kinds:
|
||||
- Pod
|
||||
exclude:
|
||||
any:
|
||||
- resources:
|
||||
namespaces:
|
||||
- kube-system
|
||||
- kyverno
|
||||
- istio-system
|
||||
validate:
|
||||
message: "Containers must run as non-root. Set runAsNonRoot: true or specify a non-root runAsUser."
|
||||
anyPattern:
|
||||
# Pattern 1: Pod-level runAsNonRoot
|
||||
- spec:
|
||||
securityContext:
|
||||
runAsNonRoot: true
|
||||
# Pattern 2: Container-level runAsNonRoot
|
||||
- spec:
|
||||
containers:
|
||||
- securityContext:
|
||||
runAsNonRoot: true
|
||||
# Pattern 3: Explicit non-root UID (>= 1000)
|
||||
- spec:
|
||||
securityContext:
|
||||
runAsUser: ">999"
|
||||
- spec:
|
||||
containers:
|
||||
- securityContext:
|
||||
runAsUser: ">999"
|
||||
41
infrastructure/kyverno/policies/require-resource-limits.yaml
Normal file
41
infrastructure/kyverno/policies/require-resource-limits.yaml
Normal file
@@ -0,0 +1,41 @@
|
||||
# infrastructure/kyverno/policies/require-resource-limits.yaml
|
||||
# Ensures all pods have resource limits defined
|
||||
# Prevents resource exhaustion and enables proper scheduling
|
||||
apiVersion: kyverno.io/v1
|
||||
kind: ClusterPolicy
|
||||
metadata:
|
||||
name: require-resource-limits
|
||||
annotations:
|
||||
policies.kyverno.io/title: Require Resource Limits
|
||||
policies.kyverno.io/category: Best Practices
|
||||
policies.kyverno.io/severity: medium
|
||||
policies.kyverno.io/subject: Pod
|
||||
policies.kyverno.io/description: >-
|
||||
Resource limits prevent a single workload from consuming excessive
|
||||
cluster resources. This policy requires all containers to define
|
||||
CPU and memory limits.
|
||||
spec:
|
||||
validationFailureAction: Enforce
|
||||
background: true
|
||||
rules:
|
||||
- name: validate-resources
|
||||
match:
|
||||
any:
|
||||
- resources:
|
||||
kinds:
|
||||
- Pod
|
||||
exclude:
|
||||
any:
|
||||
- resources:
|
||||
namespaces:
|
||||
- kube-system
|
||||
- kyverno
|
||||
validate:
|
||||
message: "CPU and memory limits are required. Add resources.limits.cpu and resources.limits.memory."
|
||||
pattern:
|
||||
spec:
|
||||
containers:
|
||||
- resources:
|
||||
limits:
|
||||
memory: "?*"
|
||||
cpu: "?*"
|
||||
Reference in New Issue
Block a user