mirror of
https://github.com/kyverno/kyverno.git
synced 2025-03-31 03:45:17 +00:00
change engine interface to take policyContext struct
This commit is contained in:
parent
0e9a952d64
commit
6048d59949
7 changed files with 85 additions and 28 deletions
|
@ -5,13 +5,15 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/golang/glog"
|
||||
kyverno "github.com/nirmata/kyverno/pkg/api/kyverno/v1alpha1"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
)
|
||||
|
||||
// Mutate performs mutation. Overlay first and then mutation patches
|
||||
func Mutate(policy kyverno.ClusterPolicy, resource unstructured.Unstructured) (response EngineResponse) {
|
||||
func Mutate(policyContext PolicyContext) (response EngineResponse) {
|
||||
startTime := time.Now()
|
||||
policy := policyContext.Policy
|
||||
resource := policyContext.Resource
|
||||
|
||||
// policy information
|
||||
func() {
|
||||
// set policy information
|
||||
|
@ -40,6 +42,13 @@ func Mutate(policy kyverno.ClusterPolicy, resource unstructured.Unstructured) (r
|
|||
if !rule.HasMutate() {
|
||||
continue
|
||||
}
|
||||
|
||||
if !matchAdmissionInfo(rule, policyContext.AdmissionInfo) {
|
||||
glog.Infof("rule '%s' cannot be applied on %s/%s/%s, admission permission: %v",
|
||||
rule.Name, resource.GetKind(), resource.GetNamespace(), resource.GetName(), policyContext.AdmissionInfo)
|
||||
continue
|
||||
}
|
||||
|
||||
// check if the resource satisfies the filter conditions defined in the rule
|
||||
//TODO: this needs to be extracted, to filter the resource so that we can avoid passing resources that
|
||||
// dont statisfy a policy rule resource description
|
||||
|
|
26
pkg/engine/policyContext.go
Normal file
26
pkg/engine/policyContext.go
Normal file
|
@ -0,0 +1,26 @@
|
|||
package engine
|
||||
|
||||
import (
|
||||
kyverno "github.com/nirmata/kyverno/pkg/api/kyverno/v1alpha1"
|
||||
authenticationv1 "k8s.io/api/authentication/v1"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
)
|
||||
|
||||
// PolicyContext contains the contexts for engine to process
|
||||
type PolicyContext struct {
|
||||
// policy to be processed
|
||||
Policy kyverno.ClusterPolicy
|
||||
// resource to be processed
|
||||
Resource unstructured.Unstructured
|
||||
AdmissionInfo RequestInfo
|
||||
}
|
||||
|
||||
// RequestInfo contains permission info carried in an admission request
|
||||
type RequestInfo struct {
|
||||
// Roles is a list of possible role send the request
|
||||
Roles []string
|
||||
// ClusterRoles is a list of possible clusterRoles send the request
|
||||
ClusterRoles []string
|
||||
// UserInfo is the userInfo carried in the admission request
|
||||
AdmissionUserInfo authenticationv1.UserInfo
|
||||
}
|
|
@ -16,8 +16,11 @@ import (
|
|||
)
|
||||
|
||||
//Validate applies validation rules from policy on the resource
|
||||
func Validate(policy kyverno.ClusterPolicy, resource unstructured.Unstructured) (response EngineResponse) {
|
||||
func Validate(policyContext PolicyContext) (response EngineResponse) {
|
||||
startTime := time.Now()
|
||||
policy := policyContext.Policy
|
||||
resource := policyContext.Resource
|
||||
|
||||
// policy information
|
||||
func() {
|
||||
// set policy information
|
||||
|
|
|
@ -1628,7 +1628,8 @@ func TestValidate_ServiceTest(t *testing.T) {
|
|||
|
||||
resourceUnstructured, err := ConvertToUnstructured(rawResource)
|
||||
assert.NilError(t, err)
|
||||
er := Validate(policy, *resourceUnstructured)
|
||||
|
||||
er := Validate(PolicyContext{Policy: policy, Resource: *resourceUnstructured})
|
||||
assert.Assert(t, len(er.PolicyResponse.Rules) == 0)
|
||||
}
|
||||
|
||||
|
@ -1725,7 +1726,7 @@ func TestValidate_MapHasFloats(t *testing.T) {
|
|||
|
||||
resourceUnstructured, err := ConvertToUnstructured(rawResource)
|
||||
assert.NilError(t, err)
|
||||
er := Validate(policy, *resourceUnstructured)
|
||||
er := Validate(PolicyContext{Policy: policy, Resource: *resourceUnstructured})
|
||||
assert.Assert(t, len(er.PolicyResponse.Rules) == 0)
|
||||
}
|
||||
|
||||
|
@ -1820,7 +1821,7 @@ func TestValidate_image_tag_fail(t *testing.T) {
|
|||
"Validation rule 'validate-tag' succesfully validated",
|
||||
"Validation rule 'validate-latest' failed at '/spec/containers/0/imagePullPolicy/' for resource Pod//myapp-pod. imagePullPolicy 'Always' required with tag 'latest'.",
|
||||
}
|
||||
er := Validate(policy, *resourceUnstructured)
|
||||
er := Validate(PolicyContext{Policy: policy, Resource: *resourceUnstructured})
|
||||
for index, r := range er.PolicyResponse.Rules {
|
||||
assert.Equal(t, r.Message, msgs[index])
|
||||
}
|
||||
|
@ -1918,7 +1919,7 @@ func TestValidate_image_tag_pass(t *testing.T) {
|
|||
"Validation rule 'validate-tag' succesfully validated",
|
||||
"Validation rule 'validate-latest' succesfully validated",
|
||||
}
|
||||
er := Validate(policy, *resourceUnstructured)
|
||||
er := Validate(PolicyContext{Policy: policy, Resource: *resourceUnstructured})
|
||||
for index, r := range er.PolicyResponse.Rules {
|
||||
assert.Equal(t, r.Message, msgs[index])
|
||||
}
|
||||
|
@ -1991,7 +1992,7 @@ func TestValidate_Fail_anyPattern(t *testing.T) {
|
|||
|
||||
resourceUnstructured, err := ConvertToUnstructured(rawResource)
|
||||
assert.NilError(t, err)
|
||||
er := Validate(policy, *resourceUnstructured)
|
||||
er := Validate(PolicyContext{Policy: policy, Resource: *resourceUnstructured})
|
||||
msgs := []string{"Validation rule 'check-default-namespace' failed to validate patterns defined in anyPattern. A namespace is required.; anyPattern[0] failed at path /metadata/namespace/; anyPattern[1] failed at path /metadata/namespace/"}
|
||||
for index, r := range er.PolicyResponse.Rules {
|
||||
assert.Equal(t, r.Message, msgs[index])
|
||||
|
@ -2072,7 +2073,7 @@ func TestValidate_host_network_port(t *testing.T) {
|
|||
|
||||
resourceUnstructured, err := ConvertToUnstructured(rawResource)
|
||||
assert.NilError(t, err)
|
||||
er := Validate(policy, *resourceUnstructured)
|
||||
er := Validate(PolicyContext{Policy: policy, Resource: *resourceUnstructured})
|
||||
msgs := []string{"Validation rule 'validate-host-network-port' failed at '/spec/containers/0/ports/0/hostPort/' for resource Pod//nginx-host-network. Host network and port are not allowed."}
|
||||
|
||||
for index, r := range er.PolicyResponse.Rules {
|
||||
|
@ -2161,7 +2162,7 @@ func TestValidate_anchor_arraymap_pass(t *testing.T) {
|
|||
|
||||
resourceUnstructured, err := ConvertToUnstructured(rawResource)
|
||||
assert.NilError(t, err)
|
||||
er := Validate(policy, *resourceUnstructured)
|
||||
er := Validate(PolicyContext{Policy: policy, Resource: *resourceUnstructured})
|
||||
msgs := []string{"Validation rule 'validate-host-path' succesfully validated"}
|
||||
|
||||
for index, r := range er.PolicyResponse.Rules {
|
||||
|
@ -2249,7 +2250,7 @@ func TestValidate_anchor_arraymap_fail(t *testing.T) {
|
|||
|
||||
resourceUnstructured, err := ConvertToUnstructured(rawResource)
|
||||
assert.NilError(t, err)
|
||||
er := Validate(policy, *resourceUnstructured)
|
||||
er := Validate(PolicyContext{Policy: policy, Resource: *resourceUnstructured})
|
||||
msgs := []string{"Validation rule 'validate-host-path' failed at '/spec/volumes/0/hostPath/path/' for resource Pod//image-with-hostpath. Host path '/var/lib/' is not allowed."}
|
||||
|
||||
for index, r := range er.PolicyResponse.Rules {
|
||||
|
@ -2318,7 +2319,7 @@ func TestValidate_anchor_map_notfound(t *testing.T) {
|
|||
|
||||
resourceUnstructured, err := ConvertToUnstructured(rawResource)
|
||||
assert.NilError(t, err)
|
||||
er := Validate(policy, *resourceUnstructured)
|
||||
er := Validate(PolicyContext{Policy: policy, Resource: *resourceUnstructured})
|
||||
msgs := []string{"Validation rule 'pod rule 2' succesfully validated"}
|
||||
|
||||
for index, r := range er.PolicyResponse.Rules {
|
||||
|
@ -2390,7 +2391,7 @@ func TestValidate_anchor_map_found_valid(t *testing.T) {
|
|||
|
||||
resourceUnstructured, err := ConvertToUnstructured(rawResource)
|
||||
assert.NilError(t, err)
|
||||
er := Validate(policy, *resourceUnstructured)
|
||||
er := Validate(PolicyContext{Policy: policy, Resource: *resourceUnstructured})
|
||||
msgs := []string{"Validation rule 'pod rule 2' succesfully validated"}
|
||||
|
||||
for index, r := range er.PolicyResponse.Rules {
|
||||
|
@ -2462,7 +2463,7 @@ func TestValidate_anchor_map_found_invalid(t *testing.T) {
|
|||
|
||||
resourceUnstructured, err := ConvertToUnstructured(rawResource)
|
||||
assert.NilError(t, err)
|
||||
er := Validate(policy, *resourceUnstructured)
|
||||
er := Validate(PolicyContext{Policy: policy, Resource: *resourceUnstructured})
|
||||
msgs := []string{"Validation rule 'pod rule 2' failed at '/spec/securityContext/runAsNonRoot/' for resource Pod//myapp-pod. pod: validate run as non root user."}
|
||||
|
||||
for index, r := range er.PolicyResponse.Rules {
|
||||
|
@ -2536,7 +2537,7 @@ func TestValidate_AnchorList_pass(t *testing.T) {
|
|||
|
||||
resourceUnstructured, err := ConvertToUnstructured(rawResource)
|
||||
assert.NilError(t, err)
|
||||
er := Validate(policy, *resourceUnstructured)
|
||||
er := Validate(PolicyContext{Policy: policy, Resource: *resourceUnstructured})
|
||||
msgs := []string{"Validation rule 'pod image rule' succesfully validated"}
|
||||
|
||||
for index, r := range er.PolicyResponse.Rules {
|
||||
|
@ -2610,7 +2611,7 @@ func TestValidate_AnchorList_fail(t *testing.T) {
|
|||
|
||||
resourceUnstructured, err := ConvertToUnstructured(rawResource)
|
||||
assert.NilError(t, err)
|
||||
er := Validate(policy, *resourceUnstructured)
|
||||
er := Validate(PolicyContext{Policy: policy, Resource: *resourceUnstructured})
|
||||
// msgs := []string{"Validation rule 'pod image rule' failed at '/spec/containers/1/name/' for resource Pod//myapp-pod."}
|
||||
// for index, r := range er.PolicyResponse.Rules {
|
||||
// // t.Log(r.Message)
|
||||
|
@ -2684,7 +2685,7 @@ func TestValidate_existenceAnchor_fail(t *testing.T) {
|
|||
|
||||
resourceUnstructured, err := ConvertToUnstructured(rawResource)
|
||||
assert.NilError(t, err)
|
||||
er := Validate(policy, *resourceUnstructured)
|
||||
er := Validate(PolicyContext{Policy: policy, Resource: *resourceUnstructured})
|
||||
// msgs := []string{"Validation rule 'pod image rule' failed at '/spec/containers/' for resource Pod//myapp-pod."}
|
||||
|
||||
// for index, r := range er.PolicyResponse.Rules {
|
||||
|
@ -2759,7 +2760,7 @@ func TestValidate_existenceAnchor_pass(t *testing.T) {
|
|||
|
||||
resourceUnstructured, err := ConvertToUnstructured(rawResource)
|
||||
assert.NilError(t, err)
|
||||
er := Validate(policy, *resourceUnstructured)
|
||||
er := Validate(PolicyContext{Policy: policy, Resource: *resourceUnstructured})
|
||||
msgs := []string{"Validation rule 'pod image rule' succesfully validated"}
|
||||
|
||||
for index, r := range er.PolicyResponse.Rules {
|
||||
|
@ -2846,7 +2847,7 @@ func TestValidate_negationAnchor_deny(t *testing.T) {
|
|||
|
||||
resourceUnstructured, err := ConvertToUnstructured(rawResource)
|
||||
assert.NilError(t, err)
|
||||
er := Validate(policy, *resourceUnstructured)
|
||||
er := Validate(PolicyContext{Policy: policy, Resource: *resourceUnstructured})
|
||||
msgs := []string{"Validation rule 'validate-host-path' failed at '/spec/volumes/0/hostPath/' for resource Pod//image-with-hostpath. Host path is not allowed."}
|
||||
|
||||
for index, r := range er.PolicyResponse.Rules {
|
||||
|
@ -2932,7 +2933,7 @@ func TestValidate_negationAnchor_pass(t *testing.T) {
|
|||
|
||||
resourceUnstructured, err := ConvertToUnstructured(rawResource)
|
||||
assert.NilError(t, err)
|
||||
er := Validate(policy, *resourceUnstructured)
|
||||
er := Validate(PolicyContext{Policy: policy, Resource: *resourceUnstructured})
|
||||
msgs := []string{"Validation rule 'validate-host-path' succesfully validated"}
|
||||
|
||||
for index, r := range er.PolicyResponse.Rules {
|
||||
|
|
|
@ -69,7 +69,7 @@ func applyPolicy(policy kyverno.ClusterPolicy, resource unstructured.Unstructure
|
|||
sendStat(false)
|
||||
|
||||
//VALIDATION
|
||||
engineResponse = engine.Validate(policy, resource)
|
||||
engineResponse = engine.Validate(engine.PolicyContext{Policy: policy, Resource: resource})
|
||||
engineResponses = append(engineResponses, engineResponse)
|
||||
// gather stats
|
||||
gatherStat(policy.Name, engineResponse.PolicyResponse)
|
||||
|
@ -80,7 +80,7 @@ func applyPolicy(policy kyverno.ClusterPolicy, resource unstructured.Unstructure
|
|||
return engineResponses
|
||||
}
|
||||
func mutation(policy kyverno.ClusterPolicy, resource unstructured.Unstructured, policyStatus PolicyStatusInterface) (engine.EngineResponse, error) {
|
||||
engineResponse := engine.Mutate(policy, resource)
|
||||
engineResponse := engine.Mutate(engine.PolicyContext{Policy: policy, Resource: resource})
|
||||
if !engineResponse.IsSuccesful() {
|
||||
glog.V(4).Infof("mutation had errors reporting them")
|
||||
return engineResponse, nil
|
||||
|
|
|
@ -11,7 +11,8 @@ import (
|
|||
)
|
||||
|
||||
// HandleMutation handles mutating webhook admission request
|
||||
func (ws *WebhookServer) HandleMutation(request *v1beta1.AdmissionRequest, policies []*v1alpha1.ClusterPolicy) (bool, []byte, string) {
|
||||
func (ws *WebhookServer) HandleMutation(request *v1beta1.AdmissionRequest,
|
||||
policies []*v1alpha1.ClusterPolicy, roles, clusterRoles []string) (bool, []byte, string) {
|
||||
glog.V(4).Infof("Receive request in mutating webhook: Kind=%s, Namespace=%s Name=%s UID=%s patchOperation=%s",
|
||||
request.Kind.Kind, request.Namespace, request.Name, request.UID, request.Operation)
|
||||
|
||||
|
@ -63,8 +64,16 @@ func (ws *WebhookServer) HandleMutation(request *v1beta1.AdmissionRequest, polic
|
|||
resource.SetGroupVersionKind(schema.GroupVersionKind{Group: request.Kind.Group, Version: request.Kind.Version, Kind: request.Kind.Kind})
|
||||
|
||||
var engineResponses []engine.EngineResponse
|
||||
for _, policy := range policies {
|
||||
policyContext := engine.PolicyContext{
|
||||
Resource: *resource,
|
||||
AdmissionInfo: engine.RequestInfo{
|
||||
Roles: roles,
|
||||
ClusterRoles: clusterRoles,
|
||||
AdmissionUserInfo: request.UserInfo},
|
||||
}
|
||||
|
||||
for _, policy := range policies {
|
||||
policyContext.Policy = *policy
|
||||
// check if policy has a rule for the admission request kind
|
||||
if !utils.ContainsString(getApplicableKindsForPolicy(policy), request.Kind.Kind) {
|
||||
continue
|
||||
|
@ -73,7 +82,7 @@ func (ws *WebhookServer) HandleMutation(request *v1beta1.AdmissionRequest, polic
|
|||
glog.V(2).Infof("Handling mutation for Kind=%s, Namespace=%s Name=%s UID=%s patchOperation=%s",
|
||||
resource.GetKind(), resource.GetNamespace(), resource.GetName(), request.UID, request.Operation)
|
||||
// TODO: this can be
|
||||
engineResponse := engine.Mutate(*policy, *resource)
|
||||
engineResponse := engine.Mutate(policyContext)
|
||||
engineResponses = append(engineResponses, engineResponse)
|
||||
// Gather policy application statistics
|
||||
gatherStat(policy.Name, engineResponse.PolicyResponse)
|
||||
|
|
|
@ -14,7 +14,8 @@ import (
|
|||
// HandleValidation handles validating webhook admission request
|
||||
// If there are no errors in validating rule we apply generation rules
|
||||
// patchedResource is the (resource + patches) after applying mutation rules
|
||||
func (ws *WebhookServer) HandleValidation(request *v1beta1.AdmissionRequest, policies []*v1alpha1.ClusterPolicy, patchedResource []byte) (bool, string) {
|
||||
func (ws *WebhookServer) HandleValidation(request *v1beta1.AdmissionRequest,
|
||||
policies []*v1alpha1.ClusterPolicy, patchedResource []byte, roles, clusterRoles []string) (bool, string) {
|
||||
glog.V(4).Infof("Receive request in validating webhook: Kind=%s, Namespace=%s Name=%s UID=%s patchOperation=%s",
|
||||
request.Kind.Kind, request.Namespace, request.Name, request.UID, request.Operation)
|
||||
|
||||
|
@ -71,9 +72,17 @@ func (ws *WebhookServer) HandleValidation(request *v1beta1.AdmissionRequest, pol
|
|||
// resource namespace is empty for the first CREATE operation
|
||||
resource.SetNamespace(request.Namespace)
|
||||
|
||||
policyContext := engine.PolicyContext{
|
||||
Resource: *resource,
|
||||
AdmissionInfo: engine.RequestInfo{
|
||||
Roles: roles,
|
||||
ClusterRoles: clusterRoles,
|
||||
AdmissionUserInfo: request.UserInfo},
|
||||
}
|
||||
|
||||
var engineResponses []engine.EngineResponse
|
||||
for _, policy := range policies {
|
||||
|
||||
policyContext.Policy = *policy
|
||||
if !utils.ContainsString(getApplicableKindsForPolicy(policy), request.Kind.Kind) {
|
||||
continue
|
||||
}
|
||||
|
@ -81,7 +90,7 @@ func (ws *WebhookServer) HandleValidation(request *v1beta1.AdmissionRequest, pol
|
|||
glog.V(2).Infof("Handling validation for Kind=%s, Namespace=%s Name=%s UID=%s patchOperation=%s",
|
||||
resource.GetKind(), resource.GetNamespace(), resource.GetName(), request.UID, request.Operation)
|
||||
|
||||
engineResponse := engine.Validate(*policy, *resource)
|
||||
engineResponse := engine.Validate(policyContext)
|
||||
engineResponses = append(engineResponses, engineResponse)
|
||||
// Gather policy application statistics
|
||||
gatherStat(policy.Name, engineResponse.PolicyResponse)
|
||||
|
|
Loading…
Add table
Reference in a new issue