diff --git a/definitions/install.yaml b/definitions/install.yaml index d5c433bb77..9a5776959a 100644 --- a/definitions/install.yaml +++ b/definitions/install.yaml @@ -212,8 +212,6 @@ spec: AnyValue: {} deny: properties: - allRequests: - type: boolean conditions: type: array items: diff --git a/definitions/install_debug.yaml b/definitions/install_debug.yaml index d0193eb91e..8bdb8662fb 100644 --- a/definitions/install_debug.yaml +++ b/definitions/install_debug.yaml @@ -212,8 +212,6 @@ spec: AnyValue: {} deny: properties: - allRequests: - type: boolean conditions: type: array items: diff --git a/pkg/api/kyverno/v1/types.go b/pkg/api/kyverno/v1/types.go index 4c7bc74c59..5c2c4e329b 100644 --- a/pkg/api/kyverno/v1/types.go +++ b/pkg/api/kyverno/v1/types.go @@ -215,8 +215,7 @@ type Validation struct { } type Deny struct { - AllRequests bool `json:"allRequests,omitempty"` - Conditions []Condition `json:"conditions,omitempty"` + Conditions []Condition `json:"conditions,omitempty"` } // Generation describes which resources will be created when other resource is created diff --git a/pkg/engine/validation.go b/pkg/engine/validation.go index 0f575748ea..7515c9d26d 100644 --- a/pkg/engine/validation.go +++ b/pkg/engine/validation.go @@ -115,7 +115,7 @@ func isRequestDenied(log logr.Logger, ctx context.EvalInterface, policy kyverno. if rule.Validation.Deny != nil { denyConditionsCopy := copyConditions(rule.Validation.Deny.Conditions) - if rule.Validation.Deny.AllRequests || variables.EvaluateConditions(log, ctx, denyConditionsCopy) { + if len(rule.Validation.Deny.Conditions) == 0 || variables.EvaluateConditions(log, ctx, denyConditionsCopy) { ruleResp := response.RuleResponse{ Name: rule.Name, Type: utils.Validation.String(), diff --git a/pkg/policy/background.go b/pkg/policy/background.go index 35611efa74..b6af9d2d23 100644 --- a/pkg/policy/background.go +++ b/pkg/policy/background.go @@ -9,51 +9,52 @@ import ( "sigs.k8s.io/controller-runtime/pkg/log" ) -//ContainsVariablesOtherThanObject returns error if variable that does not start from request.object is defined +//ContainsVariablesOtherThanObject returns error if variable that does not start from request.object func ContainsVariablesOtherThanObject(policy kyverno.ClusterPolicy) error { var err error - // iterate of the policy rules to identify if userInfo is used for idx, rule := range policy.Spec.Rules { if path := userInfoDefined(rule.MatchResources.UserInfo); path != "" { - return fmt.Errorf("userInfo variable used at path: spec/rules[%d]/match/%s", idx, path) + return fmt.Errorf("invalid variable used at path: spec/rules[%d]/match/%s", idx, path) } if path := userInfoDefined(rule.ExcludeResources.UserInfo); path != "" { - return fmt.Errorf("userInfo variable used at path: spec/rules[%d]/exclude/%s", idx, path) + return fmt.Errorf("invalid variable used at path: spec/rules[%d]/exclude/%s", idx, path) } - // variable defined with user information - // - condition.key - // - condition.value - // - mutate.overlay - // - validate.pattern - // - validate.anyPattern[*] - // variables to filter - // - request.userInfo* - // - serviceAccountName - // - serviceAccountNamespace - filterVars := []string{"request.object"} ctx := context.NewContext(filterVars...) for condIdx, condition := range rule.Conditions { if condition.Key, err = variables.SubstituteVars(log.Log, ctx, condition.Key); err != nil { - return fmt.Errorf("userInfo variable used at spec/rules[%d]/condition[%d]/key", idx, condIdx) + return fmt.Errorf("invalid variable used at spec/rules[%d]/condition[%d]/key", idx, condIdx) } if condition.Value, err = variables.SubstituteVars(log.Log, ctx, condition.Value); err != nil { - return fmt.Errorf("userInfo variable used at spec/rules[%d]/condition[%d]/value", idx, condIdx) + return fmt.Errorf("invalid variable used at spec/rules[%d]/condition[%d]/value", idx, condIdx) } } if rule.Mutation.Overlay, err = variables.SubstituteVars(log.Log, ctx, rule.Mutation.Overlay); err != nil { - return fmt.Errorf("userInfo variable used at spec/rules[%d]/mutate/overlay", idx) + return fmt.Errorf("invalid variable used at spec/rules[%d]/mutate/overlay", idx) } if rule.Validation.Pattern, err = variables.SubstituteVars(log.Log, ctx, rule.Validation.Pattern); err != nil { - return fmt.Errorf("userInfo variable used at spec/rules[%d]/validate/pattern", idx) + return fmt.Errorf("invalid variable used at spec/rules[%d]/validate/pattern", idx) } for idx2, pattern := range rule.Validation.AnyPattern { if rule.Validation.AnyPattern[idx2], err = variables.SubstituteVars(log.Log, ctx, pattern); err != nil { - return fmt.Errorf("userInfo variable used at spec/rules[%d]/validate/anyPattern[%d]", idx, idx2) + return fmt.Errorf("invalid variable used at spec/rules[%d]/validate/anyPattern[%d]", idx, idx2) + } + } + if _, err = variables.SubstituteVars(log.Log, ctx, rule.Validation.Message); err != nil { + return fmt.Errorf("invalid variable used at spec/rules[%d]/validate/message", idx) + } + if rule.Validation.Deny != nil { + for i := range rule.Validation.Deny.Conditions { + if _, err = variables.SubstituteVars(log.Log, ctx, rule.Validation.Deny.Conditions[i].Key); err != nil { + return fmt.Errorf("invalid variable used at spec/rules[%d]/validate/deny/conditions[%d]/key", idx, i) + } + if _, err = variables.SubstituteVars(log.Log, ctx, rule.Validation.Deny.Conditions[i].Value); err != nil { + return fmt.Errorf("invalid variable used at spec/rules[%d]/validate/deny/conditions[%d]/value", idx, i) + } } } } diff --git a/pkg/policy/validate.go b/pkg/policy/validate.go index f06d83b1de..de7b791f04 100644 --- a/pkg/policy/validate.go +++ b/pkg/policy/validate.go @@ -30,16 +30,9 @@ func Validate(policyRaw []byte, client *dclient.Client, mock bool, openAPIContro if path, err := validateUniqueRuleName(p); err != nil { return fmt.Errorf("path: spec.%s: %v", path, err) } - if p.Spec.Background == nil { - //skipped policy mutation default -> skip validation -> will not be processed for background processing - return nil - } - if *p.Spec.Background { + if p.Spec.Background == nil || (p.Spec.Background != nil && *p.Spec.Background) { if err := ContainsVariablesOtherThanObject(p); err != nil { - // policy.spec.background -> "true" - // - cannot use variables with request.userInfo - // - cannot define userInfo(roles, cluserRoles, subjects) for filtering (match & exclude) - return fmt.Errorf("userInfo is not allowed in match or exclude when backgroud policy mode is true. Set spec.background=false to disable background mode for this policy rule. %s ", err) + return fmt.Errorf("only variables referring request.object are allowed in background mode. Set spec.background=false to disable background mode for this policy rule. %s ", err) } } diff --git a/pkg/policy/validate_test.go b/pkg/policy/validate_test.go index 8f10eddfae..9855f2130c 100644 --- a/pkg/policy/validate_test.go +++ b/pkg/policy/validate_test.go @@ -609,7 +609,7 @@ func Test_BackGroundUserInfo_match_roles(t *testing.T) { assert.NilError(t, err) err = ContainsVariablesOtherThanObject(*policy) - assert.Equal(t, err.Error(), "userInfo variable used at path: spec/rules[0]/match/roles") + assert.Equal(t, err.Error(), "invalid variable used at path: spec/rules[0]/match/roles") } func Test_BackGroundUserInfo_match_clusterRoles(t *testing.T) { @@ -642,7 +642,7 @@ func Test_BackGroundUserInfo_match_clusterRoles(t *testing.T) { err = ContainsVariablesOtherThanObject(*policy) - assert.Equal(t, err.Error(), "userInfo variable used at path: spec/rules[0]/match/clusterRoles") + assert.Equal(t, err.Error(), "invalid variable used at path: spec/rules[0]/match/clusterRoles") } func Test_BackGroundUserInfo_match_subjects(t *testing.T) { @@ -678,7 +678,7 @@ func Test_BackGroundUserInfo_match_subjects(t *testing.T) { err = ContainsVariablesOtherThanObject(*policy) - assert.Equal(t, err.Error(), "userInfo variable used at path: spec/rules[0]/match/subjects") + assert.Equal(t, err.Error(), "invalid variable used at path: spec/rules[0]/match/subjects") } func Test_BackGroundUserInfo_mutate_overlay1(t *testing.T) { @@ -710,7 +710,7 @@ func Test_BackGroundUserInfo_mutate_overlay1(t *testing.T) { err = ContainsVariablesOtherThanObject(*policy) - if err.Error() != "userInfo variable used at spec/rules[0]/mutate/overlay" { + if err.Error() != "invalid variable used at spec/rules[0]/mutate/overlay" { t.Log(err) t.Error("Incorrect Path") } @@ -745,7 +745,7 @@ func Test_BackGroundUserInfo_mutate_overlay2(t *testing.T) { err = ContainsVariablesOtherThanObject(*policy) - if err.Error() != "userInfo variable used at spec/rules[0]/mutate/overlay" { + if err.Error() != "invalid variable used at spec/rules[0]/mutate/overlay" { t.Log(err) t.Error("Incorrect Path") } @@ -780,7 +780,7 @@ func Test_BackGroundUserInfo_validate_pattern(t *testing.T) { err = ContainsVariablesOtherThanObject(*policy) - if err.Error() != "userInfo variable used at spec/rules[0]/validate/pattern" { + if err.Error() != "invalid variable used at spec/rules[0]/validate/pattern" { t.Log(err) t.Error("Incorrect Path") } @@ -819,7 +819,7 @@ func Test_BackGroundUserInfo_validate_anyPattern(t *testing.T) { err = ContainsVariablesOtherThanObject(*policy) - if err.Error() != "userInfo variable used at spec/rules[0]/validate/anyPattern[1]" { + if err.Error() != "invalid variable used at spec/rules[0]/validate/anyPattern[1]" { t.Log(err) t.Error("Incorrect Path") } @@ -858,7 +858,7 @@ func Test_BackGroundUserInfo_validate_anyPattern_multiple_var(t *testing.T) { err = ContainsVariablesOtherThanObject(*policy) - if err.Error() != "userInfo variable used at spec/rules[0]/validate/anyPattern[1]" { + if err.Error() != "invalid variable used at spec/rules[0]/validate/anyPattern[1]" { t.Log(err) t.Error("Incorrect Path") } @@ -897,7 +897,7 @@ func Test_BackGroundUserInfo_validate_anyPattern_serviceAccount(t *testing.T) { err = ContainsVariablesOtherThanObject(*policy) - if err.Error() != "userInfo variable used at spec/rules[0]/validate/anyPattern[1]" { + if err.Error() != "invalid variable used at spec/rules[0]/validate/anyPattern[1]" { t.Log(err) t.Error("Incorrect Path") }