diff --git a/api/kyverno/v2/updaterequest_types.go b/api/kyverno/v2/updaterequest_types.go index b62a4140d3..c3e57f8b7d 100644 --- a/api/kyverno/v2/updaterequest_types.go +++ b/api/kyverno/v2/updaterequest_types.go @@ -144,6 +144,11 @@ type RequestInfo struct { // UserInfo is the userInfo carried in the admission request. // +optional AdmissionUserInfo authenticationv1.UserInfo `json:"userInfo"` + + // DryRun indicates that modifications will definitely not be persisted for this request. + // Defaults to false. + // +optional + DryRun bool `json:"synchronize,omitempty"` } // AdmissionRequestInfoObject stores the admission request and operation details diff --git a/charts/kyverno/charts/crds/templates/kyverno.io/kyverno.io_updaterequests.yaml b/charts/kyverno/charts/crds/templates/kyverno.io/kyverno.io_updaterequests.yaml index 8c53322e15..8d5a2db8d2 100644 --- a/charts/kyverno/charts/crds/templates/kyverno.io/kyverno.io_updaterequests.yaml +++ b/charts/kyverno/charts/crds/templates/kyverno.io/kyverno.io_updaterequests.yaml @@ -660,6 +660,11 @@ spec: type: string nullable: true type: array + synchronize: + description: |- + DryRun indicates that modifications will definitely not be persisted for this request. + Defaults to false. + type: boolean userInfo: description: UserInfo is the userInfo carried in the admission request. diff --git a/cmd/cli/kubectl-kyverno/config/crds/cli.kyverno.io_userinfoes.yaml b/cmd/cli/kubectl-kyverno/config/crds/cli.kyverno.io_userinfoes.yaml index 7820dd44f8..180086a308 100644 --- a/cmd/cli/kubectl-kyverno/config/crds/cli.kyverno.io_userinfoes.yaml +++ b/cmd/cli/kubectl-kyverno/config/crds/cli.kyverno.io_userinfoes.yaml @@ -49,6 +49,11 @@ spec: type: string nullable: true type: array + synchronize: + description: |- + DryRun indicates that modifications will definitely not be persisted for this request. + Defaults to false. + type: boolean userInfo: description: UserInfo is the userInfo carried in the admission request. properties: diff --git a/cmd/cli/kubectl-kyverno/data/crds/cli.kyverno.io_userinfoes.yaml b/cmd/cli/kubectl-kyverno/data/crds/cli.kyverno.io_userinfoes.yaml index 7820dd44f8..180086a308 100644 --- a/cmd/cli/kubectl-kyverno/data/crds/cli.kyverno.io_userinfoes.yaml +++ b/cmd/cli/kubectl-kyverno/data/crds/cli.kyverno.io_userinfoes.yaml @@ -49,6 +49,11 @@ spec: type: string nullable: true type: array + synchronize: + description: |- + DryRun indicates that modifications will definitely not be persisted for this request. + Defaults to false. + type: boolean userInfo: description: UserInfo is the userInfo carried in the admission request. properties: diff --git a/config/crds/kyverno/kyverno.io_updaterequests.yaml b/config/crds/kyverno/kyverno.io_updaterequests.yaml index cf2f91d042..f12e5483db 100644 --- a/config/crds/kyverno/kyverno.io_updaterequests.yaml +++ b/config/crds/kyverno/kyverno.io_updaterequests.yaml @@ -654,6 +654,11 @@ spec: type: string nullable: true type: array + synchronize: + description: |- + DryRun indicates that modifications will definitely not be persisted for this request. + Defaults to false. + type: boolean userInfo: description: UserInfo is the userInfo carried in the admission request. diff --git a/config/install-latest-testing.yaml b/config/install-latest-testing.yaml index ebb9095376..aec1d2970a 100644 --- a/config/install-latest-testing.yaml +++ b/config/install-latest-testing.yaml @@ -48304,6 +48304,11 @@ spec: type: string nullable: true type: array + synchronize: + description: |- + DryRun indicates that modifications will definitely not be persisted for this request. + Defaults to false. + type: boolean userInfo: description: UserInfo is the userInfo carried in the admission request. diff --git a/docs/user/crd/index.html b/docs/user/crd/index.html index 70c10c58d8..a9861ab01c 100644 --- a/docs/user/crd/index.html +++ b/docs/user/crd/index.html @@ -6946,6 +6946,19 @@ Kubernetes authentication/v1.UserInfo

UserInfo is the userInfo carried in the admission request.

+ + +synchronize
+ +bool + + + +(Optional) +

DryRun indicates that modifications will definitely not be persisted for this request. +Defaults to false.

+ +
diff --git a/docs/user/crd/kyverno.v2.html b/docs/user/crd/kyverno.v2.html index 10e3e7c453..dc86a36855 100644 --- a/docs/user/crd/kyverno.v2.html +++ b/docs/user/crd/kyverno.v2.html @@ -2419,6 +2419,34 @@ Applicable only to policies that have validate.podSecurity subrule.

+ + + + synchronize + +
+ + + + + bool + + + + + + +

DryRun indicates that modifications will definitely not be persisted for this request. +Defaults to false.

+ + + + + + + + + diff --git a/pkg/engine/engine.go b/pkg/engine/engine.go index 0dec3ebc49..a7471b9084 100644 --- a/pkg/engine/engine.go +++ b/pkg/engine/engine.go @@ -100,7 +100,7 @@ func (e *engine) Validate( response = response.WithPolicyResponse(policyResponse) } response = response.WithStats(engineapi.NewExecutionStats(startTime, time.Now())) - e.reportMetrics(ctx, logger, policyContext.Operation(), policyContext.AdmissionOperation(), response) + e.reportMetrics(ctx, logger, policyContext.Operation(), policyContext.AdmissionOperation(), policyContext.AdmissionInfo(), response) return response } @@ -118,7 +118,7 @@ func (e *engine) Mutate( WithPolicyResponse(policyResponse) } response = response.WithStats(engineapi.NewExecutionStats(startTime, time.Now())) - e.reportMetrics(ctx, logger, policyContext.Operation(), policyContext.AdmissionOperation(), response) + e.reportMetrics(ctx, logger, policyContext.Operation(), policyContext.AdmissionOperation(), policyContext.AdmissionInfo(), response) return response } @@ -134,7 +134,7 @@ func (e *engine) Generate( response = response.WithPolicyResponse(policyResponse) } response = response.WithStats(engineapi.NewExecutionStats(startTime, time.Now())) - e.reportMetrics(ctx, logger, policyContext.Operation(), policyContext.AdmissionOperation(), response) + e.reportMetrics(ctx, logger, policyContext.Operation(), policyContext.AdmissionOperation(), policyContext.AdmissionInfo(), response) return response } @@ -153,7 +153,7 @@ func (e *engine) VerifyAndPatchImages( WithPatchedResource(patchedResource), innerIvm } response = response.WithStats(engineapi.NewExecutionStats(startTime, time.Now())) - e.reportMetrics(ctx, logger, policyContext.Operation(), policyContext.AdmissionOperation(), response) + e.reportMetrics(ctx, logger, policyContext.Operation(), policyContext.AdmissionOperation(), policyContext.AdmissionInfo(), response) return response, ivm } @@ -169,7 +169,7 @@ func (e *engine) ApplyBackgroundChecks( response = response.WithPolicyResponse(policyResponse) } response = response.WithStats(engineapi.NewExecutionStats(startTime, time.Now())) - e.reportMetrics(ctx, logger, policyContext.Operation(), policyContext.AdmissionOperation(), response) + e.reportMetrics(ctx, logger, policyContext.Operation(), policyContext.AdmissionOperation(), policyContext.AdmissionInfo(), response) return response } diff --git a/pkg/engine/metrics.go b/pkg/engine/metrics.go index 5357f91cf5..b2573e0706 100644 --- a/pkg/engine/metrics.go +++ b/pkg/engine/metrics.go @@ -2,10 +2,12 @@ package engine import ( "context" + "strconv" "strings" "github.com/go-logr/logr" kyvernov1 "github.com/kyverno/kyverno/api/kyverno/v1" + kyvernov2 "github.com/kyverno/kyverno/api/kyverno/v2" engineapi "github.com/kyverno/kyverno/pkg/engine/api" "github.com/kyverno/kyverno/pkg/metrics" "go.opentelemetry.io/otel/attribute" @@ -17,6 +19,7 @@ func (e *engine) reportMetrics( logger logr.Logger, operation kyvernov1.AdmissionOperation, admissionOperation bool, + admissionInfo kyvernov2.RequestInfo, response engineapi.EngineResponse, ) { if e.resultCounter == nil && e.durationHistogram == nil { @@ -71,6 +74,7 @@ func (e *engine) reportMetrics( attribute.String("rule_result", string(ruleResult)), attribute.String("rule_type", string(ruleType)), attribute.String("rule_execution_cause", string(executionCause)), + attribute.String("dry_run", strconv.FormatBool(admissionInfo.DryRun)), } e.resultCounter.Add(ctx, 1, metric.WithAttributes(commonLabels...)) } @@ -88,6 +92,7 @@ func (e *engine) reportMetrics( attribute.String("rule_result", string(ruleResult)), attribute.String("rule_type", string(ruleType)), attribute.String("rule_execution_cause", string(executionCause)), + attribute.String("dry_run", strconv.FormatBool(admissionInfo.DryRun)), } e.durationHistogram.Record(ctx, rule.Stats().ProcessingTime().Seconds(), metric.WithAttributes(commonLabels...)) } diff --git a/pkg/webhooks/utils/policy_context_builder.go b/pkg/webhooks/utils/policy_context_builder.go index d3d16b85d7..977a7b2c04 100644 --- a/pkg/webhooks/utils/policy_context_builder.go +++ b/pkg/webhooks/utils/policy_context_builder.go @@ -34,5 +34,9 @@ func (b *policyContextBuilder) Build(request admissionv1.AdmissionRequest, roles Roles: roles, ClusterRoles: clusterRoles, } + + if request.DryRun != nil { + userRequestInfo.DryRun = *request.DryRun + } return engine.NewPolicyContextFromAdmissionRequest(b.jp, request, userRequestInfo, gvk, b.configuration) }