Skip to content

Conversation

@janisz
Copy link
Collaborator

@janisz janisz commented Aug 27, 2025

Add CEL Template for Custom Expression-Based Checks

This PR introduces a new cel-expression template that enables users to write custom checks using the Common Expression Language (CEL). This powerful addition allows for flexible, expression-based validation of Kubernetes resources without requiring Go code changes.

🚀 Features

  • CEL Expression Template: New cel-expression template in pkg/templates/cel/template.go:18
  • Flexible Resource Validation: Supports any Kubernetes resource type through objectkinds.Any
  • Expression-Based Logic: Write custom validation logic using CEL syntax
  • Access to Full Context: CEL expressions have access to both the subject resource and all other objects in the cluster

🔧 How It Works

The template provides two variables to CEL expressions:

  • subject: The current Kubernetes resource being evaluated
  • objects: Array of all Kubernetes resources in the current context

CEL expressions should return:

  • An empty string "" if the check passes
  • A descriptive string message if the check fails

📝 Usage Examples

Replace complex template logic with simple CEL expressions:

Example 1: Forbidden Annotation Check

customChecks:
  - name: "cel-forbidden-annotation"
    description: "Detect forbidden reloader annotation"
    template: "cel-expression"
    scope:
      objectKinds:
        - DeploymentLike
    params:
      check: |
        has(subject.metadata.annotations) && 
        subject.metadata.annotations["reloader.stakater.com/auto"] == "true" ? 
        "Object has reloader annotation" : ""

Example 2: IRSA Role Validation

customChecks:
  - name: "invalid-irsa-role"
    description: "Validate EKS IRSA role ARN format"
    template: "cel-expression"
    scope:
      objectKinds:
        - ServiceAccount
    params:
      check: |
        subject.metadata.annotations["eks.amazonaws.com/role-arn"].matches("^arn:aws:iam::\\d{12}:role/[\\w+=,.@-]{1,64}$") ? 
        "" : "Invalid EKS IAM role ARN format"

🧪 Testing

  • E2E Tests: New test case in e2etests/bats-tests.sh demonstrates the CEL template replacing traditional forbidden annotation checks
  • Unit Tests: Comprehensive test coverage in pkg/templates/cel/template_test.go
  • Test Data: Real-world examples in e2etests/testdata/cel-config.yaml and tests/checks/cel.yml

💡 Benefits

  1. No Code Changes Required: Add custom checks through configuration
  2. Powerful Expression Language: Leverage CEL's rich syntax for complex validations
  3. Cluster-Wide Context: Access to all resources enables cross-resource validation
  4. Type Safety: CEL provides compile-time expression validation
  5. Performance: Efficient evaluation of expressions

🔄 Migration Path

This template can replace many existing specialized templates. For example, the forbidden annotation functionality previously requiring a dedicated template can now be implemented with a simple CEL expression (as shown in the e2e tests).

📚 Resources


🤖 Generated with Claude Code

Co-Authored-By: Claude noreply@anthropic.com

@janisz janisz requested a review from rhybrillou as a code owner August 27, 2025 17:26
@janisz janisz requested a review from rukletsov August 27, 2025 17:26
Copy link
Member

@rukletsov rukletsov left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like there is some AI-generated code in this PR. That's fine but I'd advice to add a note in the description about that .

Copy link
Member

@rukletsov rukletsov left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice and compact, I'm a fan!

I understand that due to being an expression language, a CEL check is a bit limited compared to a check in some procedural language, where you can accumulate state. I'm not sure how important this limitation will be so I'm in favor of merging CEL support.

We can then try to implement open requests for checks using this CEL template and see how far we can go.

janisz added 6 commits August 28, 2025 18:49
Signed-off-by: Tomasz Janiszewski <tomek@redhat.com>
Signed-off-by: Tomasz Janiszewski <tomek@redhat.com>
Signed-off-by: Tomasz Janiszewski <tomek@redhat.com>
Signed-off-by: Tomasz Janiszewski <tomek@redhat.com>
Signed-off-by: Tomasz Janiszewski <tomek@redhat.com>
Signed-off-by: Tomasz Janiszewski <tomek@redhat.com>
@janisz
Copy link
Collaborator Author

janisz commented Aug 28, 2025

This dangling service can accumulate state, which means it can basically do anything we've done with Go. The issue is that it can get messy for big projects, especially since we're keeping it all in one YAML file.

Moving forward, we should make CEL development easier by:

  • Letting developers load the check body from a separate file.
  • Adding more extension functions to keep checks small.
  • Providing a way to merge multiple configuration files so we don't have to keep all the checks in a single YAML.

@janisz janisz requested a review from rukletsov August 28, 2025 17:01
@janisz janisz merged commit 98ba3d9 into main Aug 29, 2025
8 checks passed
@janisz janisz deleted the cel branch August 29, 2025 08:52
janisz added a commit that referenced this pull request Oct 8, 2025
  This PR adds a fallback when decoding unknown resources to be able to handle
  CRDs. The schema validation could be then performed with kubeconform check
  from #1033 and CEL from
  #1012. This should fix
  #606

  Changes:
  - Modified parseObjects to use unstructured decoder as fallback for unknown resource types
  - Added comprehensive test suite covering standard K8s resources and CRDs
  - Maintained backward compatibility for existing decode error handling
  - Added test cases for Tekton Task CRD and other custom resources

  The fallback allows kube-linter to parse CRDs like Tekton Pipelines without
  failing, while delegating proper schema validation to specialized templates
  like kubeconform and CEL expressions.

  🤖 Generated with [Claude Code](https://claude.ai/code)

  Co-Authored-By: Claude <noreply@anthropic.com>

Signed-off-by: Tomasz Janiszewski <tomek@redhat.com>
janisz added a commit that referenced this pull request Oct 9, 2025
  This PR adds a fallback when decoding unknown resources to be able to handle
  CRDs. The schema validation could be then performed with kubeconform check
  from #1033 and CEL from
  #1012. This should fix
  #606

  Changes:
  - Modified parseObjects to use unstructured decoder as fallback for unknown resource types
  - Added comprehensive test suite covering standard K8s resources and CRDs
  - Maintained backward compatibility for existing decode error handling
  - Added test cases for Tekton Task CRD and other custom resources

  The fallback allows kube-linter to parse CRDs like Tekton Pipelines without
  failing, while delegating proper schema validation to specialized templates
  like kubeconform and CEL expressions.

  🤖 Generated with [Claude Code](https://claude.ai/code)

  Co-Authored-By: Claude <noreply@anthropic.com>

Signed-off-by: Tomasz Janiszewski <tomek@redhat.com>
janisz added a commit that referenced this pull request Oct 30, 2025
  This PR adds a fallback when decoding unknown resources to be able to handle
  CRDs. The schema validation could be then performed with kubeconform check
  from #1033 and CEL from
  #1012. This should fix
  #606

  Changes:
  - Modified parseObjects to use unstructured decoder as fallback for unknown resource types
  - Added comprehensive test suite covering standard K8s resources and CRDs
  - Maintained backward compatibility for existing decode error handling
  - Added test cases for Tekton Task CRD and other custom resources

  The fallback allows kube-linter to parse CRDs like Tekton Pipelines without
  failing, while delegating proper schema validation to specialized templates
  like kubeconform and CEL expressions.

  🤖 Generated with [Claude Code](https://claude.ai/code)

  Co-Authored-By: Claude <noreply@anthropic.com>

Signed-off-by: Tomasz Janiszewski <tomek@redhat.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants