Unverified Commit 7b9affae authored by Kubernetes Submit Queue's avatar Kubernetes Submit Queue Committed by GitHub

Merge pull request #54634 from CaoShuFeng/omit_stage

Automatic merge from submit-queue (batch tested with PRs 52322, 54634). If you want to cherry-pick this change to another branch, please follow the instructions <a href="https://github.com/kubernetes/community/blob/master/contributors/devel/cherry-picks.md">here</a>. [advanced audit]add a policy wide omitStage Related to: https://github.com/kubernetes/kubernetes/issues/54551 For example: 1. only log panic events ``` apiVersion: audit.k8s.io/v1beta1 kind: Policy omitStages: - "RequestReceived" - "ResponseStarted" - "ResponseComplete" rules: - level: Request ``` 2. only log events inRequestReceived stage: ``` apiVersion: audit.k8s.io/v1beta1 kind: Policy omitStages: - "ResponseStarted" - "ResponseComplete" - "Panic" rules: - level: Request ``` **Release note**: ``` support a policy wide omitStage for advanced audit ```
parents 80e1c790 4a20d729
...@@ -153,6 +153,11 @@ type Policy struct { ...@@ -153,6 +153,11 @@ type Policy struct {
// The default audit level is None, but can be overridden by a catch-all rule at the end of the list. // The default audit level is None, but can be overridden by a catch-all rule at the end of the list.
// PolicyRules are strictly ordered. // PolicyRules are strictly ordered.
Rules []PolicyRule Rules []PolicyRule
// OmitStages is a list of stages for which no events are created. Note that this can also
// be specified per rule in which case the union of both are omitted.
// +optional
OmitStages []Stage
} }
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
...@@ -208,8 +213,10 @@ type PolicyRule struct { ...@@ -208,8 +213,10 @@ type PolicyRule struct {
// +optional // +optional
NonResourceURLs []string NonResourceURLs []string
// OmitStages specify events generated in which stages will not be emitted to backend. // OmitStages is a list of stages for which no events are created. Note that this can also
// be specified policy wide in which case the union of both are omitted.
// An empty list means no restrictions will apply. // An empty list means no restrictions will apply.
// +optional
OmitStages []Stage OmitStages []Stage
} }
......
...@@ -164,6 +164,11 @@ message Policy { ...@@ -164,6 +164,11 @@ message Policy {
// The default audit level is None, but can be overridden by a catch-all rule at the end of the list. // The default audit level is None, but can be overridden by a catch-all rule at the end of the list.
// PolicyRules are strictly ordered. // PolicyRules are strictly ordered.
repeated PolicyRule rules = 2; repeated PolicyRule rules = 2;
// OmitStages is a list of stages for which no events are created. Note that this can also
// be specified per rule in which case the union of both are omitted.
// +optional
repeated string omitStages = 3;
} }
// PolicyList is a list of audit Policies. // PolicyList is a list of audit Policies.
...@@ -214,8 +219,10 @@ message PolicyRule { ...@@ -214,8 +219,10 @@ message PolicyRule {
// +optional // +optional
repeated string nonResourceURLs = 7; repeated string nonResourceURLs = 7;
// OmitStages specify events generated in which stages will not be emitted to backend. // OmitStages is a list of stages for which no events are created. Note that this can also
// be specified policy wide in which case the union of both are omitted.
// An empty list means no restrictions will apply. // An empty list means no restrictions will apply.
// +optional
repeated string omitStages = 8; repeated string omitStages = 8;
} }
...@@ -160,6 +160,11 @@ type Policy struct { ...@@ -160,6 +160,11 @@ type Policy struct {
// The default audit level is None, but can be overridden by a catch-all rule at the end of the list. // The default audit level is None, but can be overridden by a catch-all rule at the end of the list.
// PolicyRules are strictly ordered. // PolicyRules are strictly ordered.
Rules []PolicyRule `json:"rules" protobuf:"bytes,2,rep,name=rules"` Rules []PolicyRule `json:"rules" protobuf:"bytes,2,rep,name=rules"`
// OmitStages is a list of stages for which no events are created. Note that this can also
// be specified per rule in which case the union of both are omitted.
// +optional
OmitStages []Stage `json:"omitStages,omitempty" protobuf:"bytes,3,rep,name=omitStages"`
} }
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
...@@ -215,8 +220,10 @@ type PolicyRule struct { ...@@ -215,8 +220,10 @@ type PolicyRule struct {
// +optional // +optional
NonResourceURLs []string `json:"nonResourceURLs,omitempty" protobuf:"bytes,7,rep,name=nonResourceURLs"` NonResourceURLs []string `json:"nonResourceURLs,omitempty" protobuf:"bytes,7,rep,name=nonResourceURLs"`
// OmitStages specify events generated in which stages will not be emitted to backend. // OmitStages is a list of stages for which no events are created. Note that this can also
// be specified policy wide in which case the union of both are omitted.
// An empty list means no restrictions will apply. // An empty list means no restrictions will apply.
// +optional
OmitStages []Stage `json:"omitStages,omitempty" protobuf:"bytes,8,rep,name=omitStages"` OmitStages []Stage `json:"omitStages,omitempty" protobuf:"bytes,8,rep,name=omitStages"`
} }
......
...@@ -207,6 +207,7 @@ func autoConvert_audit_ObjectReference_To_v1alpha1_ObjectReference(in *audit.Obj ...@@ -207,6 +207,7 @@ func autoConvert_audit_ObjectReference_To_v1alpha1_ObjectReference(in *audit.Obj
func autoConvert_v1alpha1_Policy_To_audit_Policy(in *Policy, out *audit.Policy, s conversion.Scope) error { func autoConvert_v1alpha1_Policy_To_audit_Policy(in *Policy, out *audit.Policy, s conversion.Scope) error {
out.ObjectMeta = in.ObjectMeta out.ObjectMeta = in.ObjectMeta
out.Rules = *(*[]audit.PolicyRule)(unsafe.Pointer(&in.Rules)) out.Rules = *(*[]audit.PolicyRule)(unsafe.Pointer(&in.Rules))
out.OmitStages = *(*[]audit.Stage)(unsafe.Pointer(&in.OmitStages))
return nil return nil
} }
...@@ -218,6 +219,7 @@ func Convert_v1alpha1_Policy_To_audit_Policy(in *Policy, out *audit.Policy, s co ...@@ -218,6 +219,7 @@ func Convert_v1alpha1_Policy_To_audit_Policy(in *Policy, out *audit.Policy, s co
func autoConvert_audit_Policy_To_v1alpha1_Policy(in *audit.Policy, out *Policy, s conversion.Scope) error { func autoConvert_audit_Policy_To_v1alpha1_Policy(in *audit.Policy, out *Policy, s conversion.Scope) error {
out.ObjectMeta = in.ObjectMeta out.ObjectMeta = in.ObjectMeta
out.Rules = *(*[]PolicyRule)(unsafe.Pointer(&in.Rules)) out.Rules = *(*[]PolicyRule)(unsafe.Pointer(&in.Rules))
out.OmitStages = *(*[]Stage)(unsafe.Pointer(&in.OmitStages))
return nil return nil
} }
......
...@@ -195,6 +195,11 @@ func (in *Policy) DeepCopyInto(out *Policy) { ...@@ -195,6 +195,11 @@ func (in *Policy) DeepCopyInto(out *Policy) {
(*in)[i].DeepCopyInto(&(*out)[i]) (*in)[i].DeepCopyInto(&(*out)[i])
} }
} }
if in.OmitStages != nil {
in, out := &in.OmitStages, &out.OmitStages
*out = make([]Stage, len(*in))
copy(*out, *in)
}
return return
} }
......
...@@ -174,6 +174,11 @@ message Policy { ...@@ -174,6 +174,11 @@ message Policy {
// The default audit level is None, but can be overridden by a catch-all rule at the end of the list. // The default audit level is None, but can be overridden by a catch-all rule at the end of the list.
// PolicyRules are strictly ordered. // PolicyRules are strictly ordered.
repeated PolicyRule rules = 2; repeated PolicyRule rules = 2;
// OmitStages is a list of stages for which no events are created. Note that this can also
// be specified per rule in which case the union of both are omitted.
// +optional
repeated string omitStages = 3;
} }
// PolicyList is a list of audit Policies. // PolicyList is a list of audit Policies.
...@@ -224,8 +229,10 @@ message PolicyRule { ...@@ -224,8 +229,10 @@ message PolicyRule {
// +optional // +optional
repeated string nonResourceURLs = 7; repeated string nonResourceURLs = 7;
// OmitStages specify events generated in which stages will not be emitted to backend. // OmitStages is a list of stages for which no events are created. Note that this can also
// be specified policy wide in which case the union of both are omitted.
// An empty list means no restrictions will apply. // An empty list means no restrictions will apply.
// +optional
repeated string omitStages = 8; repeated string omitStages = 8;
} }
...@@ -156,6 +156,11 @@ type Policy struct { ...@@ -156,6 +156,11 @@ type Policy struct {
// The default audit level is None, but can be overridden by a catch-all rule at the end of the list. // The default audit level is None, but can be overridden by a catch-all rule at the end of the list.
// PolicyRules are strictly ordered. // PolicyRules are strictly ordered.
Rules []PolicyRule `json:"rules" protobuf:"bytes,2,rep,name=rules"` Rules []PolicyRule `json:"rules" protobuf:"bytes,2,rep,name=rules"`
// OmitStages is a list of stages for which no events are created. Note that this can also
// be specified per rule in which case the union of both are omitted.
// +optional
OmitStages []Stage `json:"omitStages,omitempty" protobuf:"bytes,3,rep,name=omitStages"`
} }
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
...@@ -211,8 +216,10 @@ type PolicyRule struct { ...@@ -211,8 +216,10 @@ type PolicyRule struct {
// +optional // +optional
NonResourceURLs []string `json:"nonResourceURLs,omitempty" protobuf:"bytes,7,rep,name=nonResourceURLs"` NonResourceURLs []string `json:"nonResourceURLs,omitempty" protobuf:"bytes,7,rep,name=nonResourceURLs"`
// OmitStages specify events generated in which stages will not be emitted to backend. // OmitStages is a list of stages for which no events are created. Note that this can also
// be specified policy wide in which case the union of both are omitted.
// An empty list means no restrictions will apply. // An empty list means no restrictions will apply.
// +optional
OmitStages []Stage `json:"omitStages,omitempty" protobuf:"bytes,8,rep,name=omitStages"` OmitStages []Stage `json:"omitStages,omitempty" protobuf:"bytes,8,rep,name=omitStages"`
} }
......
...@@ -202,6 +202,7 @@ func Convert_audit_ObjectReference_To_v1beta1_ObjectReference(in *audit.ObjectRe ...@@ -202,6 +202,7 @@ func Convert_audit_ObjectReference_To_v1beta1_ObjectReference(in *audit.ObjectRe
func autoConvert_v1beta1_Policy_To_audit_Policy(in *Policy, out *audit.Policy, s conversion.Scope) error { func autoConvert_v1beta1_Policy_To_audit_Policy(in *Policy, out *audit.Policy, s conversion.Scope) error {
out.ObjectMeta = in.ObjectMeta out.ObjectMeta = in.ObjectMeta
out.Rules = *(*[]audit.PolicyRule)(unsafe.Pointer(&in.Rules)) out.Rules = *(*[]audit.PolicyRule)(unsafe.Pointer(&in.Rules))
out.OmitStages = *(*[]audit.Stage)(unsafe.Pointer(&in.OmitStages))
return nil return nil
} }
...@@ -213,6 +214,7 @@ func Convert_v1beta1_Policy_To_audit_Policy(in *Policy, out *audit.Policy, s con ...@@ -213,6 +214,7 @@ func Convert_v1beta1_Policy_To_audit_Policy(in *Policy, out *audit.Policy, s con
func autoConvert_audit_Policy_To_v1beta1_Policy(in *audit.Policy, out *Policy, s conversion.Scope) error { func autoConvert_audit_Policy_To_v1beta1_Policy(in *audit.Policy, out *Policy, s conversion.Scope) error {
out.ObjectMeta = in.ObjectMeta out.ObjectMeta = in.ObjectMeta
out.Rules = *(*[]PolicyRule)(unsafe.Pointer(&in.Rules)) out.Rules = *(*[]PolicyRule)(unsafe.Pointer(&in.Rules))
out.OmitStages = *(*[]Stage)(unsafe.Pointer(&in.OmitStages))
return nil return nil
} }
......
...@@ -195,6 +195,11 @@ func (in *Policy) DeepCopyInto(out *Policy) { ...@@ -195,6 +195,11 @@ func (in *Policy) DeepCopyInto(out *Policy) {
(*in)[i].DeepCopyInto(&(*out)[i]) (*in)[i].DeepCopyInto(&(*out)[i])
} }
} }
if in.OmitStages != nil {
in, out := &in.OmitStages, &out.OmitStages
*out = make([]Stage, len(*in))
copy(*out, *in)
}
return return
} }
......
...@@ -26,6 +26,7 @@ import ( ...@@ -26,6 +26,7 @@ import (
func ValidatePolicy(policy *audit.Policy) field.ErrorList { func ValidatePolicy(policy *audit.Policy) field.ErrorList {
var allErrs field.ErrorList var allErrs field.ErrorList
allErrs = append(allErrs, validateOmitStages(policy.OmitStages, field.NewPath("omitStages"))...)
rulePath := field.NewPath("rules") rulePath := field.NewPath("rules")
for i, rule := range policy.Rules { for i, rule := range policy.Rules {
allErrs = append(allErrs, validatePolicyRule(rule, rulePath.Index(i))...) allErrs = append(allErrs, validatePolicyRule(rule, rulePath.Index(i))...)
......
...@@ -54,7 +54,9 @@ func TestValidatePolicy(t *testing.T) { ...@@ -54,7 +54,9 @@ func TestValidatePolicy(t *testing.T) {
for _, rule := range validRules { for _, rule := range validRules {
successCases = append(successCases, audit.Policy{Rules: []audit.PolicyRule{rule}}) successCases = append(successCases, audit.Policy{Rules: []audit.PolicyRule{rule}})
} }
successCases = append(successCases, audit.Policy{}) // Empty policy is valid. successCases = append(successCases, audit.Policy{}) // Empty policy is valid.
successCases = append(successCases, audit.Policy{OmitStages: []audit.Stage{ // Policy with omitStages
audit.Stage("RequestReceived")}})
successCases = append(successCases, audit.Policy{Rules: validRules}) // Multiple rules. successCases = append(successCases, audit.Policy{Rules: validRules}) // Multiple rules.
for i, policy := range successCases { for i, policy := range successCases {
...@@ -113,7 +115,7 @@ func TestValidatePolicy(t *testing.T) { ...@@ -113,7 +115,7 @@ func TestValidatePolicy(t *testing.T) {
Resources: []audit.GroupResources{{ResourceNames: []string{"leader"}}}, Resources: []audit.GroupResources{{ResourceNames: []string{"leader"}}},
Namespaces: []string{"kube-system"}, Namespaces: []string{"kube-system"},
}, },
{ // invalid omitStages { // invalid omitStages in rule
Level: audit.LevelMetadata, Level: audit.LevelMetadata,
OmitStages: []audit.Stage{ OmitStages: []audit.Stage{
audit.Stage("foo"), audit.Stage("foo"),
...@@ -124,7 +126,21 @@ func TestValidatePolicy(t *testing.T) { ...@@ -124,7 +126,21 @@ func TestValidatePolicy(t *testing.T) {
for _, rule := range invalidRules { for _, rule := range invalidRules {
errorCases = append(errorCases, audit.Policy{Rules: []audit.PolicyRule{rule}}) errorCases = append(errorCases, audit.Policy{Rules: []audit.PolicyRule{rule}})
} }
errorCases = append(errorCases, audit.Policy{Rules: append(validRules, audit.PolicyRule{})}) // Multiple rules.
// Multiple rules.
errorCases = append(errorCases, audit.Policy{Rules: append(validRules, audit.PolicyRule{})})
// invalid omitStages in policy
policy := audit.Policy{OmitStages: []audit.Stage{
audit.Stage("foo"),
},
Rules: []audit.PolicyRule{
{
Level: audit.LevelMetadata,
},
},
}
errorCases = append(errorCases, policy)
for i, policy := range errorCases { for i, policy := range errorCases {
if errs := ValidatePolicy(&policy); len(errs) == 0 { if errs := ValidatePolicy(&policy); len(errs) == 0 {
......
...@@ -192,6 +192,11 @@ func (in *Policy) DeepCopyInto(out *Policy) { ...@@ -192,6 +192,11 @@ func (in *Policy) DeepCopyInto(out *Policy) {
(*in)[i].DeepCopyInto(&(*out)[i]) (*in)[i].DeepCopyInto(&(*out)[i])
} }
} }
if in.OmitStages != nil {
in, out := &in.OmitStages, &out.OmitStages
*out = make([]Stage, len(*in))
copy(*out, *in)
}
return return
} }
......
...@@ -36,9 +36,26 @@ type Checker interface { ...@@ -36,9 +36,26 @@ type Checker interface {
// NewChecker creates a new policy checker. // NewChecker creates a new policy checker.
func NewChecker(policy *audit.Policy) Checker { func NewChecker(policy *audit.Policy) Checker {
for i, rule := range policy.Rules {
policy.Rules[i].OmitStages = unionStages(policy.OmitStages, rule.OmitStages)
}
return &policyChecker{*policy} return &policyChecker{*policy}
} }
func unionStages(stageLists ...[]audit.Stage) []audit.Stage {
m := make(map[audit.Stage]bool)
for _, sl := range stageLists {
for _, s := range sl {
m[s] = true
}
}
result := make([]audit.Stage, 0, len(m))
for key := range m {
result = append(result, key)
}
return result
}
// FakeChecker creates a checker that returns a constant level for all requests (for testing). // FakeChecker creates a checker that returns a constant level for all requests (for testing).
func FakeChecker(level audit.Level, stage []audit.Stage) Checker { func FakeChecker(level audit.Level, stage []audit.Stage) Checker {
return &fakeChecker{level, stage} return &fakeChecker{level, stage}
...@@ -54,7 +71,7 @@ func (p *policyChecker) LevelAndStages(attrs authorizer.Attributes) (audit.Level ...@@ -54,7 +71,7 @@ func (p *policyChecker) LevelAndStages(attrs authorizer.Attributes) (audit.Level
return rule.Level, rule.OmitStages return rule.Level, rule.OmitStages
} }
} }
return DefaultAuditLevel, nil return DefaultAuditLevel, p.OmitStages
} }
// Check whether the rule matches the request attrs. // Check whether the rule matches the request attrs.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment