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

change to use validationFailureAction for the mutation failure action

This commit is contained in:
Shuting Zhao 2020-01-16 11:57:28 -08:00
parent 7e59e8e484
commit ba8030bec0
6 changed files with 87 additions and 34 deletions

View file

@ -13,6 +13,7 @@ import (
"github.com/nirmata/kyverno/pkg/engine/response" "github.com/nirmata/kyverno/pkg/engine/response"
"github.com/nirmata/kyverno/pkg/engine/utils" "github.com/nirmata/kyverno/pkg/engine/utils"
"github.com/nirmata/kyverno/pkg/engine/variables" "github.com/nirmata/kyverno/pkg/engine/variables"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
) )
const ( const (
@ -28,22 +29,10 @@ func Mutate(policyContext PolicyContext) (resp response.EngineResponse) {
resource := policyContext.NewResource resource := policyContext.NewResource
ctx := policyContext.Context ctx := policyContext.Context
// policy information startMutateResultResponse(&resp, policy, resource)
func() {
// set policy information
resp.PolicyResponse.Policy = policy.Name
// resource details
resp.PolicyResponse.Resource.Name = resource.GetName()
resp.PolicyResponse.Resource.Namespace = resource.GetNamespace()
resp.PolicyResponse.Resource.Kind = resource.GetKind()
resp.PolicyResponse.Resource.APIVersion = resource.GetAPIVersion()
}()
glog.V(4).Infof("started applying mutation rules of policy %q (%v)", policy.Name, startTime) glog.V(4).Infof("started applying mutation rules of policy %q (%v)", policy.Name, startTime)
defer func() { defer endMutateResultResponse(&resp, startTime)
resp.PolicyResponse.ProcessingTime = time.Since(startTime)
glog.V(4).Infof("finished applying mutation rules policy %v (%v)", policy.Name, resp.PolicyResponse.ProcessingTime)
glog.V(4).Infof("Mutation Rules appplied count %v for policy %q", resp.PolicyResponse.RulesAppliedCount, policy.Name)
}()
incrementAppliedRuleCount := func() { incrementAppliedRuleCount := func() {
// rules applied succesfully count // rules applied succesfully count
resp.PolicyResponse.RulesAppliedCount++ resp.PolicyResponse.RulesAppliedCount++
@ -146,6 +135,24 @@ func Mutate(policyContext PolicyContext) (resp response.EngineResponse) {
return resp return resp
} }
func startMutateResultResponse(resp *response.EngineResponse, policy kyverno.ClusterPolicy, resource unstructured.Unstructured) {
// set policy information
resp.PolicyResponse.Policy = policy.Name
// resource details
resp.PolicyResponse.Resource.Name = resource.GetName()
resp.PolicyResponse.Resource.Namespace = resource.GetNamespace()
resp.PolicyResponse.Resource.Kind = resource.GetKind()
resp.PolicyResponse.Resource.APIVersion = resource.GetAPIVersion()
// TODO: replace with mutationFailureAction ?
resp.PolicyResponse.ValidationFailureAction = policy.Spec.ValidationFailureAction
}
func endMutateResultResponse(resp *response.EngineResponse, startTime time.Time) {
resp.PolicyResponse.ProcessingTime = time.Since(startTime)
glog.V(4).Infof("finished applying mutation rules policy %v (%v)", resp.PolicyResponse.Policy, resp.PolicyResponse.ProcessingTime)
glog.V(4).Infof("Mutation Rules appplied count %v for policy %q", resp.PolicyResponse.RulesAppliedCount, resp.PolicyResponse.Policy)
}
// podTemplateRule mutate pod template with annotation // podTemplateRule mutate pod template with annotation
// pod-policies.kyverno.io/autogen-applied=true // pod-policies.kyverno.io/autogen-applied=true
var podTemplateRule = kyverno.Rule{ var podTemplateRule = kyverno.Rule{

View file

@ -74,7 +74,6 @@ func startResultResponse(resp *response.EngineResponse, policy kyverno.ClusterPo
resp.PolicyResponse.Resource.Kind = newR.GetKind() resp.PolicyResponse.Resource.Kind = newR.GetKind()
resp.PolicyResponse.Resource.APIVersion = newR.GetAPIVersion() resp.PolicyResponse.Resource.APIVersion = newR.GetAPIVersion()
resp.PolicyResponse.ValidationFailureAction = policy.Spec.ValidationFailureAction resp.PolicyResponse.ValidationFailureAction = policy.Spec.ValidationFailureAction
} }
func endResultResponse(resp *response.EngineResponse, startTime time.Time) { func endResultResponse(resp *response.EngineResponse, startTime time.Time) {

View file

@ -36,6 +36,26 @@ func toBlockResource(engineReponses []response.EngineResponse) bool {
return false return false
} }
// getEnforceFailureErrorMsg gets the error messages for failed enforce policy
func getEnforceFailureErrorMsg(engineReponses []response.EngineResponse) string {
var str []string
var resourceInfo string
for _, er := range engineReponses {
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)
str = append(str, fmt.Sprintf("failed policy %s:", er.PolicyResponse.Policy))
for _, rule := range er.PolicyResponse.Rules {
if !rule.Success {
str = append(str, rule.ToString())
}
}
}
}
return fmt.Sprintf("Resource %s %s", resourceInfo, strings.Join(str, ";"))
}
// getErrorMsg gets all failed engine response message
func getErrorMsg(engineReponses []response.EngineResponse) string { func getErrorMsg(engineReponses []response.EngineResponse) string {
var str []string var str []string
var resourceInfo string var resourceInfo string

View file

@ -1,6 +1,8 @@
package webhooks package webhooks
import ( import (
"time"
"github.com/golang/glog" "github.com/golang/glog"
kyverno "github.com/nirmata/kyverno/pkg/api/kyverno/v1" kyverno "github.com/nirmata/kyverno/pkg/api/kyverno/v1"
"github.com/nirmata/kyverno/pkg/engine" "github.com/nirmata/kyverno/pkg/engine"
@ -15,8 +17,8 @@ import (
) )
// HandleMutation handles mutating webhook admission request // HandleMutation handles mutating webhook admission request
// return generated patches // return value: blocked, generated patches, error message
func (ws *WebhookServer) HandleMutation(request *v1beta1.AdmissionRequest, resource unstructured.Unstructured, policies []kyverno.ClusterPolicy, roles, clusterRoles []string) []byte { func (ws *WebhookServer) HandleMutation(request *v1beta1.AdmissionRequest, resource unstructured.Unstructured, policies []kyverno.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", 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) request.Kind.Kind, request.Namespace, request.Name, request.UID, request.Operation)
@ -80,7 +82,6 @@ func (ws *WebhookServer) HandleMutation(request *v1beta1.AdmissionRequest, resou
resource.GetKind(), resource.GetNamespace(), resource.GetName(), request.UID, request.Operation) resource.GetKind(), resource.GetNamespace(), resource.GetName(), request.UID, request.Operation)
policyContext.Policy = policy policyContext.Policy = policy
// TODO: this can be
engineResponse := engine.Mutate(policyContext) engineResponse := engine.Mutate(policyContext)
engineResponses = append(engineResponses, engineResponse) engineResponses = append(engineResponses, engineResponse)
// Gather policy application statistics // Gather policy application statistics
@ -101,7 +102,19 @@ func (ws *WebhookServer) HandleMutation(request *v1beta1.AdmissionRequest, resou
patches = append(patches, annPatches) patches = append(patches, annPatches)
} }
// generate violation when referenced path does not exist // report time
reportTime := time.Now()
// ENFORCE - block resource creation
blocked := toBlockResource(engineResponses)
if blocked {
glog.V(4).Infof("resource %s/%s/%s is blocked\n", resource.GetKind(), resource.GetNamespace(), resource.GetName())
sendStat(blocked)
return true, nil, getEnforceFailureErrorMsg(engineResponses)
}
// AUDIT
// generate violation when response fails
pvInfos := policyviolation.GeneratePVsFromEngineResponse(engineResponses) pvInfos := policyviolation.GeneratePVsFromEngineResponse(engineResponses)
ws.pvGenerator.Add(pvInfos...) ws.pvGenerator.Add(pvInfos...)
@ -109,20 +122,24 @@ func (ws *WebhookServer) HandleMutation(request *v1beta1.AdmissionRequest, resou
events := generateEvents(engineResponses, (request.Operation == v1beta1.Update)) events := generateEvents(engineResponses, (request.Operation == v1beta1.Update))
ws.eventGen.Add(events...) ws.eventGen.Add(events...)
sendStat(false) sendStat(blocked)
// debug info // debug info
if len(patches) != 0 { func() {
glog.V(3).Infof("Patches generated for %s/%s/%s, operation=%v:\n %v", if len(patches) != 0 {
resource.GetKind(), resource.GetNamespace(), resource.GetName(), request.Operation, string(engineutils.JoinPatches(patches))) glog.V(3).Infof("Patches generated for %s/%s/%s, operation=%v:\n %v",
} resource.GetKind(), resource.GetNamespace(), resource.GetName(), request.Operation, string(engineutils.JoinPatches(patches)))
}
// if any of the policies fails, print out the error // if any of the policies fails, print out the error
if !isResponseSuccesful(engineResponses) { if !isResponseSuccesful(engineResponses) {
glog.Errorf("Failed to mutate the resource, report as violation: %s\n", getErrorMsg(engineResponses)) glog.Errorf("Failed to mutate the resource, report as violation: %s\n", getErrorMsg(engineResponses))
} }
}()
// patches holds all the successful patches // report time end
// if no patch is created, it returns nil glog.V(4).Infof("report: %v %s/%s/%s", time.Since(reportTime), resource.GetKind(), resource.GetNamespace(), resource.GetName())
return engineutils.JoinPatches(patches)
// patches holds all the successful patches, if no patch is created, it returns nil
return false, engineutils.JoinPatches(patches), ""
} }

View file

@ -237,7 +237,17 @@ func (ws *WebhookServer) handleAdmissionRequest(request *v1beta1.AdmissionReques
// MUTATION // MUTATION
// mutation failure should not block the resource creation // mutation failure should not block the resource creation
// any mutation failure is reported as the violation // any mutation failure is reported as the violation
patches := ws.HandleMutation(request, resource, policies, roles, clusterRoles) blocked, patches, errMsg := ws.HandleMutation(request, resource, policies, roles, clusterRoles)
if blocked {
glog.V(4).Infof("Deny admission request: %v/%s/%s", request.Kind, request.Namespace, request.Name)
return &v1beta1.AdmissionResponse{
Allowed: false,
Result: &metav1.Status{
Status: "Failure",
Message: errMsg,
},
}
}
// patch the resource with patches before handling validation rules // patch the resource with patches before handling validation rules
patchedResource := processResourceWithPatches(patches, request.Object.Raw) patchedResource := processResourceWithPatches(patches, request.Object.Raw)

View file

@ -107,7 +107,7 @@ func (ws *WebhookServer) HandleValidation(request *v1beta1.AdmissionRequest, pol
if blocked { if blocked {
glog.V(4).Infof("resource %s/%s/%s is blocked\n", newR.GetKind(), newR.GetNamespace(), newR.GetName()) glog.V(4).Infof("resource %s/%s/%s is blocked\n", newR.GetKind(), newR.GetNamespace(), newR.GetName())
sendStat(true) sendStat(true)
return false, getErrorMsg(engineResponses) return false, getEnforceFailureErrorMsg(engineResponses)
} }
// ADD POLICY VIOLATIONS // ADD POLICY VIOLATIONS