1
0
Fork 0
mirror of https://github.com/kyverno/kyverno.git synced 2024-12-14 11:57:48 +00:00
kyverno/pkg/common/common.go
Jim Bugwadia 13caaed8b7
Feature/cosign (#2078)
* 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>
2021-07-09 18:01:46 -07:00

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
}