mirror of
https://github.com/kyverno/kyverno.git
synced 2024-12-14 11:57:48 +00:00
13caaed8b7
* add image verification * inline policy list Signed-off-by: Jim Bugwadia <jim@nirmata.com> * cosign version and dependencies updates Signed-off-by: Jim Bugwadia <jim@nirmata.com> * add registry initialization Signed-off-by: Jim Bugwadia <jim@nirmata.com> * add build tag to exclude k8schain for cloud providers Signed-off-by: Jim Bugwadia <jim@nirmata.com> * add build tag to exclude k8schain for cloud providers Signed-off-by: Jim Bugwadia <jim@nirmata.com> * generate deep copy and other fixtures Signed-off-by: Jim Bugwadia <jim@nirmata.com> * fix deep copy issues Signed-off-by: Jim Bugwadia <jim@nirmata.com> * mutate images to add digest Signed-off-by: Jim Bugwadia <jim@nirmata.com> * add certificates to Kyverno container for HTTPS lookups Signed-off-by: Jim Bugwadia <jim@nirmata.com> * align flag syntax Signed-off-by: Jim Bugwadia <jim@nirmata.com> * update docs Signed-off-by: Jim Bugwadia <jim@nirmata.com> * update dependencies Signed-off-by: Jim Bugwadia <jim@nirmata.com> * update dependencies Signed-off-by: Jim Bugwadia <jim@nirmata.com> * patch image with digest and fix checks Signed-off-by: Jim Bugwadia <jim@nirmata.com> * hardcode image for demos Signed-off-by: Jim Bugwadia <jim@nirmata.com> * add default registry (docker.io) before calling reference.Parse Signed-off-by: Jim Bugwadia <jim@nirmata.com> * fix definition Signed-off-by: Jim Bugwadia <jim@nirmata.com> * increase webhook timeout Signed-off-by: Jim Bugwadia <jim@nirmata.com> * fix args Signed-off-by: Jim Bugwadia <jim@nirmata.com> * run gofmt Signed-off-by: Jim Bugwadia <jim@nirmata.com> * rename for clarity Signed-off-by: Jim Bugwadia <jim@nirmata.com> * fix HasImageVerify check Signed-off-by: Jim Bugwadia <jim@nirmata.com> * align make test commands Signed-off-by: Jim Bugwadia <jim@nirmata.com> * align make test commands Signed-off-by: Jim Bugwadia <jim@nirmata.com> * align make test commands Signed-off-by: Jim Bugwadia <jim@nirmata.com> * fix linter error Signed-off-by: Jim Bugwadia <jim@nirmata.com> * format Signed-off-by: Jim Bugwadia <jim@nirmata.com> * handle API conflict and retry Signed-off-by: Jim Bugwadia <jim@nirmata.com> * format Signed-off-by: Jim Bugwadia <jim@nirmata.com> * fix reviewdog issues Signed-off-by: Jim Bugwadia <jim@nirmata.com> * fix make for unit tests Signed-off-by: Jim Bugwadia <jim@nirmata.com> * improve error message Signed-off-by: Jim Bugwadia <jim@nirmata.com> * fix durations Signed-off-by: Jim Bugwadia <jim@nirmata.com> * handle errors in tests Signed-off-by: Jim Bugwadia <jim@nirmata.com> * print policy name Signed-off-by: Jim Bugwadia <jim@nirmata.com> * update tests Signed-off-by: Jim Bugwadia <jim@nirmata.com> * add retries and duration to error log Signed-off-by: Jim Bugwadia <jim@nirmata.com> * fix time check in tests Signed-off-by: Jim Bugwadia <jim@nirmata.com> * round creation times in test Signed-off-by: Jim Bugwadia <jim@nirmata.com> * fix retry loop Signed-off-by: Jim Bugwadia <jim@nirmata.com> * remove timing check for policy creation Signed-off-by: Jim Bugwadia <jim@nirmata.com> * fix e2e error - policy not found Signed-off-by: Shuting Zhao <shutting06@gmail.com> * update string comparison method Signed-off-by: Shuting Zhao <shutting06@gmail.com> * fix test Generate_Namespace_Label_Actions Signed-off-by: Shuting Zhao <shutting06@gmail.com> * add debug info for e2e tests Signed-off-by: Jim Bugwadia <jim@nirmata.com> * fix error Signed-off-by: Jim Bugwadia <jim@nirmata.com> * fix generate bug Signed-off-by: Jim Bugwadia <jim@nirmata.com> * fix format Signed-off-by: Jim Bugwadia <jim@nirmata.com> * add check for update operations Signed-off-by: Jim Bugwadia <jim@nirmata.com> * increase time for deleteing a resource Signed-off-by: Jim Bugwadia <jim@nirmata.com> * fix check Signed-off-by: Jim Bugwadia <jim@nirmata.com> Co-authored-by: Shuting Zhao <shutting06@gmail.com>
203 lines
6.1 KiB
Go
203 lines
6.1 KiB
Go
package common
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/go-logr/logr"
|
|
kyverno "github.com/kyverno/kyverno/pkg/api/kyverno/v1"
|
|
dclient "github.com/kyverno/kyverno/pkg/dclient"
|
|
enginutils "github.com/kyverno/kyverno/pkg/engine/utils"
|
|
"github.com/pkg/errors"
|
|
v1 "k8s.io/api/core/v1"
|
|
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
|
"k8s.io/client-go/informers"
|
|
listerv1 "k8s.io/client-go/listers/core/v1"
|
|
"sigs.k8s.io/controller-runtime/pkg/log"
|
|
)
|
|
|
|
// Policy Reporting Modes
|
|
const (
|
|
Enforce = "enforce" // blocks the request on failure
|
|
Audit = "audit" // dont block the request on failure, but report failiures as policy violations
|
|
)
|
|
|
|
// Policy Reporting Types
|
|
const (
|
|
PolicyViolation = "POLICYVIOLATION"
|
|
PolicyReport = "POLICYREPORT"
|
|
)
|
|
|
|
// GetNamespaceSelectorsFromGenericInformer - extracting the namespacelabels when generic informer is passed
|
|
func GetNamespaceSelectorsFromGenericInformer(kind, namespaceOfResource string, nsInformer informers.GenericInformer, logger logr.Logger) map[string]string {
|
|
namespaceLabels := make(map[string]string)
|
|
if kind != "Namespace" {
|
|
runtimeNamespaceObj, err := nsInformer.Lister().Get(namespaceOfResource)
|
|
if err != nil {
|
|
log.Log.Error(err, "failed to get the namespace", "name", namespaceOfResource)
|
|
return namespaceLabels
|
|
}
|
|
|
|
unstructuredObj := runtimeNamespaceObj.(*unstructured.Unstructured)
|
|
return unstructuredObj.GetLabels()
|
|
}
|
|
return namespaceLabels
|
|
}
|
|
|
|
// GetNamespaceSelectorsFromNamespaceLister - extract the namespacelabels when namespace lister is passed
|
|
func GetNamespaceSelectorsFromNamespaceLister(kind, namespaceOfResource string, nsLister listerv1.NamespaceLister, logger logr.Logger) map[string]string {
|
|
namespaceLabels := make(map[string]string)
|
|
if kind != "Namespace" {
|
|
namespaceObj, err := nsLister.Get(namespaceOfResource)
|
|
if err != nil {
|
|
log.Log.Error(err, "failed to get the namespace", "name", namespaceOfResource)
|
|
return namespaceLabels
|
|
}
|
|
return GetNamespaceLabels(namespaceObj, logger)
|
|
}
|
|
return namespaceLabels
|
|
}
|
|
|
|
// GetNamespaceLabels - from namespace obj
|
|
func GetNamespaceLabels(namespaceObj *v1.Namespace, logger logr.Logger) map[string]string {
|
|
namespaceObj.Kind = "Namespace"
|
|
namespaceRaw, err := json.Marshal(namespaceObj)
|
|
namespaceUnstructured, err := enginutils.ConvertToUnstructured(namespaceRaw)
|
|
if err != nil {
|
|
logger.Error(err, "failed to convert object resource to unstructured format")
|
|
}
|
|
return namespaceUnstructured.GetLabels()
|
|
}
|
|
|
|
// GetKindFromGVK - get kind and APIVersion from GVK
|
|
func GetKindFromGVK(str string) (apiVersion string, kind string) {
|
|
if strings.Count(str, "/") == 0 {
|
|
return "", str
|
|
}
|
|
splitString := strings.Split(str, "/")
|
|
if strings.Count(str, "/") == 1 {
|
|
return splitString[0], splitString[1]
|
|
}
|
|
return splitString[0] + "/" + splitString[1], splitString[2]
|
|
}
|
|
|
|
func VariableToJSON(key, value string) []byte {
|
|
var subString string
|
|
splitBySlash := strings.Split(key, "\"")
|
|
if len(splitBySlash) > 1 {
|
|
subString = splitBySlash[1]
|
|
}
|
|
|
|
startString := ""
|
|
endString := ""
|
|
lenOfVariableString := 0
|
|
addedSlashString := false
|
|
for _, k := range strings.Split(splitBySlash[0], ".") {
|
|
if k != "" {
|
|
startString += fmt.Sprintf(`{"%s":`, k)
|
|
endString += `}`
|
|
lenOfVariableString = lenOfVariableString + len(k) + 1
|
|
if lenOfVariableString >= len(splitBySlash[0]) && len(splitBySlash) > 1 && !addedSlashString {
|
|
startString += fmt.Sprintf(`{"%s":`, subString)
|
|
endString += `}`
|
|
addedSlashString = true
|
|
}
|
|
}
|
|
}
|
|
|
|
midString := fmt.Sprintf(`"%s"`, strings.Replace(value, `"`, `\"`, -1))
|
|
finalString := startString + midString + endString
|
|
var jsonData = []byte(finalString)
|
|
return jsonData
|
|
}
|
|
|
|
func RetryFunc(retryInterval, timeout time.Duration, run func() error, logger logr.Logger) func() error {
|
|
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 {
|
|
logger.V(3).Info("Failed to register admission control webhooks", "reason", err.Error())
|
|
} else {
|
|
break loop
|
|
}
|
|
|
|
case <-registerTimeout:
|
|
return errors.Wrap(err, "Timeout registering admission control webhooks")
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
}
|
|
|
|
func ProcessDeletePolicyForCloneGenerateRule(rules []kyverno.Rule, client *dclient.Client, pName string, logger logr.Logger) bool {
|
|
generatePolicyWithClone := false
|
|
for _, rule := range rules {
|
|
if rule.Generation.Clone.Name == "" {
|
|
continue
|
|
}
|
|
|
|
logger.V(4).Info("generate policy with clone, remove policy name from label of source resource")
|
|
generatePolicyWithClone = true
|
|
|
|
retryCount := 0
|
|
for retryCount < 5 {
|
|
err := updateSourceResource(pName, rule, client, logger)
|
|
if err != nil {
|
|
logger.Error(err, "failed to update generate source resource labels")
|
|
if apierrors.IsConflict(err) {
|
|
retryCount++
|
|
} else {
|
|
break
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return generatePolicyWithClone
|
|
}
|
|
|
|
func updateSourceResource(pName string, rule kyverno.Rule, client *dclient.Client, log logr.Logger) error {
|
|
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)
|
|
}
|
|
|
|
update := false
|
|
labels := obj.GetLabels()
|
|
update, labels = removePolicyFromLabels(pName, labels)
|
|
if update {
|
|
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) {
|
|
updatedPolicyNames := strings.Replace(policyNames, pName, "", -1)
|
|
labels["generate.kyverno.io/clone-policy-name"] = updatedPolicyNames
|
|
return true, labels
|
|
}
|
|
}
|
|
|
|
return false, labels
|
|
}
|