Skip to content

Add a cel function to X.509 templates - #1115

Open
maraino wants to merge 8 commits into
masterfrom
mariano/cel
Open

Add a cel function to X.509 templates#1115
maraino wants to merge 8 commits into
masterfrom
mariano/cel

Conversation

@maraino

@maraino maraino commented Aug 26, 2026

Copy link
Copy Markdown
Contributor

This commit adds a "cel" template function that compiles and evaluates a CEL expression against the template data. It allows templates to do filtering, mapping and conditional logic that is awkward to express with Go's text/template.

The CEL environment exposes the usual template keys as typed variables: Subject, SANs, Token, Webhooks, Insecure, AuthorizationCrt, AuthorizationChain and CertificateRequest. The x509util and crypto/x509 structs are registered as native types, honoring a "cel" struct tag, and the strings, encoders, lists, sets, network, regex and optional types extensions are enabled.

Expressions are compiled with cel.CostLimit(10000) to bound the amount of work a single expression can do.

For example:

{{cel "SANs.filter(s, s.Value.contains(\"foo\")).map(s, s.Value)"}}

This commit adds a "cel" template function that compiles and evaluates a
CEL expression against the template data. It allows templates to do
filtering, mapping and conditional logic that is awkward to express with
Go's text/template.

The CEL environment exposes the usual template keys as typed variables:
Subject, SANs, Token, Webhooks, Insecure, AuthorizationCrt,
AuthorizationChain and CertificateRequest. The x509util and crypto/x509
structs are registered as native types, honoring a "cel" struct tag, and
the strings, encoders, lists, sets, network, regex and optional types
extensions are enabled.

Expressions are compiled with cel.CostLimit(1000) to bound the amount of
work a single expression can do.

For example:

```
{{cel "SANs.filter(s, s.Value.contains(\"foo\")).map(s, s.Value)"}}
```
Add a "cel" built-in that evaluates a CEL expression against the
template data:

    {{ cel "Token.sub" }}
    {{ cel "Subject.CommonName" | toJson }}

Each package builds a CEL environment declaring its template data
variables and native types, on top of shared options (optional types,
strings, encoders, lists, sets, network, regex, and two-variable
comprehensions) from internal/templates.

The environment is built lazily and compiled programs are cached in a
new fixed-capacity LRU cache (internal/lru), keeping compilation out of
the signing path. Evaluation is metered with a cost limit so a template
expression cannot make signing arbitrarily expensive.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants