1
0
Fork 0
mirror of https://github.com/kyverno/kyverno.git synced 2025-04-08 10:04:25 +00:00

add delete op to webhook & violation removal

This commit is contained in:
shivkumar dudhani 2019-07-15 20:16:06 -07:00
parent f47910da53
commit 68a48373ae
4 changed files with 144 additions and 23 deletions

View file

@ -18,6 +18,7 @@ import (
type Generator interface {
Add(infos ...*Info) error
RemoveInactiveViolation(policy, rKind, rNs, rName string, ruleType info.RuleType) error
ResourceRemoval(policy, rKind, rNs, rName string) error
}
type builder struct {
@ -316,3 +317,50 @@ func (b *builder) RemoveInactiveViolation(policy, rKind, rNs, rName string, rule
}
return nil
}
func (b *builder) ResourceRemoval(policy, rKind, rNs, rName string) error {
// Remove the <resource, Violation> pair from map
statusMap := map[string]interface{}{}
currVs := map[string]interface{}{}
// Get the policy
p, err := b.client.GetResource("Policy", "", policy, "status")
if err != nil {
glog.Infof("policy %s not found", policy)
return err
}
unstr := p.UnstructuredContent()
// check if "status" field exists
status, ok := unstr["status"]
if ok {
// status is already present then we append violations
if statusMap, ok = status.(map[string]interface{}); !ok {
return errors.New("Unable to parse status subresource")
}
violations, ok := statusMap["violations"]
if !ok {
glog.Info("violation not present")
}
glog.Info(reflect.TypeOf(violations))
if currVs, ok = violations.(map[string]interface{}); !ok {
return errors.New("Unable to parse violations")
}
_, ok = currVs[BuildKey(rKind, rNs, rName)]
if !ok {
// No Violation for this resource
return nil
}
// remove the pair from the map
delete(currVs, BuildKey(rKind, rNs, rName))
glog.Info("Removed Violation")
// update violations
statusMap["violations"] = currVs
// update status
unstr["status"] = statusMap
p.SetUnstructuredContent(unstr)
_, err = b.client.UpdateStatusResource("Policy", "", p, false)
if err != nil {
return err
}
}
return nil
}

View file

@ -0,0 +1,40 @@
package webhooks
import (
"errors"
engine "github.com/nirmata/kyverno/pkg/engine"
v1beta1 "k8s.io/api/admission/v1beta1"
"k8s.io/apimachinery/pkg/labels"
)
func (ws *WebhookServer) removePolicyViolation(request *v1beta1.AdmissionRequest) error {
// Get the list of policies that apply on the resource
policies, err := ws.policyLister.List(labels.NewSelector())
if err != nil {
// Unable to connect to policy Lister to access policies
return errors.New("Unable to connect to policy controller to access policies. Clean Up of Policy Violations is not being done")
}
for _, policy := range policies {
// check if policy has a rule for the admission request kind
if !StringInSlice(request.Kind.Kind, getApplicableKindsForPolicy(policy)) {
continue
}
rname := engine.ParseNameFromObject(request.Object.Raw)
rns := engine.ParseNamespaceFromObject(request.Object.Raw)
rkind := engine.ParseKindFromObject(request.Object.Raw)
// check if the resource meets the policy Resource description
for _, rule := range policy.Spec.Rules {
ok := engine.ResourceMeetsDescription(request.Object.Raw, rule.ResourceDescription, request.Kind)
if ok {
// Check if the policy has a violation for this resource
err := ws.violationBuilder.ResourceRemoval(policy.Name, rkind, rns, rname)
if err != nil {
return err
}
}
}
}
return nil
}

View file

@ -139,7 +139,8 @@ func (wrc *WebhookRegistrationClient) constructMutatingWebhookConfig(configurati
constructWebhook(
config.MutatingWebhookName,
config.MutatingWebhookServicePath,
caData),
caData,
false),
},
}, nil
}
@ -157,7 +158,8 @@ func (wrc *WebhookRegistrationClient) contructDebugMutatingWebhookConfig(caData
constructDebugWebhook(
config.MutatingWebhookName,
url,
caData),
caData,
false),
},
}
}
@ -190,7 +192,8 @@ func (wrc *WebhookRegistrationClient) constructValidatingWebhookConfig(configura
constructWebhook(
config.ValidatingWebhookName,
config.ValidatingWebhookServicePath,
caData),
caData,
true),
},
}, nil
}
@ -208,7 +211,8 @@ func (wrc *WebhookRegistrationClient) contructDebugValidatingWebhookConfig(caDat
constructDebugWebhook(
config.ValidatingWebhookName,
url,
caData),
caData,
true),
},
}
}
@ -241,7 +245,8 @@ func (wrc *WebhookRegistrationClient) contructPolicyValidatingWebhookConfig() (*
constructWebhook(
config.PolicyValidatingWebhookName,
config.PolicyValidatingWebhookServicePath,
caData),
caData,
true),
},
}, nil
}
@ -259,12 +264,13 @@ func (wrc *WebhookRegistrationClient) contructDebugPolicyValidatingWebhookConfig
constructDebugWebhook(
config.PolicyValidatingWebhookName,
url,
caData),
caData,
true),
},
}
}
func constructWebhook(name, servicePath string, caData []byte) admregapi.Webhook {
func constructWebhook(name, servicePath string, caData []byte, validation bool) admregapi.Webhook {
resource := "*/*"
apiGroups := "*"
apiversions := "*"
@ -273,6 +279,15 @@ func constructWebhook(name, servicePath string, caData []byte) admregapi.Webhook
apiGroups = "kyverno.io"
apiversions = "v1alpha1"
}
operationtypes := []admregapi.OperationType{
admregapi.Create,
admregapi.Update,
}
// Add operation DELETE for validation
if validation {
operationtypes = append(operationtypes, admregapi.Delete)
}
return admregapi.Webhook{
Name: name,
@ -286,10 +301,7 @@ func constructWebhook(name, servicePath string, caData []byte) admregapi.Webhook
},
Rules: []admregapi.RuleWithOperations{
admregapi.RuleWithOperations{
Operations: []admregapi.OperationType{
admregapi.Create,
admregapi.Update,
},
Operations: operationtypes,
Rule: admregapi.Rule{
APIGroups: []string{
apiGroups,
@ -306,7 +318,7 @@ func constructWebhook(name, servicePath string, caData []byte) admregapi.Webhook
}
}
func constructDebugWebhook(name, url string, caData []byte) admregapi.Webhook {
func constructDebugWebhook(name, url string, caData []byte, validation bool) admregapi.Webhook {
resource := "*/*"
apiGroups := "*"
apiversions := "*"
@ -316,6 +328,14 @@ func constructDebugWebhook(name, url string, caData []byte) admregapi.Webhook {
apiGroups = "kyverno.io"
apiversions = "v1alpha1"
}
operationtypes := []admregapi.OperationType{
admregapi.Create,
admregapi.Update,
}
// Add operation DELETE for validation
if validation {
operationtypes = append(operationtypes, admregapi.Delete)
}
return admregapi.Webhook{
Name: name,
@ -325,10 +345,7 @@ func constructDebugWebhook(name, url string, caData []byte) admregapi.Webhook {
},
Rules: []admregapi.RuleWithOperations{
admregapi.RuleWithOperations{
Operations: []admregapi.OperationType{
admregapi.Create,
admregapi.Update,
},
Operations: operationtypes,
Rule: admregapi.Rule{
APIGroups: []string{
apiGroups,

View file

@ -89,14 +89,30 @@ func (ws *WebhookServer) serve(w http.ResponseWriter, r *http.Request) {
// Do not process the admission requests for kinds that are in filterKinds for filtering
if !StringInSlice(admissionReview.Request.Kind.Kind, ws.filterKinds) {
// if the resource is being deleted we need to clear any existing Policy Violations
// TODO: can report to the user that we clear the violation corresponding to this resource
if admissionReview.Request.Operation == v1beta1.Delete {
// Resource DELETE
err := ws.removePolicyViolation(admissionReview.Request)
if err != nil {
glog.Info(err)
}
admissionReview.Response = &v1beta1.AdmissionResponse{
Allowed: true,
}
admissionReview.Response.UID = admissionReview.Request.UID
} else {
// Resource CREATE
// Resource UPDATE
switch r.URL.Path {
case config.MutatingWebhookServicePath:
admissionReview.Response = ws.HandleMutation(admissionReview.Request)
case config.ValidatingWebhookServicePath:
admissionReview.Response = ws.HandleValidation(admissionReview.Request)
case config.PolicyValidatingWebhookServicePath:
admissionReview.Response = ws.HandlePolicyValidation(admissionReview.Request)
}
switch r.URL.Path {
case config.MutatingWebhookServicePath:
admissionReview.Response = ws.HandleMutation(admissionReview.Request)
case config.ValidatingWebhookServicePath:
admissionReview.Response = ws.HandleValidation(admissionReview.Request)
case config.PolicyValidatingWebhookServicePath:
admissionReview.Response = ws.HandlePolicyValidation(admissionReview.Request)
}
}