1
0
Fork 0
mirror of https://github.com/kyverno/kyverno.git synced 2025-03-31 03:45:17 +00:00

skip validation if the resource updates dont violate policy rules (#477)

This commit is contained in:
Shivkumar Dudhani 2019-11-13 13:13:07 -08:00 committed by GitHub
parent d162f52714
commit 7a12e12cb5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 187 additions and 82 deletions

View file

@ -29,7 +29,6 @@ func (t *LastReqTime) Time() time.Time {
func (t *LastReqTime) SetTime(tm time.Time) {
t.mu.Lock()
defer t.mu.Unlock()
glog.V(4).Info("updating last request time")
t.t = tm
}

View file

@ -11,7 +11,7 @@ import (
func Mutate(policyContext PolicyContext) (response EngineResponse) {
startTime := time.Now()
policy := policyContext.Policy
resource := policyContext.Resource
resource := policyContext.NewResource
// policy information
func() {

View file

@ -11,7 +11,9 @@ type PolicyContext struct {
// policy to be processed
Policy kyverno.ClusterPolicy
// resource to be processed
Resource unstructured.Unstructured
NewResource unstructured.Unstructured
// old Resource - Update operations
OldResource unstructured.Unstructured
AdmissionInfo RequestInfo
}

View file

@ -15,44 +15,82 @@ import (
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
)
func startResultResponse(response *EngineResponse, policy kyverno.ClusterPolicy, newR unstructured.Unstructured) {
// set policy information
response.PolicyResponse.Policy = policy.Name
// resource details
response.PolicyResponse.Resource.Name = newR.GetName()
response.PolicyResponse.Resource.Namespace = newR.GetNamespace()
response.PolicyResponse.Resource.Kind = newR.GetKind()
response.PolicyResponse.Resource.APIVersion = newR.GetAPIVersion()
response.PolicyResponse.ValidationFailureAction = policy.Spec.ValidationFailureAction
}
func endResultResponse(response *EngineResponse, startTime time.Time) {
response.PolicyResponse.ProcessingTime = time.Since(startTime)
glog.V(4).Infof("Finished applying validation rules policy %v (%v)", response.PolicyResponse.Policy, response.PolicyResponse.ProcessingTime)
glog.V(4).Infof("Validation Rules appplied succesfully count %v for policy %q", response.PolicyResponse.RulesAppliedCount, response.PolicyResponse.Policy)
}
func incrementAppliedCount(response *EngineResponse) {
// rules applied succesfully count
response.PolicyResponse.RulesAppliedCount++
}
//Validate applies validation rules from policy on the resource
func Validate(policyContext PolicyContext) (response EngineResponse) {
startTime := time.Now()
policy := policyContext.Policy
resource := policyContext.Resource
newR := policyContext.NewResource
oldR := policyContext.OldResource
admissionInfo := policyContext.AdmissionInfo
// policy information
func() {
// set policy information
response.PolicyResponse.Policy = policy.Name
// resource details
response.PolicyResponse.Resource.Name = resource.GetName()
response.PolicyResponse.Resource.Namespace = resource.GetNamespace()
response.PolicyResponse.Resource.Kind = resource.GetKind()
response.PolicyResponse.Resource.APIVersion = resource.GetAPIVersion()
response.PolicyResponse.ValidationFailureAction = policy.Spec.ValidationFailureAction
}()
glog.V(4).Infof("started applying validation rules of policy %q (%v)", policy.Name, startTime)
defer func() {
response.PolicyResponse.ProcessingTime = time.Since(startTime)
glog.V(4).Infof("Finished applying validation rules policy %v (%v)", policy.Name, response.PolicyResponse.ProcessingTime)
glog.V(4).Infof("Validation Rules appplied succesfully count %v for policy %q", response.PolicyResponse.RulesAppliedCount, policy.Name)
}()
incrementAppliedRuleCount := func() {
// rules applied succesfully count
response.PolicyResponse.RulesAppliedCount++
}
// Process new & old resource
if reflect.DeepEqual(oldR, unstructured.Unstructured{}) {
// Create Mode
// Operate on New Resource only
response := validate(policy, newR, admissionInfo)
startResultResponse(response, policy, newR)
defer endResultResponse(response, startTime)
// set PatchedResource with orgin resource if empty
// in order to create policy violation
if reflect.DeepEqual(response.PatchedResource, unstructured.Unstructured{}) {
response.PatchedResource = newR
}
return *response
}
// Update Mode
// Operate on New and Old Resource only
// New resource
oldResponse := validate(policy, oldR, admissionInfo)
newResponse := validate(policy, newR, admissionInfo)
// if the old and new response is same then return empty response
if !isSameResponse(oldResponse, newResponse) {
// there are changes send response
startResultResponse(newResponse, policy, newR)
defer endResultResponse(newResponse, startTime)
return *newResponse
}
// if there are no changes with old and new response then sent empty response
// skip processing
return EngineResponse{}
}
func validate(policy kyverno.ClusterPolicy, resource unstructured.Unstructured, admissionInfo RequestInfo) *EngineResponse {
response := &EngineResponse{}
for _, rule := range policy.Spec.Rules {
if !rule.HasValidate() {
continue
}
startTime := time.Now()
if !matchAdmissionInfo(rule, policyContext.AdmissionInfo) {
if !matchAdmissionInfo(rule, admissionInfo) {
glog.V(3).Infof("rule '%s' cannot be applied on %s/%s/%s, admission permission: %v",
rule.Name, resource.GetKind(), resource.GetNamespace(), resource.GetName(), policyContext.AdmissionInfo)
rule.Name, resource.GetKind(), resource.GetNamespace(), resource.GetName(), admissionInfo)
continue
}
glog.V(4).Infof("Time: Validate matchAdmissionInfo %v", time.Since(startTime))
@ -67,20 +105,52 @@ func Validate(policyContext PolicyContext) (response EngineResponse) {
}
if rule.Validation.Pattern != nil || rule.Validation.AnyPattern != nil {
ruleResponse := validatePatterns(resource, rule)
incrementAppliedRuleCount()
incrementAppliedCount(response)
response.PolicyResponse.Rules = append(response.PolicyResponse.Rules, ruleResponse)
}
}
// set PatchedResource with orgin resource if empty
// in order to create policy violation
if reflect.DeepEqual(response.PatchedResource, unstructured.Unstructured{}) {
response.PatchedResource = resource
}
return response
}
func isSameResponse(oldResponse, newResponse *EngineResponse) bool {
// if the respones are same then return true
return isSamePolicyResponse(oldResponse.PolicyResponse, newResponse.PolicyResponse)
}
func isSamePolicyResponse(oldPolicyRespone, newPolicyResponse PolicyResponse) bool {
// can skip policy and resource checks as they will be same
// compare rules
return isSameRules(oldPolicyRespone.Rules, newPolicyResponse.Rules)
}
func isSameRules(oldRules []RuleResponse, newRules []RuleResponse) bool {
if len(oldRules) != len(newRules) {
return false
}
// as the rules are always processed in order the indices wil be same
for idx, oldrule := range oldRules {
newrule := newRules[idx]
// Name
if oldrule.Name != newrule.Name {
return false
}
// Type
if oldrule.Type != newrule.Type {
return false
}
// Message
if oldrule.Message != newrule.Message {
return false
}
// skip patches
if oldrule.Success != newrule.Success {
return false
}
}
return true
}
// validatePatterns validate pattern and anyPattern
func validatePatterns(resource unstructured.Unstructured, rule kyverno.Rule) (response RuleResponse) {
startTime := time.Now()

View file

@ -1629,7 +1629,7 @@ func TestValidate_ServiceTest(t *testing.T) {
resourceUnstructured, err := ConvertToUnstructured(rawResource)
assert.NilError(t, err)
er := Validate(PolicyContext{Policy: policy, Resource: *resourceUnstructured})
er := Validate(PolicyContext{Policy: policy, NewResource: *resourceUnstructured})
assert.Assert(t, len(er.PolicyResponse.Rules) == 0)
}
@ -1726,7 +1726,7 @@ func TestValidate_MapHasFloats(t *testing.T) {
resourceUnstructured, err := ConvertToUnstructured(rawResource)
assert.NilError(t, err)
er := Validate(PolicyContext{Policy: policy, Resource: *resourceUnstructured})
er := Validate(PolicyContext{Policy: policy, NewResource: *resourceUnstructured})
assert.Assert(t, len(er.PolicyResponse.Rules) == 0)
}
@ -1821,7 +1821,7 @@ func TestValidate_image_tag_fail(t *testing.T) {
"Validation rule 'validate-tag' succeeded.",
"Validation error: imagePullPolicy 'Always' required with tag 'latest'\nValidation rule 'validate-latest' failed at path '/spec/containers/0/imagePullPolicy/'.",
}
er := Validate(PolicyContext{Policy: policy, Resource: *resourceUnstructured})
er := Validate(PolicyContext{Policy: policy, NewResource: *resourceUnstructured})
for index, r := range er.PolicyResponse.Rules {
assert.Equal(t, r.Message, msgs[index])
}
@ -1919,7 +1919,7 @@ func TestValidate_image_tag_pass(t *testing.T) {
"Validation rule 'validate-tag' succeeded.",
"Validation rule 'validate-latest' succeeded.",
}
er := Validate(PolicyContext{Policy: policy, Resource: *resourceUnstructured})
er := Validate(PolicyContext{Policy: policy, NewResource: *resourceUnstructured})
for index, r := range er.PolicyResponse.Rules {
assert.Equal(t, r.Message, msgs[index])
}
@ -1992,7 +1992,7 @@ func TestValidate_Fail_anyPattern(t *testing.T) {
resourceUnstructured, err := ConvertToUnstructured(rawResource)
assert.NilError(t, err)
er := Validate(PolicyContext{Policy: policy, Resource: *resourceUnstructured})
er := Validate(PolicyContext{Policy: policy, NewResource: *resourceUnstructured})
msgs := []string{"Validation error: A namespace is required\nValidation rule check-default-namespace anyPattern[0] failed at path /metadata/namespace/.\nValidation rule check-default-namespace anyPattern[1] failed at path /metadata/namespace/."}
for index, r := range er.PolicyResponse.Rules {
assert.Equal(t, r.Message, msgs[index])
@ -2073,7 +2073,7 @@ func TestValidate_host_network_port(t *testing.T) {
resourceUnstructured, err := ConvertToUnstructured(rawResource)
assert.NilError(t, err)
er := Validate(PolicyContext{Policy: policy, Resource: *resourceUnstructured})
er := Validate(PolicyContext{Policy: policy, NewResource: *resourceUnstructured})
msgs := []string{"Validation error: Host network and port are not allowed\nValidation rule 'validate-host-network-port' failed at path '/spec/containers/0/ports/0/hostPort/'."}
for index, r := range er.PolicyResponse.Rules {
@ -2162,7 +2162,7 @@ func TestValidate_anchor_arraymap_pass(t *testing.T) {
resourceUnstructured, err := ConvertToUnstructured(rawResource)
assert.NilError(t, err)
er := Validate(PolicyContext{Policy: policy, Resource: *resourceUnstructured})
er := Validate(PolicyContext{Policy: policy, NewResource: *resourceUnstructured})
msgs := []string{"Validation rule 'validate-host-path' succeeded."}
for index, r := range er.PolicyResponse.Rules {
@ -2250,7 +2250,7 @@ func TestValidate_anchor_arraymap_fail(t *testing.T) {
resourceUnstructured, err := ConvertToUnstructured(rawResource)
assert.NilError(t, err)
er := Validate(PolicyContext{Policy: policy, Resource: *resourceUnstructured})
er := Validate(PolicyContext{Policy: policy, NewResource: *resourceUnstructured})
msgs := []string{"Validation error: Host path '/var/lib/' is not allowed\nValidation rule 'validate-host-path' failed at path '/spec/volumes/0/hostPath/path/'."}
for index, r := range er.PolicyResponse.Rules {
@ -2319,7 +2319,7 @@ func TestValidate_anchor_map_notfound(t *testing.T) {
resourceUnstructured, err := ConvertToUnstructured(rawResource)
assert.NilError(t, err)
er := Validate(PolicyContext{Policy: policy, Resource: *resourceUnstructured})
er := Validate(PolicyContext{Policy: policy, NewResource: *resourceUnstructured})
msgs := []string{"Validation rule 'pod rule 2' succeeded."}
for index, r := range er.PolicyResponse.Rules {
@ -2391,7 +2391,7 @@ func TestValidate_anchor_map_found_valid(t *testing.T) {
resourceUnstructured, err := ConvertToUnstructured(rawResource)
assert.NilError(t, err)
er := Validate(PolicyContext{Policy: policy, Resource: *resourceUnstructured})
er := Validate(PolicyContext{Policy: policy, NewResource: *resourceUnstructured})
msgs := []string{"Validation rule 'pod rule 2' succeeded."}
for index, r := range er.PolicyResponse.Rules {
@ -2463,7 +2463,7 @@ func TestValidate_anchor_map_found_invalid(t *testing.T) {
resourceUnstructured, err := ConvertToUnstructured(rawResource)
assert.NilError(t, err)
er := Validate(PolicyContext{Policy: policy, Resource: *resourceUnstructured})
er := Validate(PolicyContext{Policy: policy, NewResource: *resourceUnstructured})
msgs := []string{"Validation error: pod: validate run as non root user\nValidation rule 'pod rule 2' failed at path '/spec/securityContext/runAsNonRoot/'."}
for index, r := range er.PolicyResponse.Rules {
@ -2537,7 +2537,7 @@ func TestValidate_AnchorList_pass(t *testing.T) {
resourceUnstructured, err := ConvertToUnstructured(rawResource)
assert.NilError(t, err)
er := Validate(PolicyContext{Policy: policy, Resource: *resourceUnstructured})
er := Validate(PolicyContext{Policy: policy, NewResource: *resourceUnstructured})
msgs := []string{"Validation rule 'pod image rule' succeeded."}
for index, r := range er.PolicyResponse.Rules {
@ -2611,7 +2611,7 @@ func TestValidate_AnchorList_fail(t *testing.T) {
resourceUnstructured, err := ConvertToUnstructured(rawResource)
assert.NilError(t, err)
er := Validate(PolicyContext{Policy: policy, Resource: *resourceUnstructured})
er := Validate(PolicyContext{Policy: policy, NewResource: *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)
@ -2685,7 +2685,7 @@ func TestValidate_existenceAnchor_fail(t *testing.T) {
resourceUnstructured, err := ConvertToUnstructured(rawResource)
assert.NilError(t, err)
er := Validate(PolicyContext{Policy: policy, Resource: *resourceUnstructured})
er := Validate(PolicyContext{Policy: policy, NewResource: *resourceUnstructured})
// msgs := []string{"Validation rule 'pod image rule' failed at '/spec/containers/' for resource Pod//myapp-pod."}
// for index, r := range er.PolicyResponse.Rules {
@ -2760,7 +2760,7 @@ func TestValidate_existenceAnchor_pass(t *testing.T) {
resourceUnstructured, err := ConvertToUnstructured(rawResource)
assert.NilError(t, err)
er := Validate(PolicyContext{Policy: policy, Resource: *resourceUnstructured})
er := Validate(PolicyContext{Policy: policy, NewResource: *resourceUnstructured})
msgs := []string{"Validation rule 'pod image rule' succeeded."}
for index, r := range er.PolicyResponse.Rules {
@ -2847,7 +2847,7 @@ func TestValidate_negationAnchor_deny(t *testing.T) {
resourceUnstructured, err := ConvertToUnstructured(rawResource)
assert.NilError(t, err)
er := Validate(PolicyContext{Policy: policy, Resource: *resourceUnstructured})
er := Validate(PolicyContext{Policy: policy, NewResource: *resourceUnstructured})
msgs := []string{"Validation error: Host path is not allowed\nValidation rule 'validate-host-path' failed at path '/spec/volumes/0/hostPath/'."}
for index, r := range er.PolicyResponse.Rules {
@ -2933,7 +2933,7 @@ func TestValidate_negationAnchor_pass(t *testing.T) {
resourceUnstructured, err := ConvertToUnstructured(rawResource)
assert.NilError(t, err)
er := Validate(PolicyContext{Policy: policy, Resource: *resourceUnstructured})
er := Validate(PolicyContext{Policy: policy, NewResource: *resourceUnstructured})
msgs := []string{"Validation rule 'validate-host-path' succeeded."}
for index, r := range er.PolicyResponse.Rules {

View file

@ -105,7 +105,7 @@ func applyPolicyOnRaw(policy *kyverno.ClusterPolicy, rawResource []byte, gvk *me
}
//TODO check if the kind information is present resource
// Process Mutation
engineResponse := engine.Mutate(engine.PolicyContext{Policy: *policy, Resource: *resource})
engineResponse := engine.Mutate(engine.PolicyContext{Policy: *policy, NewResource: *resource})
if !engineResponse.IsSuccesful() {
glog.Infof("Failed to apply policy %s on resource %s/%s", policy.Name, rname, rns)
for _, r := range engineResponse.PolicyResponse.Rules {
@ -115,7 +115,7 @@ func applyPolicyOnRaw(policy *kyverno.ClusterPolicy, rawResource []byte, gvk *me
glog.Infof("Mutation from policy %s has applied succesfully to %s %s/%s", policy.Name, gvk.Kind, rname, rns)
// Process Validation
engineResponse := engine.Validate(engine.PolicyContext{Policy: *policy, Resource: *resource})
engineResponse := engine.Validate(engine.PolicyContext{Policy: *policy, NewResource: *resource})
if !engineResponse.IsSuccesful() {
glog.Infof("Failed to apply policy %s on resource %s/%s", policy.Name, rname, rns)

View file

@ -69,7 +69,7 @@ func applyPolicy(policy kyverno.ClusterPolicy, resource unstructured.Unstructure
sendStat(false)
//VALIDATION
engineResponse = engine.Validate(engine.PolicyContext{Policy: policy, Resource: resource})
engineResponse = engine.Validate(engine.PolicyContext{Policy: policy, NewResource: 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(engine.PolicyContext{Policy: policy, Resource: resource})
engineResponse := engine.Mutate(engine.PolicyContext{Policy: policy, NewResource: resource})
if !engineResponse.IsSuccesful() {
glog.V(4).Infof("mutation had errors reporting them")
return engineResponse, nil

View file

@ -148,7 +148,7 @@ func runTestCase(t *testing.T, tc scaseT) bool {
var er engine.EngineResponse
er = engine.Mutate(engine.PolicyContext{Policy: *policy, Resource: *resource})
er = engine.Mutate(engine.PolicyContext{Policy: *policy, NewResource: *resource})
t.Log("---Mutation---")
validateResource(t, er.PatchedResource, tc.Expected.Mutation.PatchedResource)
validateResponse(t, er.PolicyResponse, tc.Expected.Mutation.PolicyResponse)
@ -158,7 +158,7 @@ func runTestCase(t *testing.T, tc scaseT) bool {
resource = &er.PatchedResource
}
er = engine.Validate(engine.PolicyContext{Policy: *policy, Resource: *resource})
er = engine.Validate(engine.PolicyContext{Policy: *policy, NewResource: *resource})
t.Log("---Validation---")
validateResponse(t, er.PolicyResponse, tc.Expected.Validation.PolicyResponse)

View file

@ -64,7 +64,7 @@ func (ws *WebhookServer) HandleMutation(request *v1beta1.AdmissionRequest, polic
var engineResponses []engine.EngineResponse
policyContext := engine.PolicyContext{
Resource: *resource,
NewResource: *resource,
AdmissionInfo: engine.RequestInfo{
Roles: roles,
ClusterRoles: clusterRoles,

View file

@ -7,6 +7,9 @@ import (
"github.com/golang/glog"
kyverno "github.com/nirmata/kyverno/pkg/api/kyverno/v1alpha1"
"github.com/nirmata/kyverno/pkg/engine"
"k8s.io/api/admission/v1beta1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime/schema"
)
func isResponseSuccesful(engineReponses []engine.EngineResponse) bool {
@ -109,3 +112,42 @@ func containRBACinfo(policies []kyverno.ClusterPolicy) bool {
}
return false
}
// extracts the new and old resource as unstructured
func extractResources(request *v1beta1.AdmissionRequest) (unstructured.Unstructured, unstructured.Unstructured, error) {
var emptyResource unstructured.Unstructured
var err error
// New Resource
newRaw := request.Object.Raw
if newRaw == nil {
return emptyResource, emptyResource, fmt.Errorf("new resource is not defined")
}
new, err := convertToUnstructured(newRaw)
if err != nil {
return emptyResource, emptyResource, fmt.Errorf("failed to convert new raw to unstructured: %v", err)
}
new.SetGroupVersionKind(schema.GroupVersionKind{Group: request.Kind.Group, Version: request.Kind.Version, Kind: request.Kind.Kind})
new.SetNamespace(request.Namespace)
// Old Resource - Optional
oldRaw := request.OldObject.Raw
if oldRaw == nil {
return *new, emptyResource, nil
}
old, err := convertToUnstructured((oldRaw))
if err != nil {
return emptyResource, emptyResource, fmt.Errorf("failed to convert old raw to unstructured: %v", err)
}
old.SetGroupVersionKind(schema.GroupVersionKind{Group: request.Kind.Group, Version: request.Kind.Version, Kind: request.Kind.Kind})
old.SetNamespace(request.Namespace)
return *new, *old, err
}
func convertToUnstructured(data []byte) (*unstructured.Unstructured, error) {
resource := &unstructured.Unstructured{}
err := resource.UnmarshalJSON(data)
if err != nil {
glog.V(4).Infof("failed to unmarshall resource: %v", err)
return nil, err
}
return resource, nil
}

View file

@ -1,6 +1,7 @@
package webhooks
import (
"reflect"
"time"
"github.com/golang/glog"
@ -9,7 +10,6 @@ import (
policyctr "github.com/nirmata/kyverno/pkg/policy"
"github.com/nirmata/kyverno/pkg/utils"
v1beta1 "k8s.io/api/admission/v1beta1"
"k8s.io/apimachinery/pkg/runtime/schema"
)
// handleValidation handles validating webhook admission request
@ -50,30 +50,17 @@ func (ws *WebhookServer) HandleValidation(request *v1beta1.AdmissionRequest, pol
}
}
resourceRaw := request.Object.Raw
if patchedResource != nil {
glog.V(4).Info("using patched resource from mutation to process validation rules")
resourceRaw = patchedResource
}
// convert RAW to unstructured
resource, err := engine.ConvertToUnstructured(resourceRaw)
// Get new and old resource
newR, oldR, err := extractResources(request)
if err != nil {
//TODO: skip applying the amiddions control ?
glog.Errorf("unable to convert raw resource to unstructured: %v", err)
// as resource cannot be parsed, we skip processing
glog.Error(err)
return true, ""
}
//TODO: check if resource gvk is available in raw resource,
// if not then set it from the api request
resource.SetGroupVersionKind(schema.GroupVersionKind{Group: request.Kind.Group, Version: request.Kind.Version, Kind: request.Kind.Kind})
//TODO: check if the name is also passed right in the resource?
// all the patches to be applied on the resource
// explictly set resource namespace with request namespace
// resource namespace is empty for the first CREATE operation
resource.SetNamespace(request.Namespace)
policyContext := engine.PolicyContext{
Resource: *resource,
NewResource: newR,
OldResource: oldR,
AdmissionInfo: engine.RequestInfo{
Roles: roles,
ClusterRoles: clusterRoles,
@ -83,15 +70,20 @@ func (ws *WebhookServer) HandleValidation(request *v1beta1.AdmissionRequest, pol
var engineResponses []engine.EngineResponse
for _, policy := range policies {
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)
newR.GetKind(), newR.GetNamespace(), newR.GetName(), request.UID, request.Operation)
policyContext.Policy = policy
engineResponse := engine.Validate(policyContext)
if reflect.DeepEqual(engineResponse, engine.EngineResponse{}) {
// we get an empty response if old and new resources created the same response
// allow updates if resource update doesnt change the policy evaluation
continue
}
engineResponses = append(engineResponses, engineResponse)
// Gather policy application statistics
gatherStat(policy.Name, engineResponse.PolicyResponse)
if !engineResponse.IsSuccesful() {
glog.V(4).Infof("Failed to apply policy %s on resource %s/%s\n", policy.Name, resource.GetNamespace(), resource.GetName())
glog.V(4).Infof("Failed to apply policy %s on resource %s/%s\n", policy.Name, newR.GetNamespace(), newR.GetName())
continue
}
}
@ -109,7 +101,7 @@ func (ws *WebhookServer) HandleValidation(request *v1beta1.AdmissionRequest, pol
blocked := toBlockResource(engineResponses)
if !isResponseSuccesful(engineResponses) && blocked {
glog.V(4).Infof("resource %s/%s/%s is blocked\n", resource.GetKind(), resource.GetNamespace(), resource.GetName())
glog.V(4).Infof("resource %s/%s/%s is blocked\n", newR.GetKind(), newR.GetNamespace(), newR.GetName())
pvInfos := generatePV(engineResponses, true)
ws.pvGenerator.Add(pvInfos...)
sendStat(true)