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:
parent
f47910da53
commit
68a48373ae
4 changed files with 144 additions and 23 deletions
|
@ -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
|
||||
}
|
||||
|
|
40
pkg/webhooks/deleteresource.go
Normal file
40
pkg/webhooks/deleteresource.go
Normal 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
|
||||
}
|
|
@ -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,
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue