feat(ivpol): add CEL expression support for keyless identity fields#15479
Open
jzeng4 wants to merge 5 commits intokyverno:mainfrom
Open
feat(ivpol): add CEL expression support for keyless identity fields#15479jzeng4 wants to merge 5 commits intokyverno:mainfrom
jzeng4 wants to merge 5 commits intokyverno:mainfrom
Conversation
2 tasks
Signed-off-by: Junyuan Zeng <jzeng04@gmail.com>
Signed-off-by: Junyuan Zeng <jzeng04@gmail.com>
Member
|
this PR, if I understand it correctly, implements a breaking change into the IVPOL API, which was marked as stable in 1.17.0. So we can't merge this without introducing a it as a new API Version or in a backward compatible way. In other situations we have for example dedicated fields for static and expressions like:
You also have to make a related PR in the API repo instead of replacing the lib path. |
2 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Explanation
This PR adds CEL expression support to the
issuer,subject,issuerRegExp, andsubjectRegExpfields of theIdentitytype inImageValidatingPolicy's keyless (Fulcio/Sigstore) configuration. Previously these fields only accepted static strings, which forced users to write one policy per image when they needed per-image signing identity pinning. With this change, each field accepts either a plain string (unchanged) or a{expression: "..."}CEL expression that is evaluated at admission time with full access to the request context — enabling a single policy to enforce precise per-image signing identities across an entire organization.This is a backward-compatible addition: all existing policies using plain string values continue to work without modification.
Related issue
Fixes #15398
Depend on kyverno/api#64
Milestone of this PR
Documentation (required for features)
My PR contains new or altered behavior to Kyverno.
What type of PR is this
/kind api-change
/kind feature
Proposed Changes
The
Identitystruct fields (issuer,subject,issuerRegExp,subjectRegExp) are changed from plainstringto*StringOrExpression— the same union type already used forcert,certChain, and Notarycertsfields. A customUnmarshalJSONonStringOrExpressionensures that a plain YAML string (e.g.issuer: "https://...") is transparently decoded intoStringOrExpression{Value: "..."}, so no existing policies need to be updated.At policy compile time, any
{expression: "..."}values are compiled into CEL programs. At admission time, those programs are evaluated against the full request context (includingobject,images,request, andvariables) and their string results are substituted as the identity values passed to cosign'sCheckOpts.Identities. This meanssubjectandsubjectRegExpare matched against the Fulcio certificate's SAN URI, andissuer/issuerRegExpagainst the OIDC issuer OID extension, exactly as before — the only difference is the values can now be computed rather than hardcoded.Changes:
api/policies.kyverno.io/v1alpha1/imagevalidating_policy.go— changeIdentityfields to
*StringOrExpression; add backward-compatibleUnmarshalJSONonStringOrExpressionapi/policies.kyverno.io/v1alpha1/zz_generated.deepcopy.go— updateIdentity.DeepCopyIntoandKeyless.DeepCopyIntofor the new pointer fieldspkg/imageverification/variables/attestors.go— compile and evaluate CEL expressionsfor identity fields
pkg/imageverification/imageverifiers/cosign/opts.go— read.Valuefrom pointerfields when building
cosign.CheckOptsProof Manifests
Example 1: Backward-compatible plain string (no change needed)
Existing policies continue to work unchanged:
Example 2: Derive subject from a pod label (per-repo identity, one policy for all services)
The expected signer workflow is derived from the
github-repopod label at admissiontime.
subjectandsubjectRegExpmatch against the Fulcio certificate's SAN URI;issuer/issuerRegExpmatch against the OIDC issuer OID extension on the certificate.Pod that is admitted (label matches the signing identity):
Pod that is denied (label does not match the actual signing identity):
Example 3: Derive subject from the namespace
Enforce a per-team signing convention where each namespace maps to a GitHub org team:
Example 4: Derive subject from the image reference (single-container pods)
Use
images.containers[0]to extract the org and repo from the image reference itself.Note: this approach works reliably for single-container pods; for multi-container pods,
use a pod label (Example 2) or policy variable instead.
Available CEL variables in identity expressions
Identity expressions are evaluated once per admission request with the same context
available to
validationsexpressions:objectimagesmap<string, list<string>>images.containers,images.initContainersrequest.namespace,.name,.userInfo)namespaceObjectvariablesChecklist
Co-authored-byorAssisted-bytrailer).Further Comments
The design deliberately mirrors the existing
StringOrExpressionpattern used forcert,certChain, and Notarycertsfields, keeping the API consistent. TheUnmarshalJSONapproach for backward compatibility is the same technique used elsewherein the codebase.
Identity expressions are resolved once per admission request (not per image). For
per-image identity derived from the image reference itself,
images.containers[0]canbe used for single-container pods; for multi-container workloads, the recommended
approach is to encode the expected identity in a pod label or annotation and reference it