Kyverno
Kyverno Policy
- 2 types: Policy and ClusterPolicy
- Multiple Rules
- Match / Exclude
-- Match resources
kind is mandatory. names, namespaces, operations, selector are optional.
Wildcards * supported in kinds, names, namespaces
All are AND condition.
Any means OR condition
We can mention based on who created
exclude:
any:
- clusterRoles:
- cluster-admin
- subjects:
- kind: User
name: John
match AND exclude
exclude must be a subset of match
- Action
1. Validate ( allow / deny )
2. Mutate
3. Generate new K8s object
4. Verify image (Cosign/Sigstore)
- Enforce / Audit
* It uses JAMESPath
- Filter JSON
# Returns a list of container objects that match the condition
{{ request.object.spec.containers[?starts_with(image, 'nginx')] }}
validate:
message: "Nginx images are not allowed!"
deny:
conditions:
all:
# Filter the list. Use length() to count.
# If count > 0, it means a violation exists -> Block.
- key: "{{ request.object.spec.containers[?starts_with(image, 'nginx')] | length(@) }}"
operator: GreaterThan
value: 0
- pipe
Used to extract a specific field from a complex object into a flat list.
# Input: List of container objects
# Output: ["nginx:latest", "redis:alpine", "busybox"]
key: "{{ request.object.spec.containers[].image }}"
kyverno jp query -i object.json 'spec.containers[].name'
Combo (Filter + Pipe): “Get the containerPort of the container named ‘app’”
request.object.spec.containers[?name == 'app'].ports[].containerPort
You want to find the names of all volumes that are of type emptyDir.
spec.volumes[?emptyDir != null].name
kyverno jp query -i object.json "spec.volumes[?emptyDir != null]"
- null handling
Risk: {{ request.object.metadata.labels.team }} (If null -> Error).
Safe: {{ request.object.metadata.labels.team || '' }} (If null -> treat as empty string).
- The length function
Example: “A Pod must not have more than 3 containers.”
validate:
deny:
conditions:
all:
- key: "{{ request.object.spec.containers | length(@) }}"
operator: GreaterThan
value: 3
- if / else
- sum
- contain means exist : contains(request.object.metadata.labels, 'production')
advance mutate foreach
mutate:
foreach:
- list: "request.object.spec.containers"
patchStrategicMerge:
spec:
containers:
- name: "{{ element.name }}"
securityContext:
readOnlyRootFilesystem: true
* Aut-Gen: If rule for pod then automatically generate rules for Deployment, StatefulSet, DaemonSet, etc.
https://release-1-8-0.kyverno.io/docs/writing-policies/autogen/
Generate rule has synchronize flag
synchronize: true: Kyverno complete managed lifecycle
synchronize: false: Kyverno created for the first time then user can edit it manually without getting revert back like synchronize: true
* request.object is the incoming resource configuration (the new state) that is being submitted to Kubernetes API server
Documentation: https://kyverno.io/docs/policy-types/cluster-policy/variables/
# -------------------------------------------------------------
# ACTION: If Kyverno is dead, just let the request go through.
# -------------------------------------------------------------
failurePolicy: Ignore # or Fail
PolicyReport
PolicyReport stores the results of those rules.
The PolicyReport is essentially a “Health Check Report Card” for your Kubernetes resources.
Its main goal is Observability & Auditing.
It provides summary and then detail about all failures. For Example
apiVersion: wgpolicyk8s.io/v1alpha2
kind: PolicyReport
metadata:
name: polr-ns-default
namespace: default # It lives next to the Pod, not at the cluster level
labels:
app.kubernetes.io/managed-by: kyverno
summary:
pass: 0
fail: 1
warn: 0
error: 0
skip: 0
results:
- policy: require-labels # The name of the ClusterPolicy responsible
rule: check-for-team-label # The specific rule name
category: Best Practices
severity: medium
result: fail # The outcome (fail, pass, warn, error, skip)
message: "Validation error: label 'team' is required"
source: kyverno
resources: # The specific object that failed
- apiVersion: v1
kind: Pod
name: nginx
namespace: default
uid: a1b2c3d4-e5f6...
* Background scan never delete resource even with enforce mode
* For background scan following variable are not relevant
request.userInfo.*
request.operation
request.dryRun
serviceAccountName in admission context
Document: https://kyverno.io/docs/policy-reports/background/
* Cleanup policy delete pods
https://kyverno.io/docs/policy-types/cleanup-policy/
Kyverno CLI
* for given resource, policy is pass or fail
kyverno apply policy.yaml --resource pod.yaml
* test JAMESPath expression against JSON
kyverno jp query -i object.json 'metadata.labels'
* Check policy YAML is written correctly or not
kyverno validate policy.yaml
External Data Source
Purpose: It allows you to load data from outside into a variable before the rule logic (validate/mutate) runs.
In order to consume data from a ConfigMap in a rule, a context is required... The context data can then be referenced in the policy rule using JMESPath notation.
Kyverno supports 3 main data sources in context:
1. Kubernetes Resources (via API Call): Look up existing data in the cluster (e.g., ConfigMaps, Secrets, Services).
2. External APIs: Make an HTTP call to a service outside the cluster.
3. Image Registry: Fetch metadata about a container image (e.g., image size, architecture).
verifyImages:
- imageReferences:
- "ghcr.io/myorg/*"
attestors:
- entries:
- keys:
publicKeys: |-
-----BEGIN PUBLIC KEY-----
...
-----END PUBLIC KEY-----
https://main.kyverno.io/docs/policy-types/cluster-policy/external-data-sources/
Kyverno Mutate — JSON Patch
the standard patchStrategicMerge merges YAMLs together.
patchesJson6902 is a mutation method specific operations (RFC 6902 standard) to tell Kyverno exactly how to change the data.
Usage:
* Removing a field (impossible with standard merge).
* Adding an item to a specific position in a list (arrays).
* Replacing a value entirely without merging.
It follows the JSON Patch format:
* op: The action (add, remove, replace).
* path: The location of the field (e.g., /metadata/labels/mytag).
* value: The data to put there.
Example: “Add a sidecar container”
https://main.kyverno.io/docs/policy-types/cluster-policy/mutate/#rfc-6902-jsonpatch
TTL Default of Certification in Kyverno:
https://pkg.go.dev/github.com/kyverno/kyverno/pkg/tls
const (
CAValidityDuration = 365 * 24 * time.Hour // 365 days
TLSValidityDuration = 150 * 24 * time.Hour // 150 days
CertRenewalInterval = 12 * time.Hour // 12 hours
)
https://www.udemy.com/course/complete-certified-kyverno-associate-kca-exam-prep/
https://medium.com/@kienlt.qn/prepare-for-the-kyverno-certified-associate-kca-exam-c144906f9bc2
Concurrent Policies Generation Number Default!
PolicyException CRD
CEL
0 comments:
Post a Comment