CEL Expressions Troubleshooting Guide

Introduction

This guide helps debug and troubleshoot Common Expression Language (CEL) expressions in Kyverno policies, based on actual implementation details and real user issues from the Kyverno codebase.

Verified CEL Variables

Based on the actual implementation, these are the confirmed CEL variables available:

Core Variables (Always Available)

  • object - The incoming Kubernetes resource
  • oldObject - The existing object (null for CREATE operations)
  • request - The admission request information

Additional Variables (Implementation Status Verified)

  • namespaceObject - Available in policies (confirmed in codebase)
  • authorizer - Limited availability (GitHub issue #8021 shows partial implementation)
  • params - Available when using parameterized policies

Source: Issues #8021, #11060, and ValidatingPolicy documentation

Real Error Patterns (From GitHub Issues)

1. Variable Context Issues

Error from Issue #11060:

Creating configmaps in namespace '{{namespace}}' is not allowed

Root Cause: Variable syntax {{ }} doesn’t work in CEL expressions.

Verified Solution:

 1# Wrong - from actual failing example
 2validate:
 3  cel:
 4    expressions:
 5    - expression: "namespaceObject.metadata.name == '{{namespace}}'"
 6
 7# Correct - working pattern  
 8validate:
 9  cel:
10    expressions:
11    - expression: "namespaceObject.metadata.name == request.namespace"

2. CustomResource Matching Errors

Error from Issue #10313:

no unique match for kind MyCustomResource

Root Cause: CEL policies require explicit API group/version for CRDs.

Verified Solution:

 1# Wrong - causes the error above
 2match:
 3  any:
 4  - resources:
 5      kinds:
 6      - MyCustomResource
 7
 8# Correct - from issue resolution
 9match:
10  any:
11  - resources:
12      kinds:
13      - example.com/v1/MyCustomResource

3. CEL Expression Warnings

From Issue #9605: Currently, Kyverno doesn’t block policy creation with CEL warnings due to ValidatingAdmissionPolicy variable bugs.

Current Behavior: Policies with CEL warnings are created but may not work as expected.

Workaround: Validate expressions manually before applying policies.

Debugging Strategies (Verified Working)

1. Enable Debug Logging

From Kyverno configuration documentation:

1# Increase logging verbosity to see CEL evaluation
2containers:
3- name: kyverno
4  args:
5  - -v=4  # Shows variable substitution details

2. Use dumpPayload for Request Inspection

From troubleshooting documentation:

1# Add to admission controller
2containers:
3- name: kyverno
4  args:
5  - --dumpPayload=true  # Shows full AdmissionReview content

Note: This has performance impact - remove after debugging.

3. Progressive Expression Testing

Start with simple expressions and build complexity:

1# Step 1: Basic existence check
2expression: "has(object.spec)"
3
4# Step 2: Add specific field
5expression: "has(object.spec.containers)"
6
7# Step 3: Add validation logic
8expression: "has(object.spec.containers) && object.spec.containers.size() > 0"

Known Limitations (From Codebase)

1. Variable Composition Status

From Issue #8050: Variable composition in CEL expressions is planned but implementation details are evolving.

Current Status: Basic variables work, but complex composition may have limitations.

2. Context Variable Access

From Issue #11060: Context variables from apiCall cannot be directly used in CEL expressions.

Current Workaround: Use preconditions with traditional variable syntax, then simple CEL validation.

3. Built-in Variable Coverage

From Issue #11827: Several Kyverno built-in variables don’t have CEL equivalents yet:

  • serviceAccountName - Must be extracted from request.userInfo.username
  • serviceAccountNamespace - Must be parsed manually
  • images - CEL implementation in progress

Performance Considerations (From Codebase)

1. CEL Expression Caching

From Issue #10754: CEL expressions are compiled separately for each policy, even if identical.

Current Impact: Duplicate expressions across policies cause redundant compilation.

Planned Improvement: Expression caching and reuse (in development).

2. Webhook Timeouts

From installation documentation:

1spec:
2  webhookConfiguration:
3    timeoutSeconds: 30  # Default is 10s, max is 30s

Recommendation: Increase timeout for complex CEL expressions.

Testing Strategies (Verified Working)

1. CLI Testing

From Kyverno CLI documentation:

1# Test CEL policies before applying
2kyverno apply policy.yaml --resource test-resource.yaml
3
4# Validate policy syntax
5kyverno validate policy.yaml

2. Dry-Run Validation

1# Test against live cluster without applying
2kubectl apply -f test-resource.yaml --dry-run=server

3. Policy Reports Analysis

1# Check policy evaluation results
2kubectl get polr -A
3kubectl describe polr <policy-report-name>

Common Workarounds (From Community)

1. Complex Variable Access

Issue: CEL can’t access all context variables directly.

Workaround (from issue discussions):

 1# Use preconditions for complex variable logic
 2preconditions:
 3  all:
 4  - key: "{{ request.userInfo.username }}"
 5    operator: NotEquals  
 6    value: "system:admin"
 7validate:
 8  cel:
 9    expressions:
10    - expression: "object.spec.replicas > 0"  # Simple CEL validation

2. Resource Library Alternative

Issue: Resource library access in CEL expressions has limitations.

Workaround: Use traditional context with apiCall:

1context:
2- name: configmap
3  configMap:
4    name: allowed-values
5    namespace: kyverno
6validate:
7  cel:
8    expressions:
9    - expression: "object.metadata.name != 'forbidden'"  # Basic CEL check

Safe CEL Patterns (Verified Working)

1. Basic Field Validation

1# Confirmed working pattern
2validate:
3  cel:
4    expressions:
5    - expression: "has(object.metadata.labels.app)"
6    - expression: "object.spec.replicas >= 1"
7    - expression: "!object.spec.containers.exists(c, has(c.securityContext.privileged) && c.securityContext.privileged)"

2. Namespace Object Access

1# Confirmed working (from CLI tests)
2validate:
3  cel:
4    expressions:
5    - expression: "namespaceObject.metadata.name != 'default'"
6    - expression: "has(namespaceObject.metadata.labels.environment)"

3. Request Information

1# Verified available fields
2validate:
3  cel:
4    expressions:
5    - expression: "request.operation == 'CREATE'"
6    - expression: "request.userInfo.username != 'system:admin'"

Current Implementation Status

Fully Supported

  • ✅ Basic object validation
  • ✅ Simple field existence checks
  • ✅ Namespace object access
  • ✅ Request metadata access
  • ✅ List operations (all, exists, size)

Partially Supported

  • ⚠️ Variable composition (basic cases work)
  • ⚠️ Context variable access (limited)
  • ⚠️ Resource library functions (some restrictions)

In Development

  • 🔄 CEL expression caching (Issue #10754)
  • 🔄 Built-in variable parity (Issue #11827)
  • 🔄 Enhanced context access (Issue #11060)

Getting Help

When reporting CEL issues:

  1. Include Kyverno version: Check with kubectl get pods -n kyverno
  2. Provide policy YAML: Complete policy that reproduces the issue
  3. Share exact error: From policy reports or admission controller logs
  4. Reference similar issues: Check existing GitHub issues for patterns

Useful Commands for Bug Reports:

1# Get admission controller logs
2kubectl logs -n kyverno deployment/kyverno-admission-controller
3
4# Get policy reports
5kubectl get polr -A -o yaml
6
7# Check policy status
8kubectl describe cpol <policy-name>

Note: This guide reflects the current implementation status. Features marked as “in development” may change. Always test policies in non-production environments first.


Last modified December 31, 2025 at 4:41 AM PST: Docs/cel troubleshooting guide (#1632) (8942d28)