2020-07-10 18:12:19 +05:30
|
|
|
package common
|
|
|
|
|
2021-02-04 02:39:42 +05:30
|
|
|
import (
|
|
|
|
"encoding/json"
|
2021-03-05 06:15:52 +05:30
|
|
|
"strings"
|
2021-06-08 12:37:19 -07:00
|
|
|
"time"
|
2021-02-04 02:39:42 +05:30
|
|
|
|
|
|
|
"github.com/go-logr/logr"
|
2022-05-17 13:12:43 +02:00
|
|
|
kyvernov1 "github.com/kyverno/kyverno/api/kyverno/v1"
|
2022-09-07 06:01:43 +02:00
|
|
|
"github.com/kyverno/kyverno/pkg/client/clientset/versioned"
|
2022-05-18 06:02:31 +02:00
|
|
|
kyvernov1beta1listers "github.com/kyverno/kyverno/pkg/client/listers/kyverno/v1beta1"
|
2022-08-31 14:03:47 +08:00
|
|
|
"github.com/kyverno/kyverno/pkg/clients/dclient"
|
2021-02-04 02:39:42 +05:30
|
|
|
enginutils "github.com/kyverno/kyverno/pkg/engine/utils"
|
2021-06-08 12:37:19 -07:00
|
|
|
"github.com/pkg/errors"
|
2022-05-17 16:14:31 +02:00
|
|
|
corev1 "k8s.io/api/core/v1"
|
2022-05-05 18:56:27 +08:00
|
|
|
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
2022-05-17 17:51:03 +02:00
|
|
|
corev1listers "k8s.io/client-go/listers/core/v1"
|
2021-02-04 02:39:42 +05:30
|
|
|
"sigs.k8s.io/controller-runtime/pkg/log"
|
|
|
|
)
|
|
|
|
|
2020-11-09 11:26:12 -08:00
|
|
|
// Policy Reporting Types
|
|
|
|
const (
|
|
|
|
PolicyViolation = "POLICYVIOLATION"
|
|
|
|
PolicyReport = "POLICYREPORT"
|
|
|
|
)
|
2021-02-04 02:39:42 +05:30
|
|
|
|
|
|
|
// GetNamespaceSelectorsFromNamespaceLister - extract the namespacelabels when namespace lister is passed
|
2022-05-17 17:51:03 +02:00
|
|
|
func GetNamespaceSelectorsFromNamespaceLister(kind, namespaceOfResource string, nsLister corev1listers.NamespaceLister, logger logr.Logger) map[string]string {
|
2021-02-04 02:39:42 +05:30
|
|
|
namespaceLabels := make(map[string]string)
|
2021-11-17 15:09:00 +01:00
|
|
|
if kind != "Namespace" && namespaceOfResource != "" {
|
2021-02-04 02:39:42 +05:30
|
|
|
namespaceObj, err := nsLister.Get(namespaceOfResource)
|
|
|
|
if err != nil {
|
|
|
|
log.Log.Error(err, "failed to get the namespace", "name", namespaceOfResource)
|
2021-02-16 00:57:09 +05:30
|
|
|
return namespaceLabels
|
2021-02-04 02:39:42 +05:30
|
|
|
}
|
|
|
|
return GetNamespaceLabels(namespaceObj, logger)
|
|
|
|
}
|
|
|
|
return namespaceLabels
|
|
|
|
}
|
|
|
|
|
|
|
|
// GetNamespaceLabels - from namespace obj
|
2022-05-17 16:14:31 +02:00
|
|
|
func GetNamespaceLabels(namespaceObj *corev1.Namespace, logger logr.Logger) map[string]string {
|
2021-02-04 02:39:42 +05:30
|
|
|
namespaceObj.Kind = "Namespace"
|
|
|
|
namespaceRaw, err := json.Marshal(namespaceObj)
|
2021-10-13 22:45:23 +02:00
|
|
|
if err != nil {
|
|
|
|
logger.Error(err, "failed to marshal namespace")
|
|
|
|
}
|
2021-02-04 02:39:42 +05:30
|
|
|
namespaceUnstructured, err := enginutils.ConvertToUnstructured(namespaceRaw)
|
|
|
|
if err != nil {
|
|
|
|
logger.Error(err, "failed to convert object resource to unstructured format")
|
|
|
|
}
|
|
|
|
return namespaceUnstructured.GetLabels()
|
|
|
|
}
|
2021-03-05 06:15:52 +05:30
|
|
|
|
2021-10-29 16:06:03 +01:00
|
|
|
// RetryFunc allows retrying a function on error within a given timeout
|
2022-04-25 20:20:40 +08:00
|
|
|
func RetryFunc(retryInterval, timeout time.Duration, run func() error, msg string, logger logr.Logger) func() error {
|
2021-06-08 12:37:19 -07:00
|
|
|
return func() error {
|
|
|
|
registerTimeout := time.After(timeout)
|
|
|
|
registerTicker := time.NewTicker(retryInterval)
|
|
|
|
defer registerTicker.Stop()
|
|
|
|
var err error
|
|
|
|
|
|
|
|
loop:
|
|
|
|
for {
|
|
|
|
select {
|
|
|
|
case <-registerTicker.C:
|
|
|
|
err = run()
|
|
|
|
if err != nil {
|
2022-04-25 20:20:40 +08:00
|
|
|
logger.V(3).Info(msg, "reason", err.Error())
|
2021-06-08 12:37:19 -07:00
|
|
|
} else {
|
|
|
|
break loop
|
|
|
|
}
|
|
|
|
|
|
|
|
case <-registerTimeout:
|
2022-04-25 20:20:40 +08:00
|
|
|
return errors.Wrap(err, "retry times out")
|
2021-06-08 12:37:19 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
}
|
2021-07-01 00:30:02 +05:30
|
|
|
|
2022-09-07 06:01:43 +02:00
|
|
|
func ProcessDeletePolicyForCloneGenerateRule(policy kyvernov1.PolicyInterface, client dclient.Interface, kyvernoClient versioned.Interface, urlister kyvernov1beta1listers.UpdateRequestNamespaceLister, pName string, logger logr.Logger) bool {
|
2021-07-01 00:30:02 +05:30
|
|
|
generatePolicyWithClone := false
|
2022-05-05 18:56:27 +08:00
|
|
|
for _, rule := range policy.GetSpec().Rules {
|
|
|
|
clone, sync := rule.GetCloneSyncForGenerate()
|
|
|
|
if !(clone && sync) {
|
2021-07-09 18:01:46 -07:00
|
|
|
continue
|
|
|
|
}
|
2021-07-01 00:30:02 +05:30
|
|
|
|
2021-07-09 18:01:46 -07:00
|
|
|
logger.V(4).Info("generate policy with clone, remove policy name from label of source resource")
|
|
|
|
generatePolicyWithClone = true
|
2021-07-01 00:30:02 +05:30
|
|
|
|
2022-05-12 13:03:26 +02:00
|
|
|
var retryCount int
|
2021-07-09 18:01:46 -07:00
|
|
|
for retryCount < 5 {
|
2022-05-05 18:56:27 +08:00
|
|
|
err := updateSourceResource(policy.GetName(), rule, client, logger)
|
2021-07-09 18:01:46 -07:00
|
|
|
if err != nil {
|
|
|
|
logger.Error(err, "failed to update generate source resource labels")
|
|
|
|
if apierrors.IsConflict(err) {
|
|
|
|
retryCount++
|
|
|
|
} else {
|
|
|
|
break
|
2021-07-01 00:30:02 +05:30
|
|
|
}
|
|
|
|
}
|
2022-04-27 03:18:24 +08:00
|
|
|
break
|
2021-07-01 00:30:02 +05:30
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return generatePolicyWithClone
|
|
|
|
}
|
2021-07-09 18:01:46 -07:00
|
|
|
|
2022-05-17 13:12:43 +02:00
|
|
|
func updateSourceResource(pName string, rule kyvernov1.Rule, client dclient.Interface, log logr.Logger) error {
|
2021-07-09 18:01:46 -07:00
|
|
|
obj, err := client.GetResource("", rule.Generation.Kind, rule.Generation.Clone.Namespace, rule.Generation.Clone.Name)
|
|
|
|
if err != nil {
|
|
|
|
return errors.Wrapf(err, "source resource %s/%s/%s not found", rule.Generation.Kind, rule.Generation.Clone.Namespace, rule.Generation.Clone.Name)
|
|
|
|
}
|
|
|
|
|
2022-05-12 13:03:26 +02:00
|
|
|
var update bool
|
2021-07-09 18:01:46 -07:00
|
|
|
labels := obj.GetLabels()
|
|
|
|
update, labels = removePolicyFromLabels(pName, labels)
|
2022-04-27 03:18:24 +08:00
|
|
|
if !update {
|
2021-07-09 18:01:46 -07:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
obj.SetLabels(labels)
|
|
|
|
_, err = client.UpdateResource(obj.GetAPIVersion(), rule.Generation.Kind, rule.Generation.Clone.Namespace, obj, false)
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
func removePolicyFromLabels(pName string, labels map[string]string) (bool, map[string]string) {
|
|
|
|
if len(labels) == 0 {
|
|
|
|
return false, labels
|
|
|
|
}
|
|
|
|
|
|
|
|
if labels["generate.kyverno.io/clone-policy-name"] != "" {
|
|
|
|
policyNames := labels["generate.kyverno.io/clone-policy-name"]
|
|
|
|
if strings.Contains(policyNames, pName) {
|
2022-04-27 03:18:24 +08:00
|
|
|
desiredLabels := make(map[string]string, len(labels)-1)
|
|
|
|
for k, v := range labels {
|
|
|
|
if k != "generate.kyverno.io/clone-policy-name" {
|
|
|
|
desiredLabels[k] = v
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return true, desiredLabels
|
2021-07-09 18:01:46 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return false, labels
|
|
|
|
}
|