mirror of
https://github.com/kyverno/kyverno.git
synced 2024-12-14 11:57:48 +00:00
- fix violations re-create on the same resource - skip background processing if a resource is to be deleted
This commit is contained in:
parent
838d02c475
commit
7ea2930fa4
5 changed files with 72 additions and 14 deletions
|
@ -32,7 +32,7 @@ func applyPolicy(policy kyverno.ClusterPolicy, resource unstructured.Unstructure
|
||||||
}()
|
}()
|
||||||
|
|
||||||
var engineResponses []response.EngineResponse
|
var engineResponses []response.EngineResponse
|
||||||
var engineResponse response.EngineResponse
|
var engineResponseMutation, engineResponseValidation response.EngineResponse
|
||||||
var err error
|
var err error
|
||||||
// build context
|
// build context
|
||||||
ctx := context.NewContext()
|
ctx := context.NewContext()
|
||||||
|
@ -41,15 +41,14 @@ func applyPolicy(policy kyverno.ClusterPolicy, resource unstructured.Unstructure
|
||||||
logger.Error(err, "enable to add transform resource to ctx")
|
logger.Error(err, "enable to add transform resource to ctx")
|
||||||
}
|
}
|
||||||
//MUTATION
|
//MUTATION
|
||||||
engineResponse, err = mutation(policy, resource, ctx, logger)
|
engineResponseMutation, err = mutation(policy, resource, ctx, logger)
|
||||||
engineResponses = append(engineResponses, engineResponse)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Error(err, "failed to process mutation rule")
|
logger.Error(err, "failed to process mutation rule")
|
||||||
}
|
}
|
||||||
|
|
||||||
//VALIDATION
|
//VALIDATION
|
||||||
engineResponse = engine.Validate(engine.PolicyContext{Policy: policy, Context: ctx, NewResource: resource})
|
engineResponseValidation = engine.Validate(engine.PolicyContext{Policy: policy, Context: ctx, NewResource: resource})
|
||||||
engineResponses = append(engineResponses, engineResponse)
|
engineResponses = append(engineResponses, mergeRuleRespose(engineResponseMutation, engineResponseValidation))
|
||||||
|
|
||||||
//TODO: GENERATION
|
//TODO: GENERATION
|
||||||
return engineResponses
|
return engineResponses
|
||||||
|
@ -81,27 +80,31 @@ func getFailedOverallRuleInfo(resource unstructured.Unstructured, engineResponse
|
||||||
// resource does not match so there was a mutation rule violated
|
// resource does not match so there was a mutation rule violated
|
||||||
for index, rule := range engineResponse.PolicyResponse.Rules {
|
for index, rule := range engineResponse.PolicyResponse.Rules {
|
||||||
log.V(4).Info("veriying if policy rule was applied before", "rule", rule.Name)
|
log.V(4).Info("veriying if policy rule was applied before", "rule", rule.Name)
|
||||||
if len(rule.Patches) == 0 {
|
|
||||||
|
patches := dropKyvernoAnnotation(rule.Patches, log)
|
||||||
|
if len(patches) == 0 {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
patch, err := jsonpatch.DecodePatch(utils.JoinPatches(rule.Patches))
|
|
||||||
|
patch, err := jsonpatch.DecodePatch(utils.JoinPatches(patches))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error(err, "failed to decode JSON patch", "patches", rule.Patches)
|
log.Error(err, "failed to decode JSON patch", "patches", patches)
|
||||||
return response.EngineResponse{}, err
|
return response.EngineResponse{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// apply the patches returned by mutate to the original resource
|
// apply the patches returned by mutate to the original resource
|
||||||
patchedResource, err := patch.Apply(rawResource)
|
patchedResource, err := patch.Apply(rawResource)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error(err, "failed to apply JSON patch", "patches", rule.Patches)
|
log.Error(err, "failed to apply JSON patch", "patches", patches)
|
||||||
return response.EngineResponse{}, err
|
return response.EngineResponse{}, err
|
||||||
}
|
}
|
||||||
if !jsonpatch.Equal(patchedResource, rawResource) {
|
if !jsonpatch.Equal(patchedResource, rawResource) {
|
||||||
log.V(4).Info("policy rule conditions not satisfied by resource", "rule", rule.Name)
|
log.V(4).Info("policy rule conditions not satisfied by resource", "rule", rule.Name)
|
||||||
engineResponse.PolicyResponse.Rules[index].Success = false
|
engineResponse.PolicyResponse.Rules[index].Success = false
|
||||||
engineResponse.PolicyResponse.Rules[index].Message = fmt.Sprintf("mutation json patches not found at resource path %s", extractPatchPath(rule.Patches, log))
|
engineResponse.PolicyResponse.Rules[index].Message = fmt.Sprintf("mutation json patches not found at resource path %s", extractPatchPath(patches, log))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return engineResponse, nil
|
return engineResponse, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -125,3 +128,26 @@ func extractPatchPath(patches [][]byte, log logr.Logger) string {
|
||||||
}
|
}
|
||||||
return strings.Join(resultPath, ";")
|
return strings.Join(resultPath, ";")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func dropKyvernoAnnotation(patches [][]byte, log logr.Logger) (resultPathes [][]byte) {
|
||||||
|
for _, patch := range patches {
|
||||||
|
var data jsonPatch
|
||||||
|
if err := json.Unmarshal(patch, &data); err != nil {
|
||||||
|
log.Error(err, "failed to decode the generate patch", "patch", string(patch))
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
value := fmt.Sprintf("%v", data.Value)
|
||||||
|
if strings.Contains(value, engine.PodTemplateAnnotation) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
resultPathes = append(resultPathes, patch)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func mergeRuleRespose(mutation, validation response.EngineResponse) response.EngineResponse {
|
||||||
|
mutation.PolicyResponse.Rules = append(mutation.PolicyResponse.Rules, validation.PolicyResponse.Rules...)
|
||||||
|
return mutation
|
||||||
|
}
|
||||||
|
|
|
@ -167,6 +167,10 @@ func getResourcesPerNamespace(kind string, client *client.Client, namespace stri
|
||||||
}
|
}
|
||||||
// filter based on name
|
// filter based on name
|
||||||
for _, r := range list.Items {
|
for _, r := range list.Items {
|
||||||
|
if r.GetDeletionTimestamp() != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
// match name
|
// match name
|
||||||
if rule.MatchResources.Name != "" {
|
if rule.MatchResources.Name != "" {
|
||||||
if !wildcard.Match(rule.MatchResources.Name, r.GetName()) {
|
if !wildcard.Match(rule.MatchResources.Name, r.GetName()) {
|
||||||
|
|
|
@ -93,8 +93,17 @@ func (cpv *clusterPV) createPV(newPv *kyverno.ClusterPolicyViolation) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to retry getting resource for policy violation %s/%s: %v", newPv.Name, newPv.Spec.Policy, err)
|
return fmt.Errorf("failed to retry getting resource for policy violation %s/%s: %v", newPv.Name, newPv.Spec.Policy, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if obj.GetDeletionTimestamp() != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// set owner reference to resource
|
// set owner reference to resource
|
||||||
ownerRef := createOwnerReference(obj)
|
ownerRef, ok := createOwnerReference(obj)
|
||||||
|
if !ok {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
newPv.SetOwnerReferences([]metav1.OwnerReference{ownerRef})
|
newPv.SetOwnerReferences([]metav1.OwnerReference{ownerRef})
|
||||||
|
|
||||||
// create resource
|
// create resource
|
||||||
|
|
|
@ -14,9 +14,19 @@ import (
|
||||||
"sigs.k8s.io/controller-runtime/pkg/log"
|
"sigs.k8s.io/controller-runtime/pkg/log"
|
||||||
)
|
)
|
||||||
|
|
||||||
func createOwnerReference(resource *unstructured.Unstructured) metav1.OwnerReference {
|
func createOwnerReference(resource *unstructured.Unstructured) (metav1.OwnerReference, bool) {
|
||||||
controllerFlag := true
|
controllerFlag := true
|
||||||
blockOwnerDeletionFlag := true
|
blockOwnerDeletionFlag := true
|
||||||
|
|
||||||
|
apiversion := resource.GetAPIVersion()
|
||||||
|
kind := resource.GetKind()
|
||||||
|
name := resource.GetName()
|
||||||
|
uid := resource.GetUID()
|
||||||
|
|
||||||
|
if apiversion == "" || kind == "" || name == "" || uid == "" {
|
||||||
|
return metav1.OwnerReference{}, false
|
||||||
|
}
|
||||||
|
|
||||||
ownerRef := metav1.OwnerReference{
|
ownerRef := metav1.OwnerReference{
|
||||||
APIVersion: resource.GetAPIVersion(),
|
APIVersion: resource.GetAPIVersion(),
|
||||||
Kind: resource.GetKind(),
|
Kind: resource.GetKind(),
|
||||||
|
@ -25,7 +35,7 @@ func createOwnerReference(resource *unstructured.Unstructured) metav1.OwnerRefer
|
||||||
Controller: &controllerFlag,
|
Controller: &controllerFlag,
|
||||||
BlockOwnerDeletion: &blockOwnerDeletionFlag,
|
BlockOwnerDeletion: &blockOwnerDeletionFlag,
|
||||||
}
|
}
|
||||||
return ownerRef
|
return ownerRef, true
|
||||||
}
|
}
|
||||||
|
|
||||||
func retryGetResource(client *client.Client, rspec kyverno.ResourceSpec) (*unstructured.Unstructured, error) {
|
func retryGetResource(client *client.Client, rspec kyverno.ResourceSpec) (*unstructured.Unstructured, error) {
|
||||||
|
|
|
@ -92,8 +92,17 @@ func (nspv *namespacedPV) createPV(newPv *kyverno.PolicyViolation) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to retry getting resource for policy violation %s/%s: %v", newPv.Name, newPv.Spec.Policy, err)
|
return fmt.Errorf("failed to retry getting resource for policy violation %s/%s: %v", newPv.Name, newPv.Spec.Policy, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if obj.GetDeletionTimestamp() != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// set owner reference to resource
|
// set owner reference to resource
|
||||||
ownerRef := createOwnerReference(obj)
|
ownerRef, ok := createOwnerReference(obj)
|
||||||
|
if !ok {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
newPv.SetOwnerReferences([]metav1.OwnerReference{ownerRef})
|
newPv.SetOwnerReferences([]metav1.OwnerReference{ownerRef})
|
||||||
|
|
||||||
// create resource
|
// create resource
|
||||||
|
|
Loading…
Reference in a new issue