diff --git a/staging/src/k8s.io/apiserver/pkg/audit/evaluator.go b/staging/src/k8s.io/apiserver/pkg/audit/evaluator.go index e8591106aa2..d5e40428c00 100644 --- a/staging/src/k8s.io/apiserver/pkg/audit/evaluator.go +++ b/staging/src/k8s.io/apiserver/pkg/audit/evaluator.go @@ -39,6 +39,10 @@ type AuditContext struct { type RequestAuditConfig struct { // OmitStages is the stages that need to be omitted from being audited. OmitStages []audit.Stage + + // OmitManagedFields indicates whether to omit the managed fields of the request + // and response bodies from being written to the API audit log. + OmitManagedFields bool } // RequestAuditConfigWithLevel includes Level at which the request is being audited. diff --git a/staging/src/k8s.io/apiserver/pkg/audit/policy/checker.go b/staging/src/k8s.io/apiserver/pkg/audit/policy/checker.go index dfad2977b6c..6a98ff4ac04 100644 --- a/staging/src/k8s.io/apiserver/pkg/audit/policy/checker.go +++ b/staging/src/k8s.io/apiserver/pkg/audit/policy/checker.go @@ -67,7 +67,8 @@ func (p *policyRuleEvaluator) EvaluatePolicyRule(attrs authorizer.Attributes) au return auditinternal.RequestAuditConfigWithLevel{ Level: rule.Level, RequestAuditConfig: auditinternal.RequestAuditConfig{ - OmitStages: rule.OmitStages, + OmitStages: rule.OmitStages, + OmitManagedFields: isOmitManagedFields(&rule, p.OmitManagedFields), }, } } @@ -76,11 +77,24 @@ func (p *policyRuleEvaluator) EvaluatePolicyRule(attrs authorizer.Attributes) au return auditinternal.RequestAuditConfigWithLevel{ Level: DefaultAuditLevel, RequestAuditConfig: auditinternal.RequestAuditConfig{ - OmitStages: p.OmitStages, + OmitStages: p.OmitStages, + OmitManagedFields: p.OmitManagedFields, }, } } +// isOmitManagedFields returns whether to omit managed fields from the request +// and response bodies from being written to the API audit log. +// If a user specifies OmitManagedFields inside a policy rule, that overrides +// the global policy default in Policy.OmitManagedFields. +func isOmitManagedFields(policyRule *audit.PolicyRule, policyDefault bool) bool { + if policyRule.OmitManagedFields == nil { + return policyDefault + } + + return *policyRule.OmitManagedFields +} + // Check whether the rule matches the request attrs. func ruleMatches(r *audit.PolicyRule, attrs authorizer.Attributes) bool { user := attrs.GetUser() diff --git a/staging/src/k8s.io/apiserver/pkg/audit/policy/checker_test.go b/staging/src/k8s.io/apiserver/pkg/audit/policy/checker_test.go index 5a250c069c4..dd109ceaa0a 100644 --- a/staging/src/k8s.io/apiserver/pkg/audit/policy/checker_test.go +++ b/staging/src/k8s.io/apiserver/pkg/audit/policy/checker_test.go @@ -345,3 +345,88 @@ func TestUnionStages(t *testing.T) { } } } + +func TestOmitManagedFields(t *testing.T) { + // this authorizer.Attributes should match all policy rules + // specified in this test. + attributes := &authorizer.AttributesRecord{ + Verb: "get", + } + matchingPolicyRule := audit.PolicyRule{ + Level: audit.LevelRequestResponse, + Verbs: []string{ + attributes.GetVerb(), + }, + } + + boolPtr := func(v bool) *bool { + return &v + } + + tests := []struct { + name string + policy func() audit.Policy + want bool + }{ + { + name: "global policy default is false, rule does not override", + policy: func() audit.Policy { + return audit.Policy{ + OmitManagedFields: false, + Rules: []audit.PolicyRule{ + *matchingPolicyRule.DeepCopy(), + }, + } + }, + }, + { + name: "global policy default is true, rule does not override", + policy: func() audit.Policy { + return audit.Policy{ + OmitManagedFields: true, + Rules: []audit.PolicyRule{ + *matchingPolicyRule.DeepCopy(), + }, + } + }, + want: true, + }, + { + name: "global policy default is true, rule overrides to false", + policy: func() audit.Policy { + rule := matchingPolicyRule.DeepCopy() + rule.OmitManagedFields = boolPtr(false) + return audit.Policy{ + OmitManagedFields: true, + Rules: []audit.PolicyRule{*rule}, + } + }, + want: false, + }, + { + name: "global policy default is false, rule overrides to true", + policy: func() audit.Policy { + rule := matchingPolicyRule.DeepCopy() + rule.OmitManagedFields = boolPtr(true) + return audit.Policy{ + OmitManagedFields: false, + Rules: []audit.PolicyRule{*rule}, + } + }, + want: true, + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + evaluator := &policyRuleEvaluator{ + Policy: test.policy(), + } + + got := evaluator.EvaluatePolicyRule(attributes) + if test.want != got.OmitManagedFields { + t.Errorf("Expected OmitManagedFields to match, want: %t, got: %t", test.want, got.OmitManagedFields) + } + }) + } +}