From 2b82751964b75b6bd0dfa811619c4643f7fc4abf Mon Sep 17 00:00:00 2001 From: Evan Vetere Date: Wed, 1 Jul 2026 00:39:52 -0400 Subject: [PATCH] fix: guard create rules on 2xx instead of name fallbacks Follow-up to #672. Replace the has()-chained summary fallbacks with a success guard on the create match. Rejected creates (the DLQ-leak source) return 4xx, so they now match no rule and never deref an absent responseObject.metadata.name. Key changes: - Add audit.responseStatus.code >= 200 && < 300 to the create match in the six group/role/serviceaccount/organization/project policies - Revert create summaries to the simple link() form; a 2xx create always has responseObject.metadata.name Failed creates emit no "created" activity by design; they remain queryable via responseStatus.code >= 400 in audit query. --- config/services/activity/policies/iam/group-policy.yaml | 4 ++-- config/services/activity/policies/iam/role-policy.yaml | 4 ++-- .../services/activity/policies/iam/serviceaccount-policy.yaml | 4 ++-- .../policies/resourcemanager/organization-policy.yaml | 4 ++-- .../activity/policies/resourcemanager/project-policy.yaml | 4 ++-- config/services/identity/policies/serviceaccount-policy.yaml | 4 ++-- 6 files changed, 12 insertions(+), 12 deletions(-) diff --git a/config/services/activity/policies/iam/group-policy.yaml b/config/services/activity/policies/iam/group-policy.yaml index 37a14ce8..875d2eef 100644 --- a/config/services/activity/policies/iam/group-policy.yaml +++ b/config/services/activity/policies/iam/group-policy.yaml @@ -24,8 +24,8 @@ spec: # so controller reconciliation doesn't generate activity noise. auditRules: - name: create - match: "!audit.user.username.startsWith('system:') && audit.verb == 'create'" - summary: "{{ actor }} created group {{ has(audit.responseObject.metadata.name) ? link(audit.responseObject.metadata.name, audit.objectRef) : has(audit.objectRef.name) ? link(audit.objectRef.name, audit.objectRef) : (has(audit.responseObject.details) && has(audit.responseObject.details.name)) ? link(audit.responseObject.details.name, audit.objectRef) : link('a group', audit.objectRef) }}" + match: "!audit.user.username.startsWith('system:') && audit.verb == 'create' && audit.responseStatus.code >= 200 && audit.responseStatus.code < 300" + summary: "{{ actor }} created group {{ link(audit.responseObject.metadata.name, audit.objectRef) }}" - name: delete match: "!audit.user.username.startsWith('system:') && audit.verb == 'delete'" diff --git a/config/services/activity/policies/iam/role-policy.yaml b/config/services/activity/policies/iam/role-policy.yaml index 53b210a8..016c26d4 100644 --- a/config/services/activity/policies/iam/role-policy.yaml +++ b/config/services/activity/policies/iam/role-policy.yaml @@ -11,8 +11,8 @@ spec: auditRules: - name: create - match: "!audit.user.username.startsWith('system:') && audit.verb == 'create'" - summary: "{{ actor }} created role {{ has(audit.responseObject.metadata.name) ? link(audit.responseObject.metadata.name, audit.objectRef) : has(audit.objectRef.name) ? link(audit.objectRef.name, audit.objectRef) : (has(audit.responseObject.details) && has(audit.responseObject.details.name)) ? link(audit.responseObject.details.name, audit.objectRef) : link('a role', audit.objectRef) }}" + match: "!audit.user.username.startsWith('system:') && audit.verb == 'create' && audit.responseStatus.code >= 200 && audit.responseStatus.code < 300" + summary: "{{ actor }} created role {{ link(audit.responseObject.metadata.name, audit.objectRef) }}" - name: delete match: "!audit.user.username.startsWith('system:') && audit.verb == 'delete'" diff --git a/config/services/activity/policies/iam/serviceaccount-policy.yaml b/config/services/activity/policies/iam/serviceaccount-policy.yaml index c212d369..d796d50f 100644 --- a/config/services/activity/policies/iam/serviceaccount-policy.yaml +++ b/config/services/activity/policies/iam/serviceaccount-policy.yaml @@ -25,8 +25,8 @@ spec: # so controller reconciliation doesn't generate activity noise. auditRules: - name: create - match: "!audit.user.username.startsWith('system:') && audit.verb == 'create'" - summary: "{{ actor }} created service account {{ has(audit.responseObject.metadata.name) ? link(audit.responseObject.metadata.name, audit.objectRef) : has(audit.objectRef.name) ? link(audit.objectRef.name, audit.objectRef) : (has(audit.responseObject.details) && has(audit.responseObject.details.name)) ? link(audit.responseObject.details.name, audit.objectRef) : link('a service account', audit.objectRef) }}" + match: "!audit.user.username.startsWith('system:') && audit.verb == 'create' && audit.responseStatus.code >= 200 && audit.responseStatus.code < 300" + summary: "{{ actor }} created service account {{ link(audit.responseObject.metadata.name, audit.objectRef) }}" - name: delete match: "!audit.user.username.startsWith('system:') && audit.verb == 'delete'" diff --git a/config/services/activity/policies/resourcemanager/organization-policy.yaml b/config/services/activity/policies/resourcemanager/organization-policy.yaml index ae51dbd3..657642ca 100644 --- a/config/services/activity/policies/resourcemanager/organization-policy.yaml +++ b/config/services/activity/policies/resourcemanager/organization-policy.yaml @@ -25,8 +25,8 @@ spec: # so controller reconciliation doesn't generate activity noise. auditRules: - name: create - match: "!audit.user.username.startsWith('system:') && audit.verb == 'create'" - summary: "{{ actor }} created organization {{ has(audit.responseObject.metadata.name) ? link(audit.responseObject.metadata.name, audit.objectRef) : has(audit.objectRef.name) ? link(audit.objectRef.name, audit.objectRef) : (has(audit.responseObject.details) && has(audit.responseObject.details.name)) ? link(audit.responseObject.details.name, audit.objectRef) : link('an organization', audit.objectRef) }}" + match: "!audit.user.username.startsWith('system:') && audit.verb == 'create' && audit.responseStatus.code >= 200 && audit.responseStatus.code < 300" + summary: "{{ actor }} created organization {{ link(audit.responseObject.metadata.name, audit.objectRef) }}" - name: delete match: "!audit.user.username.startsWith('system:') && audit.verb == 'delete'" diff --git a/config/services/activity/policies/resourcemanager/project-policy.yaml b/config/services/activity/policies/resourcemanager/project-policy.yaml index 786e50c7..6254cded 100644 --- a/config/services/activity/policies/resourcemanager/project-policy.yaml +++ b/config/services/activity/policies/resourcemanager/project-policy.yaml @@ -24,8 +24,8 @@ spec: # so controller reconciliation doesn't generate activity noise. auditRules: - name: create - match: "!audit.user.username.startsWith('system:') && audit.verb == 'create'" - summary: "{{ actor }} created project {{ has(audit.responseObject.metadata.name) ? link(audit.responseObject.metadata.name, audit.objectRef) : has(audit.objectRef.name) ? link(audit.objectRef.name, audit.objectRef) : (has(audit.responseObject.details) && has(audit.responseObject.details.name)) ? link(audit.responseObject.details.name, audit.objectRef) : link('a project', audit.objectRef) }}" + match: "!audit.user.username.startsWith('system:') && audit.verb == 'create' && audit.responseStatus.code >= 200 && audit.responseStatus.code < 300" + summary: "{{ actor }} created project {{ link(audit.responseObject.metadata.name, audit.objectRef) }}" - name: delete match: "!audit.user.username.startsWith('system:') && audit.verb == 'delete'" diff --git a/config/services/identity/policies/serviceaccount-policy.yaml b/config/services/identity/policies/serviceaccount-policy.yaml index c212d369..d796d50f 100644 --- a/config/services/identity/policies/serviceaccount-policy.yaml +++ b/config/services/identity/policies/serviceaccount-policy.yaml @@ -25,8 +25,8 @@ spec: # so controller reconciliation doesn't generate activity noise. auditRules: - name: create - match: "!audit.user.username.startsWith('system:') && audit.verb == 'create'" - summary: "{{ actor }} created service account {{ has(audit.responseObject.metadata.name) ? link(audit.responseObject.metadata.name, audit.objectRef) : has(audit.objectRef.name) ? link(audit.objectRef.name, audit.objectRef) : (has(audit.responseObject.details) && has(audit.responseObject.details.name)) ? link(audit.responseObject.details.name, audit.objectRef) : link('a service account', audit.objectRef) }}" + match: "!audit.user.username.startsWith('system:') && audit.verb == 'create' && audit.responseStatus.code >= 200 && audit.responseStatus.code < 300" + summary: "{{ actor }} created service account {{ link(audit.responseObject.metadata.name, audit.objectRef) }}" - name: delete match: "!audit.user.username.startsWith('system:') && audit.verb == 'delete'"