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