1
0
Fork 0
mirror of https://github.com/kyverno/kyverno.git synced 2024-12-14 11:57:48 +00:00

Merge branch 'master' into access_check

This commit is contained in:
Shivkumar Dudhani 2020-03-20 10:07:47 -07:00 committed by GitHub
commit 2638e1002a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 126 additions and 65 deletions

View file

@ -120,6 +120,7 @@ Refer to a list of curated of ***[sample policies](/samples/README.md)*** that c
* [Getting Started](documentation/installation.md) * [Getting Started](documentation/installation.md)
* [Writing Policies](documentation/writing-policies.md) * [Writing Policies](documentation/writing-policies.md)
* [Selecting Resources](/documentation/writing-policies-match-exclude.md)
* [Validate Resources](documentation/writing-policies-validate.md) * [Validate Resources](documentation/writing-policies-validate.md)
* [Mutate Resources](documentation/writing-policies-mutate.md) * [Mutate Resources](documentation/writing-policies-mutate.md)
* [Generate Resources](documentation/writing-policies-generate.md) * [Generate Resources](documentation/writing-policies-generate.md)

View file

@ -16,6 +16,14 @@ make cli
mv ./cmd/cli/kubectl-kyverno/kyverno /usr/local/bin/kyverno mv ./cmd/cli/kubectl-kyverno/kyverno /usr/local/bin/kyverno
``` ```
## Install via AUR (archlinux)
You can install the kyverno cli via your favourite AUR helper (e.g. [yay](https://github.com/Jguer/yay))
```
yay -S kyverno-git
```
## Commands ## Commands
#### Version #### Version

View file

@ -0,0 +1,93 @@
<small>*[documentation](/README.md#documentation) / Writing Policies / Match & Exclude *</small>
# Match & Exclude
The `match` and `exclude` filters control which resources policies are applied to.
The match / exclude clauses have the same structure, and can each contain the following elements:
* resources: select resources by name, namespaces, kinds, and label selectors.
* subjects: select users, user groups, and service accounts
* roles: select namespaced roles
* clusterroles: select cluster wide roles
At least one element must be specified in a `match` block. The `kind` attribute is optional, but if it's not specified the policy rule will only be applicable to metatdata that is common across all resources kinds.
When Kyverno receives an admission controller request, i.e. a validation or mutation webhook, it first checks to see if the resource and user information matches or should be excluded from processing. If both checks pass, then the rule logic to mutate, validate, or generate resources is applied.
The following YAML provides an example for a match clause.
````yaml
apiVersion : kyverno.io/v1
kind : ClusterPolicy
metadata :
name : policy
spec :
# 'enforce' to block resource request if any rules fail
# 'audit' to allow resource request on failure of rules, but create policy violations to report them
validationFailureAction: enforce
# Each policy has a list of rules applied in declaration order
rules:
# Rules must have a unique name
- name: "check-pod-controller-labels"
# Each rule matches specific resource described by "match" field.
match:
resources:
kinds: # Required, list of kinds
- Deployment
- StatefulSet
name: "mongo*" # Optional, a resource name is optional. Name supports wildcards (* and ?)
namespaces: # Optional, list of namespaces. Supports wildcards (* and ?)
- "dev*"
- test
selector: # Optional, a resource selector is optional. Values support wildcards (* and ?)
matchLabels:
app: mongodb
matchExpressions:
- {key: tier, operator: In, values: [database]}
# Optional, subjects to be matched
subjects:
- kind: User
name: mary@somecorp.com
# Optional, roles to be matched
roles:
# Optional, clusterroles to be matched
clusterroles: cluster-admin
...
````
All`match` and `exclude` element must be satisfied for the resource to be selected as a candidate for the policy rule. In other words, the match and exclude conditions are evaluated using a logical AND operation.
Here is an example of a rule that matches all pods, excluding pods created by using the `cluster-admin` cluster role.
````yaml
spec:
rules:
name: "match-pods-except-admin"
match:
resources:
kinds:
- Pod
exclude:
clusterroles: cluster-admin
````
This rule that matches all pods, excluding pods in the `kube-system` namespace.
````yaml
spec:
rules:
name: "match-pods-except-admin"
match:
resources:
kinds:
- Pod
exclude:
namespaces:
- "kube-system"
````
---
<small>*Read Next >> [Validate Resources](/documentation/writing-policies-validate.md)*</small>

View file

@ -8,59 +8,9 @@ The following picture shows the structure of a Kyverno Policy:
Each Kyverno policy contains one or more rules. Each rule has a `match` clause, an optional `exclude` clause, and one of a `mutate`, `validate`, or `generate` clause. Each Kyverno policy contains one or more rules. Each rule has a `match` clause, an optional `exclude` clause, and one of a `mutate`, `validate`, or `generate` clause.
The match / exclude clauses have the same structure, and can contain the following elements: Each rule can validate, mutate, or generate configurations of matching resources. A rule definition can contain only a single **mutate**, **validate**, or **generate** child node.
* resources: select resources by name, namespaces, kinds, and label selectors.
* subjects: select users, user groups, and service accounts
* roles: select namespaced roles
* clusterroles: select cluster wide roles
When Kyverno receives an admission controller request, i.e. a validation or mutation webhook, it first checks to see if the resource and user information matches or should be excluded from processing. If both checks pass, then the rule logic to mutate, validate, or generate resources is applied.
The following YAML provides an example for a match clause.
````yaml
apiVersion : kyverno.io/v1
kind : ClusterPolicy
metadata :
name : policy
spec :
# 'enforce' to block resource request if any rules fail
# 'audit' to allow resource request on failure of rules, but create policy violations to report them
validationFailureAction: enforce
# Each policy has a list of rules applied in declaration order
rules:
# Rules must have a unique name
- name: "check-pod-controller-labels"
# Each rule matches specific resource described by "match" field.
match:
resources:
kinds: # Required, list of kinds
- Deployment
- StatefulSet
name: "mongo*" # Optional, a resource name is optional. Name supports wildcards (* and ?)
namespaces: # Optional, list of namespaces. Supports wildcards (* and ?)
- "dev*"
- test
selector: # Optional, a resource selector is optional. Values support wildcards (* and ?)
matchLabels:
app: mongodb
matchExpressions:
- {key: tier, operator: In, values: [database]}
# Optional, subjects to be matched
subjects:
- kind: User
name: mary@somecorp.com
# Optional, roles to be matched
roles:
# Optional, clusterroles to be matched
clusterroles: cluster-admin
...
````
Each rule can validate, mutate, or generate configurations of matching resources. A rule definition can contain only a single **mutate**, **validate**, or **generate** child node. These actions are applied to the resource in described order: mutation, validation and then generation.
These actions are applied to the resource in described order: mutation, validation and then generation.
--- ---
<small>*Read Next >> [Validate Resources](/documentation/writing-policies-validate.md)*</small> <small>*Read Next >> [Selecting Resources](/documentation/writing-policies-match-exclude.md)*</small>

View file

@ -233,7 +233,12 @@ func validatePatterns(log logr.Logger, ctx context.EvalInterface, resource unstr
errorStr = append(errorStr, err.Error()) errorStr = append(errorStr, err.Error())
} }
resp.Success = false resp.Success = false
resp.Message = fmt.Sprintf("Validation rule '%s' failed. %s", rule.Name, errorStr) glog.V(4).Infof("Validation rule '%s' failed. %s", rule.Name, errorStr)
if rule.Validation.Message == "" {
resp.Message = fmt.Sprintf("Validation rule '%s' has failed", rule.Name)
} else {
resp.Message = rule.Validation.Message
}
return resp return resp
} }
} }

View file

@ -294,7 +294,7 @@ func TestValidate_Fail_anyPattern(t *testing.T) {
resourceUnstructured, err := utils.ConvertToUnstructured(rawResource) resourceUnstructured, err := utils.ConvertToUnstructured(rawResource)
assert.NilError(t, err) assert.NilError(t, err)
er := Validate(PolicyContext{Policy: policy, NewResource: *resourceUnstructured}) er := Validate(PolicyContext{Policy: policy, NewResource: *resourceUnstructured})
msgs := []string{"Validation rule 'check-default-namespace' failed. [anyPattern[0] failed; Validation rule failed at '/metadata/namespace/' to validate value '<nil>' with pattern '?*' anyPattern[1] failed; Validation rule failed at '/metadata/namespace/' to validate value '<nil>' with pattern '!default']"} msgs := []string{"A namespace is required"}
for index, r := range er.PolicyResponse.Rules { for index, r := range er.PolicyResponse.Rules {
assert.Equal(t, r.Message, msgs[index]) assert.Equal(t, r.Message, msgs[index])
} }
@ -1582,5 +1582,5 @@ func Test_VariableSubstitutionPathNotExistInAnyPattern_AllPathPresent_NonePatter
// expectedMsg := "Validation error: ; Validation rule test-path-not-exist anyPattern[0] failed at path /spec/template/spec/containers/0/name/. Validation rule test-path-not-exist anyPattern[1] failed at path /spec/template/spec/containers/0/name/." // expectedMsg := "Validation error: ; Validation rule test-path-not-exist anyPattern[0] failed at path /spec/template/spec/containers/0/name/. Validation rule test-path-not-exist anyPattern[1] failed at path /spec/template/spec/containers/0/name/."
assert.Assert(t, !er.PolicyResponse.Rules[0].Success) assert.Assert(t, !er.PolicyResponse.Rules[0].Success)
assert.Equal(t, er.PolicyResponse.Rules[0].Message, "Validation rule 'test-path-not-exist' failed. [anyPattern[0] failed; Validation rule failed at '/spec/template/spec/containers/0/name/' to validate value 'pod-test-pod' with pattern 'test*' anyPattern[1] failed; Validation rule failed at '/spec/template/spec/containers/0/name/' to validate value 'pod-test-pod' with pattern 'test*']") assert.Equal(t, er.PolicyResponse.Rules[0].Message, "Validation rule 'test-path-not-exist' has failed")
} }

View file

@ -5,6 +5,7 @@ import (
"strings" "strings"
"github.com/go-logr/logr" "github.com/go-logr/logr"
yamlv2 "gopkg.in/yaml.v2"
kyverno "github.com/nirmata/kyverno/pkg/api/kyverno/v1" kyverno "github.com/nirmata/kyverno/pkg/api/kyverno/v1"
"github.com/nirmata/kyverno/pkg/engine/response" "github.com/nirmata/kyverno/pkg/engine/response"
engineutils "github.com/nirmata/kyverno/pkg/engine/utils" engineutils "github.com/nirmata/kyverno/pkg/engine/utils"
@ -37,22 +38,25 @@ func toBlockResource(engineReponses []response.EngineResponse, log logr.Logger)
} }
// getEnforceFailureErrorMsg gets the error messages for failed enforce policy // getEnforceFailureErrorMsg gets the error messages for failed enforce policy
func getEnforceFailureErrorMsg(engineReponses []response.EngineResponse) string { func getEnforceFailureErrorMsg(engineResponses []response.EngineResponse) string {
var str []string policyToRule := make(map[string]interface{})
var resourceInfo string var resourceName string
for _, er := range engineResponses {
for _, er := range engineReponses {
if !er.IsSuccesful() && er.PolicyResponse.ValidationFailureAction == Enforce { if !er.IsSuccesful() && er.PolicyResponse.ValidationFailureAction == Enforce {
resourceInfo = fmt.Sprintf("%s/%s/%s", er.PolicyResponse.Resource.Kind, er.PolicyResponse.Resource.Namespace, er.PolicyResponse.Resource.Name) ruleToReason := make(map[string]string)
str = append(str, fmt.Sprintf("failed policy %s:", er.PolicyResponse.Policy))
for _, rule := range er.PolicyResponse.Rules { for _, rule := range er.PolicyResponse.Rules {
if !rule.Success { if !rule.Success {
str = append(str, rule.ToString()) ruleToReason[rule.Name] = rule.Message
} }
} }
resourceName = fmt.Sprintf("%s/%s/%s", er.PolicyResponse.Resource.Kind, er.PolicyResponse.Resource.Namespace, er.PolicyResponse.Resource.Name)
policyToRule[er.PolicyResponse.Policy] = ruleToReason
} }
} }
return fmt.Sprintf("Resource %s %s", resourceInfo, strings.Join(str, ";"))
result, _ := yamlv2.Marshal(policyToRule)
return "\n\nresource " + resourceName + " was blocked due to the following policies\n\n" + string(result)
} }
// getErrorMsg gets all failed engine response message // getErrorMsg gets all failed engine response message