diff --git a/definitions/install.yaml b/definitions/install.yaml index 4aad2b9e8d..70a6ca248e 100644 --- a/definitions/install.yaml +++ b/definitions/install.yaml @@ -230,7 +230,7 @@ spec: type: string message: type: string - dependant: + managedResource: type: object required: - kind diff --git a/pkg/api/kyverno/v1alpha1/types.go b/pkg/api/kyverno/v1alpha1/types.go index 9ab2c43526..7766612876 100644 --- a/pkg/api/kyverno/v1alpha1/types.go +++ b/pkg/api/kyverno/v1alpha1/types.go @@ -173,13 +173,13 @@ type ResourceSpec struct { // ViolatedRule stores the information regarding the rule type ViolatedRule struct { - Name string `json:"name"` - Type string `json:"type"` - Message string `json:"message"` - Dependant `json:"dependant,omitempty"` + Name string `json:"name"` + Type string `json:"type"` + Message string `json:"message"` + ManagedResource ManagedResource `json:"managedResource,omitempty"` } -type Dependant struct { +type ManagedResource struct { Kind string `json:"kind,omitempty"` Namespace string `json:"namespace,omitempty"` CreationBlocked bool `json:"creationBlocked,omitempty"` diff --git a/pkg/api/kyverno/v1alpha1/zz_generated.deepcopy.go b/pkg/api/kyverno/v1alpha1/zz_generated.deepcopy.go index c97d4b6ae4..ba06870ad8 100644 --- a/pkg/api/kyverno/v1alpha1/zz_generated.deepcopy.go +++ b/pkg/api/kyverno/v1alpha1/zz_generated.deepcopy.go @@ -163,22 +163,6 @@ func (in *ClusterPolicyViolationList) DeepCopyObject() runtime.Object { return nil } -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *Dependant) DeepCopyInto(out *Dependant) { - *out = *in - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Dependant. -func (in *Dependant) DeepCopy() *Dependant { - if in == nil { - return nil - } - out := new(Dependant) - in.DeepCopyInto(out) - return out -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ExcludeResources) DeepCopyInto(out *ExcludeResources) { *out = *in @@ -206,6 +190,22 @@ func (in *Generation) DeepCopy() *Generation { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ManagedResource) DeepCopyInto(out *ManagedResource) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ManagedResource. +func (in *ManagedResource) DeepCopy() *ManagedResource { + if in == nil { + return nil + } + out := new(ManagedResource) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *MatchResources) DeepCopyInto(out *MatchResources) { *out = *in @@ -453,7 +453,7 @@ func (in *Validation) DeepCopy() *Validation { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ViolatedRule) DeepCopyInto(out *ViolatedRule) { *out = *in - out.Dependant = in.Dependant + out.ManagedResource = in.ManagedResource return } diff --git a/pkg/namespace/report.go b/pkg/namespace/report.go index 8a7969c204..4a1a6e4000 100644 --- a/pkg/namespace/report.go +++ b/pkg/namespace/report.go @@ -21,7 +21,7 @@ func (nsc *NamespaceController) report(engineResponses []engine.EngineResponse) // failure - policy/rule failed to apply on the resource } // generate policy violation - policyviolation.CreatePV(nsc.pvLister, nsc.kyvernoClient, nil, engineResponses, false) + policyviolation.CreatePV(nsc.pvLister, nsc.kyvernoClient, engineResponses) } //reportEvents generates events for the failed resources diff --git a/pkg/policy/report.go b/pkg/policy/report.go index c28f270039..d126b225e2 100644 --- a/pkg/policy/report.go +++ b/pkg/policy/report.go @@ -22,7 +22,7 @@ func (pc *PolicyController) report(engineResponses []engine.EngineResponse) { } // generate policy violation - policyviolation.CreatePV(pc.pvLister, pc.kyvernoClient, nil, engineResponses, false) + policyviolation.CreatePV(pc.pvLister, pc.kyvernoClient, engineResponses) } //reportEvents generates events for the failed resources diff --git a/pkg/policyviolation/controller.go b/pkg/policyviolation/controller.go index 3a80967d20..0175b64dd3 100644 --- a/pkg/policyviolation/controller.go +++ b/pkg/policyviolation/controller.go @@ -221,24 +221,50 @@ func (pvc *PolicyViolationController) syncPolicyViolation(key string) error { return err } - if err := pvc.syncBlockedResource(pv); err != nil { - glog.V(4).Infof("not syncing policy violation status") + return pvc.syncStatusOnly(pv) +} + +func (pvc *PolicyViolationController) syncActiveResource(curPv *kyverno.ClusterPolicyViolation) error { + // check if the resource is active or not ? + rspec := curPv.Spec.ResourceSpec + // get resource + _, err := pvc.client.GetResource(rspec.Kind, rspec.Namespace, rspec.Name) + if errors.IsNotFound(err) { + // TODO: does it help to retry? + // resource is not found + // remove the violation + + if err := pvc.pvControl.RemovePolicyViolation(curPv.Name); err != nil { + glog.Infof("unable to delete the policy violation %s: %v", curPv.Name, err) + return err + } + glog.V(4).Infof("removing policy violation %s as the corresponding resource %s/%s/%s does not exist anymore", curPv.Name, rspec.Kind, rspec.Namespace, rspec.Name) + return nil + } + if err != nil { + glog.V(4).Infof("error while retrieved resource %s/%s/%s: %v", rspec.Kind, rspec.Namespace, rspec.Name, err) return err } - return pvc.syncStatusOnly(pv) + // cleanup pv with dependant + if err := pvc.syncBlockedResource(curPv); err != nil { + return err + } + + //TODO- if the policy is not present, remove the policy violation + return nil } // syncBlockedResource remove inactive policy violation // when rejected resource created in the cluster func (pvc *PolicyViolationController) syncBlockedResource(curPv *kyverno.ClusterPolicyViolation) error { for _, violatedRule := range curPv.Spec.ViolatedRules { - if reflect.DeepEqual(violatedRule.Dependant, kyverno.Dependant{}) { + if reflect.DeepEqual(violatedRule.ManagedResource, kyverno.ManagedResource{}) { continue } // get resource - blockedResource := violatedRule.Dependant + blockedResource := violatedRule.ManagedResource resources, _ := pvc.client.ListResource(blockedResource.Kind, blockedResource.Namespace, nil) for _, resource := range resources.Items { @@ -268,31 +294,6 @@ func (pvc *PolicyViolationController) syncBlockedResource(curPv *kyverno.Cluster return nil } -func (pvc *PolicyViolationController) syncActiveResource(curPv *kyverno.ClusterPolicyViolation) error { - // check if the resource is active or not ? - rspec := curPv.Spec.ResourceSpec - // get resource - _, err := pvc.client.GetResource(rspec.Kind, rspec.Namespace, rspec.Name) - if errors.IsNotFound(err) { - // TODO: does it help to retry? - // resource is not found - // remove the violation - - if err := pvc.pvControl.RemovePolicyViolation(curPv.Name); err != nil { - glog.Infof("unable to delete the policy violation %s: %v", curPv.Name, err) - return err - } - glog.V(4).Infof("removing policy violation %s as the corresponding resource %s/%s/%s does not exist anymore", curPv.Name, rspec.Kind, rspec.Namespace, rspec.Name) - return nil - } - if err != nil { - glog.V(4).Infof("error while retrieved resource %s/%s/%s: %v", rspec.Kind, rspec.Namespace, rspec.Name, err) - return err - } - //TODO- if the policy is not present, remove the policy violation - return nil -} - //syncStatusOnly updates the policyviolation status subresource // status: func (pvc *PolicyViolationController) syncStatusOnly(curPv *kyverno.ClusterPolicyViolation) error { diff --git a/pkg/policyviolation/helpers.go b/pkg/policyviolation/helpers.go index bd1c4a8384..c41a737cac 100644 --- a/pkg/policyviolation/helpers.go +++ b/pkg/policyviolation/helpers.go @@ -36,23 +36,9 @@ func BuildPolicyViolation(policy string, resource kyverno.ResourceSpec, fRules [ } //CreatePV creates policy violation resource based on the engine responses -func CreatePV(pvLister kyvernolister.ClusterPolicyViolationLister, client *kyvernoclient.Clientset, - dclient *dclient.Client, engineResponses []engine.EngineResponse, requestBlocked bool) { +func CreatePV(pvLister kyvernolister.ClusterPolicyViolationLister, client *kyvernoclient.Clientset, engineResponses []engine.EngineResponse) { var pvs []kyverno.ClusterPolicyViolation for _, er := range engineResponses { - // create pv on resource owner only when admission request is denied - // check before validate "er.PolicyResponse.Resource.Name" since - // child resource is not created in this case thus it won't have a name - if requestBlocked { - glog.V(4).Infof("Building policy violation for denied admission request, engineResponse: %v", er) - if pvList := buildPVWithOwner(dclient, er); len(pvList) != 0 { - pvs = append(pvs, pvList...) - glog.V(3).Infof("Built policy violation for denied admission request %s/%s/%s", - er.PatchedResource.GetKind(), er.PatchedResource.GetNamespace(), er.PatchedResource.GetName()) - } - continue - } - // ignore creation of PV for resoruces that are yet to be assigned a name if er.PolicyResponse.Resource.Name == "" { glog.V(4).Infof("resource %v, has not been assigned a name, not creating a policy violation for it", er.PolicyResponse.Resource) @@ -67,6 +53,26 @@ func CreatePV(pvLister kyvernolister.ClusterPolicyViolationLister, client *kyver } } + createPV(pvLister, client, pvs) +} + +// CreatePVWhenBlocked creates pv on resource owner only when admission request is denied +func CreatePVWhenBlocked(pvLister kyvernolister.ClusterPolicyViolationLister, client *kyvernoclient.Clientset, + dclient *dclient.Client, engineResponses []engine.EngineResponse) { + var pvs []kyverno.ClusterPolicyViolation + for _, er := range engineResponses { + // child resource is not created in this case thus it won't have a name + glog.V(4).Infof("Building policy violation for denied admission request, engineResponse: %v", er) + if pvList := buildPVWithOwner(dclient, er); len(pvList) != 0 { + pvs = append(pvs, pvList...) + glog.V(3).Infof("Built policy violation for denied admission request %s/%s/%s", + er.PatchedResource.GetKind(), er.PatchedResource.GetNamespace(), er.PatchedResource.GetName()) + } + } + createPV(pvLister, client, pvs) +} + +func createPV(pvLister kyvernolister.ClusterPolicyViolationLister, client *kyvernoclient.Clientset, pvs []kyverno.ClusterPolicyViolation) { if len(pvs) == 0 { return } @@ -242,7 +248,7 @@ func getOwners(dclient *dclient.Client, unstr unstructured.Unstructured) []pvRes func newViolatedRules(er engine.EngineResponse, msg string) (violatedRules []kyverno.ViolatedRule) { unstr := er.PatchedResource - dependant := kyverno.Dependant{ + dependant := kyverno.ManagedResource{ Kind: unstr.GetKind(), Namespace: unstr.GetNamespace(), CreationBlocked: true, @@ -259,7 +265,7 @@ func newViolatedRules(er engine.EngineResponse, msg string) (violatedRules []kyv // resource creation blocked // set resource itself as dependant if strings.Contains(msg, "Request Blocked") { - vrule.Dependant = dependant + vrule.ManagedResource = dependant } violatedRules = append(violatedRules, vrule) diff --git a/pkg/webhooks/validation.go b/pkg/webhooks/validation.go index f613198ab1..7623f647ec 100644 --- a/pkg/webhooks/validation.go +++ b/pkg/webhooks/validation.go @@ -110,14 +110,14 @@ func (ws *WebhookServer) HandleValidation(request *v1beta1.AdmissionRequest, pat // and if there are any then we dont block the resource creation // Even if one the policy being applied if !isResponseSuccesful(engineResponses) && toBlockResource(engineResponses) { - policyviolation.CreatePV(ws.pvLister, ws.kyvernoClient, ws.client, engineResponses, true) + policyviolation.CreatePVWhenBlocked(ws.pvLister, ws.kyvernoClient, ws.client, engineResponses) sendStat(true) return false, getErrorMsg(engineResponses) } // ADD POLICY VIOLATIONS // violations are created with resource on "audit" - policyviolation.CreatePV(ws.pvLister, ws.kyvernoClient, ws.client, engineResponses, false) + policyviolation.CreatePV(ws.pvLister, ws.kyvernoClient, engineResponses) sendStat(false) return true, "" }