ValidatingPolicy Status Management#
The policystatus controller (pkg/controllers/policystatus/) reconciles the .status field of all CEL-based policy types — including ValidatingPolicy, NamespacedValidatingPolicy, ImageValidatingPolicy, MutatingPolicy, GeneratingPolicy, and their namespaced variants. For ValidatingPolicy, the status reflects two independent health checks: whether the policy is wired into the webhook, and whether the Kyverno reports service account has the RBAC permissions needed to list the policy's target resources.
Scope distinction: This controller is about status reporting, not policy enforcement. The CEL validation execution pipeline lives in the ValidatingPolicy Engine (
vpolengine).
Controller Entry Point#
| Item | Detail |
|---|---|
| Package | pkg/controllers/policystatus |
| Name constant | "status-controller" |
| Workers | 3 |
| Max retries | 3 |
| Instantiation | cmd/kyverno/main.go via policystatuscontroller.NewController() — registered as a leader controller |
NewController accepts informers for all 8 policy types and a webhook.StateRecorder. It wires two sets of event handlers per policy: one keyed by MetaNamespaceKey (for standard add/update reconciliation) and one keyed by BuildRecorderKey (for webhook-state-change notifications) .
Reconcile Loop#
reconcile() parses the queue key with ParseRecorderKey to determine policy type, name, and namespace, then dispatches to a type-specific update function. All updates are wrapped in retryStatusUpdate, which retries on API conflict and silently drops NotFound errors (policy deleted before the update could land).
A secondary watchdog goroutine drains the StateRecorder.NotifyChannel() and re-enqueues any key that the webhook controller broadcasts, ensuring status is refreshed whenever webhook state changes.
Status Conditions for ValidatingPolicy#
updateVpolStatus and updateNVpolStatus are the ValidatingPolicy-specific handlers. Each:
- Wraps the policy in
engineapi.NewValidatingPolicy(vpol)to get aGenericPolicy. - Calls
reconcileBeta1Conditionsto evaluate two conditions. - Derives the boolean
Readyfield from whether all conditions areConditionTrue. - Runs
vpolautogen.Autogen(vpol)to populatestatus.autogen.configs. - Writes back the full
ValidatingPolicyStatus(conditions + autogen + preservedGeneratedflag) viacontrollerutils.UpdateStatus, skipping the API write ifstatusis already equal .
Condition: WebhookConfigured#
reconcileBeta1Conditions first checks backgroundOnly — if the policy has admission disabled and background enabled, the webhook condition is skipped entirely . Otherwise it calls c.polStateRecorder.Ready(key):
- Returns
(true, true)→ setsWebhookConfigured=True, message"Webhook configured." - Returns
(false, true)→ setsWebhookConfigured=False, message"Policy is not configured in the webhook." - Key not found in recorder (
ok=false) → condition not updated
The StateRecorder is a simple mutex-protected map at pkg/controllers/webhook/recorder.go populated by the webhook controller whenever it installs or removes a ValidatingWebhookConfiguration entry for the policy.
Condition: RBACPermissionsGranted#
permissionsCheck iterates over every GroupVersionResource derived from the policy's matchConstraints.resourceRules and issues a SubjectAccessReview for the verbs get, list, and watch . The subject is the reportsSA service account passed at construction time .
- All checks pass →
RBACPermissionsGranted=True, message"Policy is ready for reporting." - Any check fails →
RBACPermissionsGranted=Falsewith a combined error message listing the missing verbs and resources auth.ErrNoServiceAccount→ skipped silently
resolveGVRs expands the cross-product of APIGroups × APIVersions × Resources from the policy's match rules to produce the full GVR list.
Status Struct Layout#
ValidatingPolicyStatus contains :
| Field | Description |
|---|---|
ConditionStatus | Conditions slice + Ready *bool |
Autogen | ValidatingPolicyAutogenStatus{Configs: []...} |
Generated | Preserved from prior status; indicates auto-generated policy |
Policy-Type Coverage#
The controller handles all CEL-based policy types via dedicated files. For ValidatingPolicy, the relevant files are:
| File | Coverage |
|---|---|
controller.go | Core reconcile loop, condition helpers, RBAC check |
vpol.go | ValidatingPolicy + NamespacedValidatingPolicy status update |
Parallel files exist for ivpol.go (ImageValidatingPolicy), mpol.go (MutatingPolicy), gpol.go (GeneratingPolicy), ngpol.go (NamespacedGeneratingPolicy), and nivpol.go (NamespacedImageValidatingPolicy).