1
0
Fork 0
mirror of https://github.com/kyverno/kyverno.git synced 2025-03-06 07:57:07 +00:00
kyverno/pkg/policy/validate.go

988 lines
32 KiB
Go
Raw Normal View History

package policy
import (
"encoding/json"
"errors"
"fmt"
"reflect"
"strings"
api server lookups (#1514) * initial commit for api server lookups Signed-off-by: Jim Bugwadia <jim@nirmata.com> * initial commit for API server lookups Signed-off-by: Jim Bugwadia <jim@nirmata.com> * Enhancing dockerfiles (multi-stage) of kyverno components and adding non-root user to the docker images (#1495) * Dockerfile refactored Signed-off-by: Raj Babu Das <mail.rajdas@gmail.com> * Adding non-root commands to docker images and enhanced the dockerfiles Signed-off-by: Raj Babu Das <mail.rajdas@gmail.com> * changing base image to scratch Signed-off-by: Raj Babu Das <mail.rajdas@gmail.com> * Minor typo fix Signed-off-by: Raj Babu Das <mail.rajdas@gmail.com> * changing dockerfiles to use /etc/passwd to use non-root user' Signed-off-by: Raj Babu Das <mail.rajdas@gmail.com> * minor typo Signed-off-by: Raj Babu Das <mail.rajdas@gmail.com> * minor typo Signed-off-by: Raj Babu Das <mail.rajdas@gmail.com> Signed-off-by: Jim Bugwadia <jim@nirmata.com> * revert cli image name (#1507) Signed-off-by: Raj Babu Das <mail.rajdas@gmail.com> Signed-off-by: Jim Bugwadia <jim@nirmata.com> * Refactor resourceCache; Reduce throttling requests (background controller) (#1500) * skip sending API request for filtered resource * fix PR comment Signed-off-by: Shuting Zhao <shutting06@gmail.com> * fixes https://github.com/kyverno/kyverno/issues/1490 Signed-off-by: Shuting Zhao <shutting06@gmail.com> * fix bug - namespace is not returned properly Signed-off-by: Shuting Zhao <shutting06@gmail.com> * reduce throttling - list resource using lister * refactor resource cache * fix test Signed-off-by: Shuting Zhao <shutting06@gmail.com> * fix label selector Signed-off-by: Shuting Zhao <shutting06@gmail.com> * fix build failure Signed-off-by: Shuting Zhao <shutting06@gmail.com> Signed-off-by: Jim Bugwadia <jim@nirmata.com> * fix merge issues Signed-off-by: Jim Bugwadia <jim@nirmata.com> * fix unit test Signed-off-by: Jim Bugwadia <jim@nirmata.com> * add nil check for API client Signed-off-by: Jim Bugwadia <jim@nirmata.com> Co-authored-by: Raj Babu Das <mail.rajdas@gmail.com> Co-authored-by: shuting <shutting06@gmail.com>
2021-02-01 12:59:13 -08:00
"github.com/jmespath/go-jmespath"
c "github.com/kyverno/kyverno/pkg/common"
api server lookups (#1514) * initial commit for api server lookups Signed-off-by: Jim Bugwadia <jim@nirmata.com> * initial commit for API server lookups Signed-off-by: Jim Bugwadia <jim@nirmata.com> * Enhancing dockerfiles (multi-stage) of kyverno components and adding non-root user to the docker images (#1495) * Dockerfile refactored Signed-off-by: Raj Babu Das <mail.rajdas@gmail.com> * Adding non-root commands to docker images and enhanced the dockerfiles Signed-off-by: Raj Babu Das <mail.rajdas@gmail.com> * changing base image to scratch Signed-off-by: Raj Babu Das <mail.rajdas@gmail.com> * Minor typo fix Signed-off-by: Raj Babu Das <mail.rajdas@gmail.com> * changing dockerfiles to use /etc/passwd to use non-root user' Signed-off-by: Raj Babu Das <mail.rajdas@gmail.com> * minor typo Signed-off-by: Raj Babu Das <mail.rajdas@gmail.com> * minor typo Signed-off-by: Raj Babu Das <mail.rajdas@gmail.com> Signed-off-by: Jim Bugwadia <jim@nirmata.com> * revert cli image name (#1507) Signed-off-by: Raj Babu Das <mail.rajdas@gmail.com> Signed-off-by: Jim Bugwadia <jim@nirmata.com> * Refactor resourceCache; Reduce throttling requests (background controller) (#1500) * skip sending API request for filtered resource * fix PR comment Signed-off-by: Shuting Zhao <shutting06@gmail.com> * fixes https://github.com/kyverno/kyverno/issues/1490 Signed-off-by: Shuting Zhao <shutting06@gmail.com> * fix bug - namespace is not returned properly Signed-off-by: Shuting Zhao <shutting06@gmail.com> * reduce throttling - list resource using lister * refactor resource cache * fix test Signed-off-by: Shuting Zhao <shutting06@gmail.com> * fix label selector Signed-off-by: Shuting Zhao <shutting06@gmail.com> * fix build failure Signed-off-by: Shuting Zhao <shutting06@gmail.com> Signed-off-by: Jim Bugwadia <jim@nirmata.com> * fix merge issues Signed-off-by: Jim Bugwadia <jim@nirmata.com> * fix unit test Signed-off-by: Jim Bugwadia <jim@nirmata.com> * add nil check for API client Signed-off-by: Jim Bugwadia <jim@nirmata.com> Co-authored-by: Raj Babu Das <mail.rajdas@gmail.com> Co-authored-by: shuting <shutting06@gmail.com>
2021-02-01 12:59:13 -08:00
"github.com/kyverno/kyverno/pkg/engine"
"github.com/kyverno/kyverno/pkg/engine/variables"
api server lookups (#1514) * initial commit for api server lookups Signed-off-by: Jim Bugwadia <jim@nirmata.com> * initial commit for API server lookups Signed-off-by: Jim Bugwadia <jim@nirmata.com> * Enhancing dockerfiles (multi-stage) of kyverno components and adding non-root user to the docker images (#1495) * Dockerfile refactored Signed-off-by: Raj Babu Das <mail.rajdas@gmail.com> * Adding non-root commands to docker images and enhanced the dockerfiles Signed-off-by: Raj Babu Das <mail.rajdas@gmail.com> * changing base image to scratch Signed-off-by: Raj Babu Das <mail.rajdas@gmail.com> * Minor typo fix Signed-off-by: Raj Babu Das <mail.rajdas@gmail.com> * changing dockerfiles to use /etc/passwd to use non-root user' Signed-off-by: Raj Babu Das <mail.rajdas@gmail.com> * minor typo Signed-off-by: Raj Babu Das <mail.rajdas@gmail.com> * minor typo Signed-off-by: Raj Babu Das <mail.rajdas@gmail.com> Signed-off-by: Jim Bugwadia <jim@nirmata.com> * revert cli image name (#1507) Signed-off-by: Raj Babu Das <mail.rajdas@gmail.com> Signed-off-by: Jim Bugwadia <jim@nirmata.com> * Refactor resourceCache; Reduce throttling requests (background controller) (#1500) * skip sending API request for filtered resource * fix PR comment Signed-off-by: Shuting Zhao <shutting06@gmail.com> * fixes https://github.com/kyverno/kyverno/issues/1490 Signed-off-by: Shuting Zhao <shutting06@gmail.com> * fix bug - namespace is not returned properly Signed-off-by: Shuting Zhao <shutting06@gmail.com> * reduce throttling - list resource using lister * refactor resource cache * fix test Signed-off-by: Shuting Zhao <shutting06@gmail.com> * fix label selector Signed-off-by: Shuting Zhao <shutting06@gmail.com> * fix build failure Signed-off-by: Shuting Zhao <shutting06@gmail.com> Signed-off-by: Jim Bugwadia <jim@nirmata.com> * fix merge issues Signed-off-by: Jim Bugwadia <jim@nirmata.com> * fix unit test Signed-off-by: Jim Bugwadia <jim@nirmata.com> * add nil check for API client Signed-off-by: Jim Bugwadia <jim@nirmata.com> Co-authored-by: Raj Babu Das <mail.rajdas@gmail.com> Co-authored-by: shuting <shutting06@gmail.com>
2021-02-01 12:59:13 -08:00
"github.com/kyverno/kyverno/pkg/kyverno/common"
kyverno "github.com/kyverno/kyverno/pkg/api/kyverno/v1"
dclient "github.com/kyverno/kyverno/pkg/dclient"
2020-11-13 16:25:51 -08:00
"github.com/kyverno/kyverno/pkg/openapi"
2020-12-15 15:21:39 -08:00
"github.com/kyverno/kyverno/pkg/utils"
2021-06-10 07:46:26 +05:30
"github.com/minio/pkg/wildcard"
2019-12-04 18:50:51 -08:00
rbacv1 "k8s.io/api/rbac/v1"
"k8s.io/apiextensions-apiserver/pkg/apis/apiextensions"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2020-11-13 16:25:51 -08:00
log "sigs.k8s.io/controller-runtime/pkg/log"
)
2019-10-21 14:22:31 -07:00
// Validate does some initial check to verify some conditions
// - One operation per rule
// - ResourceDescription mandatory checks
func Validate(policy *kyverno.ClusterPolicy, client *dclient.Client, mock bool, openAPIController *openapi.Controller) error {
p := *policy
if len(common.PolicyHasVariables(p)) > 0 {
err := common.PolicyHasNonAllowedVariables(p)
if err != nil {
return fmt.Errorf("policy contains invalid variables: %s", err.Error())
}
}
// policy name is stored in the label of the report change request
if len(p.Name) > 63 {
return fmt.Errorf("invalid policy name %s: must be no more than 63 characters", p.Name)
}
2019-10-21 14:22:31 -07:00
if path, err := validateUniqueRuleName(p); err != nil {
return fmt.Errorf("path: spec.%s: %v", path, err)
}
2020-11-25 10:11:59 -08:00
if p.Spec.Background == nil || *p.Spec.Background == true {
if err := ContainsVariablesOtherThanObject(p); err != nil {
return fmt.Errorf("only select variables are allowed in background mode. Set spec.background=false to disable background mode for this policy rule: %s ", err)
}
}
2019-10-21 14:22:31 -07:00
for i, rule := range p.Spec.Rules {
if jsonPatchOnPod(rule) {
2021-07-21 12:10:52 +05:30
log.Log.V(1).Info("pods managed by workload controllers cannot be mutated using policies. Use the auto-gen feature or write policies that match pod controllers.")
}
2019-10-21 14:22:31 -07:00
// validate resource description
if path, err := validateResources(rule); err != nil {
return fmt.Errorf("path: spec.rules[%d].%s: %v", i, path, err)
}
2020-10-14 17:39:45 -07:00
2019-10-21 14:22:31 -07:00
// validate rule types
// only one type of rule is allowed per rule
if err := validateRuleType(rule); err != nil {
// as there are more than 1 operation in rule, not need to evaluate it further
return fmt.Errorf("path: spec.rules[%d]: %v", i, err)
}
2020-10-14 17:39:45 -07:00
if err := validateRuleContext(rule); err != nil {
return fmt.Errorf("path: spec.rules[%d]: %v", i, err)
}
2020-11-13 16:25:51 -08:00
// validate Cluster Resources in namespaced policy
// For namespaced policy, ClusterResource type field and values are not allowed in match and exclude
if !mock && p.ObjectMeta.Namespace != "" {
var Empty struct{}
clusterResourcesMap := make(map[string]*struct{})
// Get all the cluster type kind supported by cluster
Add Policy Report (#1229) * add report in cli * policy report crd added * policy report added * configmap added * added jobs * added jobs * bug fixed * added logic for cli * common function added * sub command added for policy report * subcommand added for report * common package changed * configmap added * added logic for kyverno cli * added logic for jobs * added logic for jobs * added logic for jobs * added logic for cli * buf fix * cli changes * count bug fix * docs added for command * go fmt * refactor codebase * remove policy controller for policyreport * policy report removed * bug fixes * bug fixes * added job trigger if needed * job deletation logic added * build failed fix * fixed e2e test * remove hard coded variables * packages adde * improvment added in jobs sheduler * policy report yaml added * cronjob added * small fixes * remove background sync * documentation added for report command * remove extra log * small improvement * tested policy report * revert hardcoded changes * changes for demo * demo changes * resource aggrigation added * More changes * More changes * - resolve PR comments; - refactor jobs controller * set rbac for jobs * add clean up in job controller * add short names * remove application scope for policyreport * move job controller to policyreport * add report logic in command apply * - update policy report types; - upgrade k8s library; - update code gen * temporarily comment out code to pass CI build * generate / update policyreport to cluster * add unit test for CLI report * add test for apply - generate policy report * fix unit test * - remove job controller; - remove in-memory configmap; - clean up kustomize manifest * remove dependency * add reportRequest / clusterReportRequest * clean up policy report * generate report request * update crd clusterReportRequest * - update json tag of report summary; - update definition manifests; - fix dclient creation * aggregate reportRequest into policy report * fix unit tests * - update report summary to optional; - generate clusterPolicyReport; - remove reportRequests after merged to report * remove * generate reportRequest in kyverno namespace * update resource filter in helm chart * - rename reportRequest to reportChangeRequest; -rename clusterReportRequest to clusterReportChangeRequest * generate policy report in background scan * skip generating report change request if there's entry results * fix results entry removal when policy / rule gets deleted * rename apiversion from policy.kubernetes.io to policy.k8s.io * update summary.* to lower case * move reportChangeRequest to kyverno.io/v1alpha1 * remove policy report flag * fix report update * clean up policy violation CRD * remove violation CRD from manifest * clean up policy violation code - remove pvGenerator * change severity fields to lower case * update import library * set report category Co-authored-by: Yuvraj <yuvraj.yad001@gmail.com> Co-authored-by: Yuvraj <10830562+evalsocket@users.noreply.github.com> Co-authored-by: Jim Bugwadia <jim@nirmata.com>
2020-11-09 11:26:12 -08:00
res, err := client.DiscoveryClient.DiscoveryCache().ServerPreferredResources()
if err != nil {
return err
}
for _, resList := range res {
for _, r := range resList.APIResources {
if !r.Namespaced {
if _, ok := clusterResourcesMap[r.Kind]; !ok {
clusterResourcesMap[r.Kind] = &Empty
}
}
}
}
clusterResources := make([]string, 0, len(clusterResourcesMap))
for k := range clusterResourcesMap {
clusterResources = append(clusterResources, k)
}
return checkClusterResourceInMatchAndExclude(rule, clusterResources)
}
2020-10-14 17:39:45 -07:00
if doMatchAndExcludeConflict(rule) {
2020-04-27 22:01:33 +05:30
return fmt.Errorf("path: spec.rules[%v]: rule is matching an empty set", rule.Name)
}
2020-03-20 20:23:34 +05:30
// validate rule actions
// - Mutate
// - Validate
// - Generate
if err := validateActions(i, rule, client, mock); err != nil {
return err
}
2020-02-26 16:08:56 +05:30
adding any/all under match and exclude blocks (#2130) * intial commit Signed-off-by: RinkiyaKeDad <arshsharma461@gmail.com> * update types Signed-off-by: RinkiyaKeDad <arshsharma461@gmail.com> * updated all type Signed-off-by: RinkiyaKeDad <arshsharma461@gmail.com> * extract to single struct Signed-off-by: RinkiyaKeDad <arshsharma461@gmail.com> * updated match resource description function Signed-off-by: RinkiyaKeDad <arshsharma461@gmail.com> * minor test working Signed-off-by: RinkiyaKeDad <arshsharma461@gmail.com> * match resources test is working Signed-off-by: RinkiyaKeDad <arshsharma461@gmail.com> * exclude resources test is working Signed-off-by: RinkiyaKeDad <arshsharma461@gmail.com> * changed double negetive in logic Signed-off-by: RinkiyaKeDad <arshsharma461@gmail.com> * yamls updated and added validation and cache loops Signed-off-by: RinkiyaKeDad <arshsharma461@gmail.com> * match exclude working but need to fix matchExcludeConflict function Signed-off-by: RinkiyaKeDad <arshsharma461@gmail.com> * restored doMatchAndExcludeConflict function Signed-off-by: RinkiyaKeDad <arshsharma461@gmail.com> * rewrote the matchExcludeConflictFunction Signed-off-by: RinkiyaKeDad <arshsharma461@gmail.com> * finalizing completed till utils_test.go Signed-off-by: RinkiyaKeDad <arshsharma461@gmail.com> * ready for review complete Signed-off-by: RinkiyaKeDad <arshsharma461@gmail.com> * update yamls Signed-off-by: RinkiyaKeDad <arshsharma461@gmail.com> * one more merge conflict solved Signed-off-by: RinkiyaKeDad <arshsharma461@gmail.com> * regenerates YAMLs Signed-off-by: RinkiyaKeDad <arshsharma461@gmail.com> * possible fix for failing tests Signed-off-by: RinkiyaKeDad <arshsharma461@gmail.com> * removed duplicate any/all logic and added a test, (rest refacotring is in progress) Signed-off-by: RinkiyaKeDad <arshsharma461@gmail.com> * cache test is working Signed-off-by: RinkiyaKeDad <arshsharma461@gmail.com> * improved cache test and it is working Signed-off-by: RinkiyaKeDad <arshsharma461@gmail.com> * added check for mutate and generate policies too Signed-off-by: RinkiyaKeDad <arshsharma461@gmail.com> * cleaned doesResourceMatchConditionBlock logic but validation still has code from attempt to combine the all block Signed-off-by: RinkiyaKeDad <arshsharma461@gmail.com> * reverted validate.go to older logic Signed-off-by: RinkiyaKeDad <arshsharma461@gmail.com> * removed commented code Signed-off-by: RinkiyaKeDad <arshsharma461@gmail.com> * removed extra comments Signed-off-by: RinkiyaKeDad <arshsharma461@gmail.com>
2021-07-29 01:29:53 +05:30
// If a rule's match block does not match any kind,
// we should only allow it to have metadata in its overlay
if len(rule.MatchResources.Any) > 0 {
for _, rmr := range rule.MatchResources.Any {
if len(rmr.Kinds) == 0 {
return validateMatchKindHelper(rule)
}
}
} else if len(rule.MatchResources.All) > 0 {
for _, rmr := range rule.MatchResources.All {
if len(rmr.Kinds) == 0 {
return validateMatchKindHelper(rule)
}
}
} else {
if len(rule.MatchResources.Kinds) == 0 {
return validateMatchKindHelper(rule)
2020-02-26 16:08:56 +05:30
}
}
if utils.ContainsString(rule.MatchResources.Kinds, "*") || utils.ContainsString(rule.ExcludeResources.Kinds, "*") {
return fmt.Errorf("wildcards (*) are currently not supported in the match.resources.kinds field. at least one resource kind must be specified in a kind block.")
2020-02-26 16:08:56 +05:30
}
// Validate Kind with match resource kinds
for _, kind := range rule.MatchResources.Kinds {
_, k := c.GetKindFromGVK(kind)
if k == p.Kind {
return fmt.Errorf("kind and match resource kind should not be the same.")
}
}
// Validate string values in labels
if !isLabelAndAnnotationsString(rule) {
return fmt.Errorf("labels and annotations supports only string values, \"use double quotes around the non string values\"")
}
// add label to source mentioned in policy
if !mock && rule.Generation.Clone.Name != "" {
obj, err := client.GetResource("", rule.Generation.Kind, rule.Generation.Clone.Namespace, rule.Generation.Clone.Name)
if err != nil {
log.Log.Error(err, fmt.Sprintf("source resource %s/%s/%s not found.", rule.Generation.Kind, rule.Generation.Clone.Namespace, rule.Generation.Clone.Name))
continue
}
updateSource := true
label := obj.GetLabels()
if len(label) == 0 {
label = make(map[string]string)
label["generate.kyverno.io/clone-policy-name"] = p.GetName()
} else {
if label["generate.kyverno.io/clone-policy-name"] != "" {
policyNames := label["generate.kyverno.io/clone-policy-name"]
if !strings.Contains(policyNames, p.GetName()) {
policyNames = policyNames + "," + p.GetName()
label["generate.kyverno.io/clone-policy-name"] = policyNames
} else {
updateSource = false
}
} else {
label["generate.kyverno.io/clone-policy-name"] = p.GetName()
}
}
if updateSource {
log.Log.V(4).Info("updating existing clone source")
obj.SetLabels(label)
_, err = client.UpdateResource(obj.GetAPIVersion(), rule.Generation.Kind, rule.Generation.Clone.Namespace, obj, false)
if err != nil {
log.Log.Error(err, "failed to update source", "kind", obj.GetKind(), "name", obj.GetName(), "namespace", obj.GetNamespace())
continue
}
log.Log.V(4).Info("updated source", "kind", obj.GetKind(), "name", obj.GetName(), "namespace", obj.GetNamespace())
}
}
}
2020-01-25 14:53:12 +05:30
2020-04-01 19:06:13 +05:30
if !mock {
if err := openAPIController.ValidatePolicyFields(p); err != nil {
2020-04-01 19:06:13 +05:30
return err
}
} else {
if err := openAPIController.ValidatePolicyMutation(p); err != nil {
return err
}
2020-03-04 19:16:26 +05:30
}
return nil
}
adding any/all under match and exclude blocks (#2130) * intial commit Signed-off-by: RinkiyaKeDad <arshsharma461@gmail.com> * update types Signed-off-by: RinkiyaKeDad <arshsharma461@gmail.com> * updated all type Signed-off-by: RinkiyaKeDad <arshsharma461@gmail.com> * extract to single struct Signed-off-by: RinkiyaKeDad <arshsharma461@gmail.com> * updated match resource description function Signed-off-by: RinkiyaKeDad <arshsharma461@gmail.com> * minor test working Signed-off-by: RinkiyaKeDad <arshsharma461@gmail.com> * match resources test is working Signed-off-by: RinkiyaKeDad <arshsharma461@gmail.com> * exclude resources test is working Signed-off-by: RinkiyaKeDad <arshsharma461@gmail.com> * changed double negetive in logic Signed-off-by: RinkiyaKeDad <arshsharma461@gmail.com> * yamls updated and added validation and cache loops Signed-off-by: RinkiyaKeDad <arshsharma461@gmail.com> * match exclude working but need to fix matchExcludeConflict function Signed-off-by: RinkiyaKeDad <arshsharma461@gmail.com> * restored doMatchAndExcludeConflict function Signed-off-by: RinkiyaKeDad <arshsharma461@gmail.com> * rewrote the matchExcludeConflictFunction Signed-off-by: RinkiyaKeDad <arshsharma461@gmail.com> * finalizing completed till utils_test.go Signed-off-by: RinkiyaKeDad <arshsharma461@gmail.com> * ready for review complete Signed-off-by: RinkiyaKeDad <arshsharma461@gmail.com> * update yamls Signed-off-by: RinkiyaKeDad <arshsharma461@gmail.com> * one more merge conflict solved Signed-off-by: RinkiyaKeDad <arshsharma461@gmail.com> * regenerates YAMLs Signed-off-by: RinkiyaKeDad <arshsharma461@gmail.com> * possible fix for failing tests Signed-off-by: RinkiyaKeDad <arshsharma461@gmail.com> * removed duplicate any/all logic and added a test, (rest refacotring is in progress) Signed-off-by: RinkiyaKeDad <arshsharma461@gmail.com> * cache test is working Signed-off-by: RinkiyaKeDad <arshsharma461@gmail.com> * improved cache test and it is working Signed-off-by: RinkiyaKeDad <arshsharma461@gmail.com> * added check for mutate and generate policies too Signed-off-by: RinkiyaKeDad <arshsharma461@gmail.com> * cleaned doesResourceMatchConditionBlock logic but validation still has code from attempt to combine the all block Signed-off-by: RinkiyaKeDad <arshsharma461@gmail.com> * reverted validate.go to older logic Signed-off-by: RinkiyaKeDad <arshsharma461@gmail.com> * removed commented code Signed-off-by: RinkiyaKeDad <arshsharma461@gmail.com> * removed extra comments Signed-off-by: RinkiyaKeDad <arshsharma461@gmail.com>
2021-07-29 01:29:53 +05:30
func validateMatchKindHelper(rule kyverno.Rule) error {
if !ruleOnlyDealsWithResourceMetaData(rule) {
return fmt.Errorf("policy can only deal with the metadata field of the resource if" +
" the rule does not match an kind")
}
return fmt.Errorf("At least one element must be specified in a kind block. The kind attribute is mandatory when working with the resources element")
}
2020-10-14 17:39:45 -07:00
// doMatchAndExcludeConflict checks if the resultant
2020-04-04 12:46:51 +05:30
// of match and exclude block is not an empty set
// returns true if it is an empty set
2020-10-14 17:39:45 -07:00
func doMatchAndExcludeConflict(rule kyverno.Rule) bool {
2020-03-20 20:23:34 +05:30
adding any/all under match and exclude blocks (#2130) * intial commit Signed-off-by: RinkiyaKeDad <arshsharma461@gmail.com> * update types Signed-off-by: RinkiyaKeDad <arshsharma461@gmail.com> * updated all type Signed-off-by: RinkiyaKeDad <arshsharma461@gmail.com> * extract to single struct Signed-off-by: RinkiyaKeDad <arshsharma461@gmail.com> * updated match resource description function Signed-off-by: RinkiyaKeDad <arshsharma461@gmail.com> * minor test working Signed-off-by: RinkiyaKeDad <arshsharma461@gmail.com> * match resources test is working Signed-off-by: RinkiyaKeDad <arshsharma461@gmail.com> * exclude resources test is working Signed-off-by: RinkiyaKeDad <arshsharma461@gmail.com> * changed double negetive in logic Signed-off-by: RinkiyaKeDad <arshsharma461@gmail.com> * yamls updated and added validation and cache loops Signed-off-by: RinkiyaKeDad <arshsharma461@gmail.com> * match exclude working but need to fix matchExcludeConflict function Signed-off-by: RinkiyaKeDad <arshsharma461@gmail.com> * restored doMatchAndExcludeConflict function Signed-off-by: RinkiyaKeDad <arshsharma461@gmail.com> * rewrote the matchExcludeConflictFunction Signed-off-by: RinkiyaKeDad <arshsharma461@gmail.com> * finalizing completed till utils_test.go Signed-off-by: RinkiyaKeDad <arshsharma461@gmail.com> * ready for review complete Signed-off-by: RinkiyaKeDad <arshsharma461@gmail.com> * update yamls Signed-off-by: RinkiyaKeDad <arshsharma461@gmail.com> * one more merge conflict solved Signed-off-by: RinkiyaKeDad <arshsharma461@gmail.com> * regenerates YAMLs Signed-off-by: RinkiyaKeDad <arshsharma461@gmail.com> * possible fix for failing tests Signed-off-by: RinkiyaKeDad <arshsharma461@gmail.com> * removed duplicate any/all logic and added a test, (rest refacotring is in progress) Signed-off-by: RinkiyaKeDad <arshsharma461@gmail.com> * cache test is working Signed-off-by: RinkiyaKeDad <arshsharma461@gmail.com> * improved cache test and it is working Signed-off-by: RinkiyaKeDad <arshsharma461@gmail.com> * added check for mutate and generate policies too Signed-off-by: RinkiyaKeDad <arshsharma461@gmail.com> * cleaned doesResourceMatchConditionBlock logic but validation still has code from attempt to combine the all block Signed-off-by: RinkiyaKeDad <arshsharma461@gmail.com> * reverted validate.go to older logic Signed-off-by: RinkiyaKeDad <arshsharma461@gmail.com> * removed commented code Signed-off-by: RinkiyaKeDad <arshsharma461@gmail.com> * removed extra comments Signed-off-by: RinkiyaKeDad <arshsharma461@gmail.com>
2021-07-29 01:29:53 +05:30
if len(rule.ExcludeResources.All) > 0 || len(rule.MatchResources.All) > 0 {
return false
}
// if both have any then no resource should be common
if len(rule.MatchResources.Any) > 0 && len(rule.ExcludeResources.Any) > 0 {
for _, rmr := range rule.MatchResources.Any {
for _, rer := range rule.ExcludeResources.Any {
if reflect.DeepEqual(rmr, rer) {
return true
}
}
}
return false
}
2020-04-04 16:18:36 +05:30
if reflect.DeepEqual(rule.ExcludeResources, kyverno.ExcludeResources{}) {
return false
}
2020-03-20 20:23:34 +05:30
excludeRoles := make(map[string]bool)
for _, role := range rule.ExcludeResources.UserInfo.Roles {
excludeRoles[role] = true
}
excludeClusterRoles := make(map[string]bool)
for _, clusterRoles := range rule.ExcludeResources.UserInfo.ClusterRoles {
excludeClusterRoles[clusterRoles] = true
}
excludeSubjects := make(map[string]bool)
for _, subject := range rule.ExcludeResources.UserInfo.Subjects {
subjectRaw, _ := json.Marshal(subject)
excludeSubjects[string(subjectRaw)] = true
}
excludeKinds := make(map[string]bool)
for _, kind := range rule.ExcludeResources.ResourceDescription.Kinds {
excludeKinds[kind] = true
}
excludeNamespaces := make(map[string]bool)
for _, namespace := range rule.ExcludeResources.ResourceDescription.Namespaces {
excludeNamespaces[namespace] = true
}
excludeSelectorMatchExpressions := make(map[string]bool)
2020-03-20 20:23:34 +05:30
if rule.ExcludeResources.ResourceDescription.Selector != nil {
for _, matchExpression := range rule.ExcludeResources.ResourceDescription.Selector.MatchExpressions {
matchExpressionRaw, _ := json.Marshal(matchExpression)
excludeSelectorMatchExpressions[string(matchExpressionRaw)] = true
}
}
excludeNamespaceSelectorMatchExpressions := make(map[string]bool)
if rule.ExcludeResources.ResourceDescription.NamespaceSelector != nil {
for _, matchExpression := range rule.ExcludeResources.ResourceDescription.NamespaceSelector.MatchExpressions {
matchExpressionRaw, _ := json.Marshal(matchExpression)
excludeNamespaceSelectorMatchExpressions[string(matchExpressionRaw)] = true
2020-03-20 20:23:34 +05:30
}
}
2020-04-04 12:46:51 +05:30
if len(excludeRoles) > 0 {
2020-04-27 15:05:10 +05:30
if len(rule.MatchResources.UserInfo.Roles) == 0 {
return false
}
2020-04-04 12:46:51 +05:30
for _, role := range rule.MatchResources.UserInfo.Roles {
if !excludeRoles[role] {
return false
}
2020-03-20 20:23:34 +05:30
}
}
2020-04-04 12:46:51 +05:30
if len(excludeClusterRoles) > 0 {
2020-04-27 15:05:10 +05:30
if len(rule.MatchResources.UserInfo.ClusterRoles) == 0 {
return false
}
2020-04-04 12:46:51 +05:30
for _, clusterRole := range rule.MatchResources.UserInfo.ClusterRoles {
if !excludeClusterRoles[clusterRole] {
return false
}
2020-03-20 20:23:34 +05:30
}
}
2020-04-04 12:46:51 +05:30
if len(excludeSubjects) > 0 {
2020-04-27 15:05:10 +05:30
if len(rule.MatchResources.UserInfo.Subjects) == 0 {
return false
}
2020-04-04 12:46:51 +05:30
for _, subject := range rule.MatchResources.UserInfo.Subjects {
subjectRaw, _ := json.Marshal(subject)
if !excludeSubjects[string(subjectRaw)] {
return false
}
2020-03-20 20:23:34 +05:30
}
}
2020-04-04 12:46:51 +05:30
if rule.ExcludeResources.ResourceDescription.Name != "" {
if !wildcard.Match(rule.ExcludeResources.ResourceDescription.Name, rule.MatchResources.ResourceDescription.Name) {
return false
2020-03-20 20:23:34 +05:30
}
}
if len(rule.ExcludeResources.ResourceDescription.Names) > 0 {
excludeSlice := rule.ExcludeResources.ResourceDescription.Names
matchSlice := rule.MatchResources.ResourceDescription.Names
// if exclude block has something and match doesn't it means we
// have a non empty set
if len(rule.MatchResources.ResourceDescription.Names) == 0 {
return false
}
// if *any* name in match and exclude conflicts
// we want user to fix that
for _, matchName := range matchSlice {
for _, excludeName := range excludeSlice {
if wildcard.Match(excludeName, matchName) {
return true
}
}
}
return false
}
2020-04-04 14:49:50 +05:30
if len(excludeNamespaces) > 0 {
2020-04-27 15:05:10 +05:30
if len(rule.MatchResources.ResourceDescription.Namespaces) == 0 {
return false
}
2020-04-04 12:46:51 +05:30
for _, namespace := range rule.MatchResources.ResourceDescription.Namespaces {
if !excludeNamespaces[namespace] {
return false
}
2020-03-20 20:23:34 +05:30
}
}
2020-04-04 14:49:50 +05:30
if len(excludeKinds) > 0 {
2020-04-27 15:05:10 +05:30
if len(rule.MatchResources.ResourceDescription.Kinds) == 0 {
return false
}
2020-04-04 12:46:51 +05:30
for _, kind := range rule.MatchResources.ResourceDescription.Kinds {
if !excludeKinds[kind] {
return false
}
2020-03-20 20:23:34 +05:30
}
}
if rule.MatchResources.ResourceDescription.Selector != nil && rule.ExcludeResources.ResourceDescription.Selector != nil {
if len(excludeSelectorMatchExpressions) > 0 {
2020-04-27 15:05:10 +05:30
if len(rule.MatchResources.ResourceDescription.Selector.MatchExpressions) == 0 {
return false
}
2020-04-04 12:46:51 +05:30
for _, matchExpression := range rule.MatchResources.ResourceDescription.Selector.MatchExpressions {
matchExpressionRaw, _ := json.Marshal(matchExpression)
if !excludeSelectorMatchExpressions[string(matchExpressionRaw)] {
2020-04-04 12:46:51 +05:30
return false
}
2020-03-20 20:23:34 +05:30
}
}
2020-04-04 14:49:50 +05:30
if len(rule.ExcludeResources.ResourceDescription.Selector.MatchLabels) > 0 {
2020-04-27 15:05:10 +05:30
if len(rule.MatchResources.ResourceDescription.Selector.MatchLabels) == 0 {
return false
}
2020-04-04 12:46:51 +05:30
for label, value := range rule.MatchResources.ResourceDescription.Selector.MatchLabels {
if rule.ExcludeResources.ResourceDescription.Selector.MatchLabels[label] != value {
return false
}
2020-03-20 20:23:34 +05:30
}
}
}
if rule.MatchResources.ResourceDescription.NamespaceSelector != nil && rule.ExcludeResources.ResourceDescription.NamespaceSelector != nil {
if len(excludeNamespaceSelectorMatchExpressions) > 0 {
if len(rule.MatchResources.ResourceDescription.NamespaceSelector.MatchExpressions) == 0 {
return false
}
for _, matchExpression := range rule.MatchResources.ResourceDescription.NamespaceSelector.MatchExpressions {
matchExpressionRaw, _ := json.Marshal(matchExpression)
if !excludeNamespaceSelectorMatchExpressions[string(matchExpressionRaw)] {
return false
}
}
}
if len(rule.ExcludeResources.ResourceDescription.NamespaceSelector.MatchLabels) > 0 {
if len(rule.MatchResources.ResourceDescription.NamespaceSelector.MatchLabels) == 0 {
return false
}
for label, value := range rule.MatchResources.ResourceDescription.NamespaceSelector.MatchLabels {
if rule.ExcludeResources.ResourceDescription.NamespaceSelector.MatchLabels[label] != value {
return false
}
}
}
}
if (rule.MatchResources.ResourceDescription.Selector == nil && rule.ExcludeResources.ResourceDescription.Selector != nil) ||
(rule.MatchResources.ResourceDescription.Selector != nil && rule.ExcludeResources.ResourceDescription.Selector == nil) {
return false
}
if (rule.MatchResources.ResourceDescription.NamespaceSelector == nil && rule.ExcludeResources.ResourceDescription.NamespaceSelector != nil) ||
(rule.MatchResources.ResourceDescription.NamespaceSelector != nil && rule.ExcludeResources.ResourceDescription.NamespaceSelector == nil) {
return false
}
2020-11-25 11:50:53 +05:30
if rule.MatchResources.Annotations != nil && rule.ExcludeResources.Annotations != nil {
if !(reflect.DeepEqual(rule.MatchResources.Annotations, rule.ExcludeResources.Annotations)) {
return false
}
}
if (rule.MatchResources.Annotations == nil && rule.ExcludeResources.Annotations != nil) ||
(rule.MatchResources.Annotations != nil && rule.ExcludeResources.Annotations == nil) {
return false
}
2020-04-04 12:46:51 +05:30
return true
2020-03-20 20:23:34 +05:30
}
// isLabelAndAnnotationsString :- Validate if labels and annotations contains only string values
func isLabelAndAnnotationsString(rule kyverno.Rule) bool {
// checkMetadata - Verify if the labels and annotations contains string value inside metadata
checkMetadata := func(patternMap map[string]interface{}) bool {
for k := range patternMap {
if k == "metadata" {
metaKey, ok := patternMap[k].(map[string]interface{})
if ok {
// range over metadata
for mk := range metaKey {
if mk == "labels" {
labelKey, ok := metaKey[mk].(map[string]interface{})
if ok {
// range over labels
for _, val := range labelKey {
if reflect.TypeOf(val).String() != "string" {
return false
}
}
}
} else if mk == "annotations" {
annotationKey, ok := metaKey[mk].(map[string]interface{})
if ok {
// range over annotations
for _, val := range annotationKey {
if reflect.TypeOf(val).String() != "string" {
return false
}
}
}
}
}
}
}
}
return true
}
patternMap, ok := rule.Validation.Pattern.(map[string]interface{})
if ok {
return checkMetadata(patternMap)
2020-11-13 16:25:51 -08:00
} else if rule.Validation.AnyPattern != nil {
anyPatterns, err := rule.Validation.DeserializeAnyPattern()
if err != nil {
log.Log.Error(err, "failed to deserialize anyPattern, expect type array")
2020-11-13 16:25:51 -08:00
return false
}
for _, pattern := range anyPatterns {
patternMap, ok := pattern.(map[string]interface{})
if ok {
ret := checkMetadata(patternMap)
if ret == false {
return ret
}
}
}
}
return true
}
2020-02-26 16:08:56 +05:30
func ruleOnlyDealsWithResourceMetaData(rule kyverno.Rule) bool {
overlayMap, _ := rule.Mutation.Overlay.(map[string]interface{})
for k := range overlayMap {
if k != "metadata" {
return false
}
}
for _, patch := range rule.Mutation.Patches {
if !strings.HasPrefix(patch.Path, "/metadata") {
return false
}
}
patternMap, _ := rule.Validation.Pattern.(map[string]interface{})
for k := range patternMap {
if k != "metadata" {
return false
}
}
2020-11-13 16:25:51 -08:00
anyPatterns, err := rule.Validation.DeserializeAnyPattern()
if err != nil {
log.Log.Error(err, "failed to deserialize anyPattern, expect type array")
2020-11-13 16:25:51 -08:00
return false
}
for _, pattern := range anyPatterns {
2020-02-26 16:08:56 +05:30
patternMap, _ := pattern.(map[string]interface{})
for k := range patternMap {
if k != "metadata" {
return false
}
}
}
return true
}
2019-10-21 14:22:31 -07:00
func validateResources(rule kyverno.Rule) (string, error) {
2019-12-04 18:50:51 -08:00
// validate userInfo in match and exclude
if path, err := validateUserInfo(rule); err != nil {
return fmt.Sprintf("resources.%s", path), err
}
adding any/all under match and exclude blocks (#2130) * intial commit Signed-off-by: RinkiyaKeDad <arshsharma461@gmail.com> * update types Signed-off-by: RinkiyaKeDad <arshsharma461@gmail.com> * updated all type Signed-off-by: RinkiyaKeDad <arshsharma461@gmail.com> * extract to single struct Signed-off-by: RinkiyaKeDad <arshsharma461@gmail.com> * updated match resource description function Signed-off-by: RinkiyaKeDad <arshsharma461@gmail.com> * minor test working Signed-off-by: RinkiyaKeDad <arshsharma461@gmail.com> * match resources test is working Signed-off-by: RinkiyaKeDad <arshsharma461@gmail.com> * exclude resources test is working Signed-off-by: RinkiyaKeDad <arshsharma461@gmail.com> * changed double negetive in logic Signed-off-by: RinkiyaKeDad <arshsharma461@gmail.com> * yamls updated and added validation and cache loops Signed-off-by: RinkiyaKeDad <arshsharma461@gmail.com> * match exclude working but need to fix matchExcludeConflict function Signed-off-by: RinkiyaKeDad <arshsharma461@gmail.com> * restored doMatchAndExcludeConflict function Signed-off-by: RinkiyaKeDad <arshsharma461@gmail.com> * rewrote the matchExcludeConflictFunction Signed-off-by: RinkiyaKeDad <arshsharma461@gmail.com> * finalizing completed till utils_test.go Signed-off-by: RinkiyaKeDad <arshsharma461@gmail.com> * ready for review complete Signed-off-by: RinkiyaKeDad <arshsharma461@gmail.com> * update yamls Signed-off-by: RinkiyaKeDad <arshsharma461@gmail.com> * one more merge conflict solved Signed-off-by: RinkiyaKeDad <arshsharma461@gmail.com> * regenerates YAMLs Signed-off-by: RinkiyaKeDad <arshsharma461@gmail.com> * possible fix for failing tests Signed-off-by: RinkiyaKeDad <arshsharma461@gmail.com> * removed duplicate any/all logic and added a test, (rest refacotring is in progress) Signed-off-by: RinkiyaKeDad <arshsharma461@gmail.com> * cache test is working Signed-off-by: RinkiyaKeDad <arshsharma461@gmail.com> * improved cache test and it is working Signed-off-by: RinkiyaKeDad <arshsharma461@gmail.com> * added check for mutate and generate policies too Signed-off-by: RinkiyaKeDad <arshsharma461@gmail.com> * cleaned doesResourceMatchConditionBlock logic but validation still has code from attempt to combine the all block Signed-off-by: RinkiyaKeDad <arshsharma461@gmail.com> * reverted validate.go to older logic Signed-off-by: RinkiyaKeDad <arshsharma461@gmail.com> * removed commented code Signed-off-by: RinkiyaKeDad <arshsharma461@gmail.com> * removed extra comments Signed-off-by: RinkiyaKeDad <arshsharma461@gmail.com>
2021-07-29 01:29:53 +05:30
if (len(rule.MatchResources.Any) > 0 || len(rule.MatchResources.All) > 0) && !reflect.DeepEqual(rule.MatchResources.ResourceDescription, kyverno.ResourceDescription{}) {
return "match.", fmt.Errorf("Can't specify any/all together with match resources")
}
if (len(rule.ExcludeResources.Any) > 0 || len(rule.ExcludeResources.All) > 0) && !reflect.DeepEqual(rule.ExcludeResources.ResourceDescription, kyverno.ResourceDescription{}) {
return "exclude.", fmt.Errorf("Can't specify any/all together with exclude resources")
}
adding any/all under match and exclude blocks (#2130) * intial commit Signed-off-by: RinkiyaKeDad <arshsharma461@gmail.com> * update types Signed-off-by: RinkiyaKeDad <arshsharma461@gmail.com> * updated all type Signed-off-by: RinkiyaKeDad <arshsharma461@gmail.com> * extract to single struct Signed-off-by: RinkiyaKeDad <arshsharma461@gmail.com> * updated match resource description function Signed-off-by: RinkiyaKeDad <arshsharma461@gmail.com> * minor test working Signed-off-by: RinkiyaKeDad <arshsharma461@gmail.com> * match resources test is working Signed-off-by: RinkiyaKeDad <arshsharma461@gmail.com> * exclude resources test is working Signed-off-by: RinkiyaKeDad <arshsharma461@gmail.com> * changed double negetive in logic Signed-off-by: RinkiyaKeDad <arshsharma461@gmail.com> * yamls updated and added validation and cache loops Signed-off-by: RinkiyaKeDad <arshsharma461@gmail.com> * match exclude working but need to fix matchExcludeConflict function Signed-off-by: RinkiyaKeDad <arshsharma461@gmail.com> * restored doMatchAndExcludeConflict function Signed-off-by: RinkiyaKeDad <arshsharma461@gmail.com> * rewrote the matchExcludeConflictFunction Signed-off-by: RinkiyaKeDad <arshsharma461@gmail.com> * finalizing completed till utils_test.go Signed-off-by: RinkiyaKeDad <arshsharma461@gmail.com> * ready for review complete Signed-off-by: RinkiyaKeDad <arshsharma461@gmail.com> * update yamls Signed-off-by: RinkiyaKeDad <arshsharma461@gmail.com> * one more merge conflict solved Signed-off-by: RinkiyaKeDad <arshsharma461@gmail.com> * regenerates YAMLs Signed-off-by: RinkiyaKeDad <arshsharma461@gmail.com> * possible fix for failing tests Signed-off-by: RinkiyaKeDad <arshsharma461@gmail.com> * removed duplicate any/all logic and added a test, (rest refacotring is in progress) Signed-off-by: RinkiyaKeDad <arshsharma461@gmail.com> * cache test is working Signed-off-by: RinkiyaKeDad <arshsharma461@gmail.com> * improved cache test and it is working Signed-off-by: RinkiyaKeDad <arshsharma461@gmail.com> * added check for mutate and generate policies too Signed-off-by: RinkiyaKeDad <arshsharma461@gmail.com> * cleaned doesResourceMatchConditionBlock logic but validation still has code from attempt to combine the all block Signed-off-by: RinkiyaKeDad <arshsharma461@gmail.com> * reverted validate.go to older logic Signed-off-by: RinkiyaKeDad <arshsharma461@gmail.com> * removed commented code Signed-off-by: RinkiyaKeDad <arshsharma461@gmail.com> * removed extra comments Signed-off-by: RinkiyaKeDad <arshsharma461@gmail.com>
2021-07-29 01:29:53 +05:30
if len(rule.MatchResources.Any) > 0 && len(rule.MatchResources.All) > 0 {
return "match.", fmt.Errorf("Can't specify any and all together.")
}
if len(rule.ExcludeResources.Any) > 0 && len(rule.ExcludeResources.All) > 0 {
return "match.", fmt.Errorf("Can't specify any and all together.")
}
if len(rule.MatchResources.Any) > 0 {
for _, rmr := range rule.MatchResources.Any {
// matched resources
if path, err := validateMatchedResourceDescription(rmr.ResourceDescription); err != nil {
return fmt.Sprintf("match.resources.%s", path), err
}
}
} else if len(rule.MatchResources.All) > 0 {
for _, rmr := range rule.MatchResources.All {
// matched resources
if path, err := validateMatchedResourceDescription(rmr.ResourceDescription); err != nil {
return fmt.Sprintf("match.resources.%s", path), err
}
}
} else {
// matched resources
if path, err := validateMatchedResourceDescription(rule.MatchResources.ResourceDescription); err != nil {
return fmt.Sprintf("match.resources.%s", path), err
}
}
if len(rule.ExcludeResources.Any) > 0 {
for _, rmr := range rule.ExcludeResources.Any {
// exclude resources
if path, err := validateExcludeResourceDescription(rmr.ResourceDescription); err != nil {
return fmt.Sprintf("exclude.resources.%s", path), err
}
}
} else if len(rule.ExcludeResources.All) > 0 {
for _, rmr := range rule.ExcludeResources.All {
// exclude resources
if path, err := validateExcludeResourceDescription(rmr.ResourceDescription); err != nil {
return fmt.Sprintf("exclude.resources.%s", path), err
}
}
} else {
// exclude resources
if path, err := validateExcludeResourceDescription(rule.ExcludeResources.ResourceDescription); err != nil {
return fmt.Sprintf("exclude.resources.%s", path), err
}
}
//validating the values present under validate.preconditions, if they exist
if rule.AnyAllConditions != nil {
if path, err := validateConditions(rule.AnyAllConditions, "preconditions"); err != nil {
return fmt.Sprintf("validate.%s", path), err
}
}
//validating the values present under validate.conditions, if they exist
if rule.Validation.Deny != nil && rule.Validation.Deny.AnyAllConditions != nil {
if path, err := validateConditions(rule.Validation.Deny.AnyAllConditions, "conditions"); err != nil {
return fmt.Sprintf("validate.deny.%s", path), err
}
}
return "", nil
}
// validateConditions validates all the 'conditions' or 'preconditions' of a rule depending on the corresponding 'condition.key'.
// As of now, it is validating the 'value' field whether it contains the only allowed set of values or not when 'condition.key' is {{request.operation}}
// this is backwards compatible i.e. conditions can be provided in the old manner as well i.e. without 'any' or 'all'
func validateConditions(conditions apiextensions.JSON, schemaKey string) (string, error) {
// Conditions can only exist under some specific keys of the policy schema
allowedSchemaKeys := map[string]bool{
"preconditions": true,
"conditions": true,
}
if !allowedSchemaKeys[schemaKey] {
return fmt.Sprintf(schemaKey), fmt.Errorf("wrong schema key found for validating the conditions. Conditions can only occur under one of ['preconditions', 'conditions'] keys in the policy schema")
}
// conditions are currently in the form of []interface{}
kyvernoConditions, err := utils.ApiextensionsJsonToKyvernoConditions(conditions)
if err != nil {
return fmt.Sprintf("%s", schemaKey), err
}
switch typedConditions := kyvernoConditions.(type) {
case kyverno.AnyAllConditions:
// validating the conditions under 'any', if there are any
if !reflect.DeepEqual(typedConditions, kyverno.AnyAllConditions{}) && typedConditions.AnyConditions != nil {
for i, condition := range typedConditions.AnyConditions {
if path, err := validateConditionValues(condition); err != nil {
return fmt.Sprintf("%s.any[%d].%s", schemaKey, i, path), err
}
}
}
// validating the conditions under 'all', if there are any
if !reflect.DeepEqual(typedConditions, kyverno.AnyAllConditions{}) && typedConditions.AllConditions != nil {
for i, condition := range typedConditions.AllConditions {
if path, err := validateConditionValues(condition); err != nil {
return fmt.Sprintf("%s.all[%d].%s", schemaKey, i, path), err
}
}
}
case []kyverno.Condition: // backwards compatibility
for i, condition := range typedConditions {
if path, err := validateConditionValues(condition); err != nil {
return fmt.Sprintf("%s[%d].%s", schemaKey, i, path), err
}
}
}
return "", nil
}
// validateConditionValues validates whether all the values under the 'value' field of a 'conditions' field
// are apt with respect to the provided 'condition.key'
func validateConditionValues(c kyverno.Condition) (string, error) {
switch strings.ReplaceAll(c.Key.(string), " ", "") {
case "{{request.operation}}":
return validateConditionValuesKeyRequestOperation(c)
default:
return "", nil
}
}
// validateConditionValuesKeyRequestOperation validates whether all the values under the 'value' field of a 'conditions' field
// are one of ["CREATE", "UPDATE", "DELETE", "CONNECT"] when 'condition.key' is {{request.operation}}
func validateConditionValuesKeyRequestOperation(c kyverno.Condition) (string, error) {
valuesAllowed := map[string]bool{
"CREATE": true,
"UPDATE": true,
"DELETE": true,
"CONNECT": true,
}
switch reflect.TypeOf(c.Value).Kind() {
case reflect.String:
valueStr := c.Value.(string)
// allow templatized values like {{ config-map.data.sample-key }}
// because they might be actually pointing to a rightful value in the provided config-map
if len(valueStr) >= 4 && valueStr[:2] == "{{" && valueStr[len(valueStr)-2:] == "}}" {
return "", nil
}
if !valuesAllowed[valueStr] {
return fmt.Sprintf("value: %s", c.Value.(string)), fmt.Errorf("unknown value '%s' found under the 'value' field. Only the following values are allowed: [CREATE, UPDATE, DELETE, CONNECT]", c.Value.(string))
}
case reflect.Slice:
values := reflect.ValueOf(c.Value)
for i := 0; i < values.Len(); i++ {
value := values.Index(i).Interface().(string)
if !valuesAllowed[value] {
return fmt.Sprintf("value[%d]", i), fmt.Errorf("unknown value '%s' found under the 'value' field. Only the following values are allowed: [CREATE, UPDATE, DELETE, CONNECT]", value)
}
}
default:
return fmt.Sprintf("value"), fmt.Errorf("'value' field found to be of the type %v. The provided value/values are expected to be either in the form of a string or list", reflect.TypeOf(c.Value).Kind())
}
2019-10-21 14:22:31 -07:00
return "", nil
}
// validateUniqueRuleName checks if the rule names are unique across a policy
2019-10-21 14:22:31 -07:00
func validateUniqueRuleName(p kyverno.ClusterPolicy) (string, error) {
var ruleNames []string
2019-10-21 14:22:31 -07:00
for i, rule := range p.Spec.Rules {
2020-12-15 15:21:39 -08:00
if utils.ContainsString(ruleNames, rule.Name) {
2019-10-21 14:22:31 -07:00
return fmt.Sprintf("rule[%d]", i), fmt.Errorf(`duplicate rule name: '%s'`, rule.Name)
}
ruleNames = append(ruleNames, rule.Name)
2019-10-03 14:47:50 -07:00
}
2019-10-21 14:22:31 -07:00
return "", nil
}
// validateRuleType checks only one type of rule is defined per rule
func validateRuleType(r kyverno.Rule) error {
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
ruleTypes := []bool{r.HasMutate(), r.HasValidate(), r.HasGenerate(), r.HasVerifyImages()}
operationCount := func() int {
count := 0
for _, v := range ruleTypes {
if v {
count++
}
}
return count
}()
if operationCount == 0 {
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
return fmt.Errorf("no operation defined in the rule '%s'.(supported operations: mutate,validate,generate,verifyImages)", r.Name)
} else if operationCount != 1 {
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
return fmt.Errorf("multiple operations defined in the rule '%s', only one operation (mutate,validate,generate,verifyImages) is allowed per rule", r.Name)
}
return nil
}
Add Policy Report (#1229) * add report in cli * policy report crd added * policy report added * configmap added * added jobs * added jobs * bug fixed * added logic for cli * common function added * sub command added for policy report * subcommand added for report * common package changed * configmap added * added logic for kyverno cli * added logic for jobs * added logic for jobs * added logic for jobs * added logic for cli * buf fix * cli changes * count bug fix * docs added for command * go fmt * refactor codebase * remove policy controller for policyreport * policy report removed * bug fixes * bug fixes * added job trigger if needed * job deletation logic added * build failed fix * fixed e2e test * remove hard coded variables * packages adde * improvment added in jobs sheduler * policy report yaml added * cronjob added * small fixes * remove background sync * documentation added for report command * remove extra log * small improvement * tested policy report * revert hardcoded changes * changes for demo * demo changes * resource aggrigation added * More changes * More changes * - resolve PR comments; - refactor jobs controller * set rbac for jobs * add clean up in job controller * add short names * remove application scope for policyreport * move job controller to policyreport * add report logic in command apply * - update policy report types; - upgrade k8s library; - update code gen * temporarily comment out code to pass CI build * generate / update policyreport to cluster * add unit test for CLI report * add test for apply - generate policy report * fix unit test * - remove job controller; - remove in-memory configmap; - clean up kustomize manifest * remove dependency * add reportRequest / clusterReportRequest * clean up policy report * generate report request * update crd clusterReportRequest * - update json tag of report summary; - update definition manifests; - fix dclient creation * aggregate reportRequest into policy report * fix unit tests * - update report summary to optional; - generate clusterPolicyReport; - remove reportRequests after merged to report * remove * generate reportRequest in kyverno namespace * update resource filter in helm chart * - rename reportRequest to reportChangeRequest; -rename clusterReportRequest to clusterReportChangeRequest * generate policy report in background scan * skip generating report change request if there's entry results * fix results entry removal when policy / rule gets deleted * rename apiversion from policy.kubernetes.io to policy.k8s.io * update summary.* to lower case * move reportChangeRequest to kyverno.io/v1alpha1 * remove policy report flag * fix report update * clean up policy violation CRD * remove violation CRD from manifest * clean up policy violation code - remove pvGenerator * change severity fields to lower case * update import library * set report category Co-authored-by: Yuvraj <yuvraj.yad001@gmail.com> Co-authored-by: Yuvraj <10830562+evalsocket@users.noreply.github.com> Co-authored-by: Jim Bugwadia <jim@nirmata.com>
2020-11-09 11:26:12 -08:00
func validateRuleContext(rule kyverno.Rule) error {
2020-10-14 17:39:45 -07:00
if rule.Context == nil || len(rule.Context) == 0 {
return nil
}
contextNames := make([]string, 0)
2020-10-14 17:39:45 -07:00
for _, entry := range rule.Context {
Add Policy Report (#1229) * add report in cli * policy report crd added * policy report added * configmap added * added jobs * added jobs * bug fixed * added logic for cli * common function added * sub command added for policy report * subcommand added for report * common package changed * configmap added * added logic for kyverno cli * added logic for jobs * added logic for jobs * added logic for jobs * added logic for cli * buf fix * cli changes * count bug fix * docs added for command * go fmt * refactor codebase * remove policy controller for policyreport * policy report removed * bug fixes * bug fixes * added job trigger if needed * job deletation logic added * build failed fix * fixed e2e test * remove hard coded variables * packages adde * improvment added in jobs sheduler * policy report yaml added * cronjob added * small fixes * remove background sync * documentation added for report command * remove extra log * small improvement * tested policy report * revert hardcoded changes * changes for demo * demo changes * resource aggrigation added * More changes * More changes * - resolve PR comments; - refactor jobs controller * set rbac for jobs * add clean up in job controller * add short names * remove application scope for policyreport * move job controller to policyreport * add report logic in command apply * - update policy report types; - upgrade k8s library; - update code gen * temporarily comment out code to pass CI build * generate / update policyreport to cluster * add unit test for CLI report * add test for apply - generate policy report * fix unit test * - remove job controller; - remove in-memory configmap; - clean up kustomize manifest * remove dependency * add reportRequest / clusterReportRequest * clean up policy report * generate report request * update crd clusterReportRequest * - update json tag of report summary; - update definition manifests; - fix dclient creation * aggregate reportRequest into policy report * fix unit tests * - update report summary to optional; - generate clusterPolicyReport; - remove reportRequests after merged to report * remove * generate reportRequest in kyverno namespace * update resource filter in helm chart * - rename reportRequest to reportChangeRequest; -rename clusterReportRequest to clusterReportChangeRequest * generate policy report in background scan * skip generating report change request if there's entry results * fix results entry removal when policy / rule gets deleted * rename apiversion from policy.kubernetes.io to policy.k8s.io * update summary.* to lower case * move reportChangeRequest to kyverno.io/v1alpha1 * remove policy report flag * fix report update * clean up policy violation CRD * remove violation CRD from manifest * clean up policy violation code - remove pvGenerator * change severity fields to lower case * update import library * set report category Co-authored-by: Yuvraj <yuvraj.yad001@gmail.com> Co-authored-by: Yuvraj <10830562+evalsocket@users.noreply.github.com> Co-authored-by: Jim Bugwadia <jim@nirmata.com>
2020-11-09 11:26:12 -08:00
if entry.Name == "" {
2020-10-14 17:39:45 -07:00
return fmt.Errorf("a name is required for context entries")
}
contextNames = append(contextNames, entry.Name)
api server lookups (#1514) * initial commit for api server lookups Signed-off-by: Jim Bugwadia <jim@nirmata.com> * initial commit for API server lookups Signed-off-by: Jim Bugwadia <jim@nirmata.com> * Enhancing dockerfiles (multi-stage) of kyverno components and adding non-root user to the docker images (#1495) * Dockerfile refactored Signed-off-by: Raj Babu Das <mail.rajdas@gmail.com> * Adding non-root commands to docker images and enhanced the dockerfiles Signed-off-by: Raj Babu Das <mail.rajdas@gmail.com> * changing base image to scratch Signed-off-by: Raj Babu Das <mail.rajdas@gmail.com> * Minor typo fix Signed-off-by: Raj Babu Das <mail.rajdas@gmail.com> * changing dockerfiles to use /etc/passwd to use non-root user' Signed-off-by: Raj Babu Das <mail.rajdas@gmail.com> * minor typo Signed-off-by: Raj Babu Das <mail.rajdas@gmail.com> * minor typo Signed-off-by: Raj Babu Das <mail.rajdas@gmail.com> Signed-off-by: Jim Bugwadia <jim@nirmata.com> * revert cli image name (#1507) Signed-off-by: Raj Babu Das <mail.rajdas@gmail.com> Signed-off-by: Jim Bugwadia <jim@nirmata.com> * Refactor resourceCache; Reduce throttling requests (background controller) (#1500) * skip sending API request for filtered resource * fix PR comment Signed-off-by: Shuting Zhao <shutting06@gmail.com> * fixes https://github.com/kyverno/kyverno/issues/1490 Signed-off-by: Shuting Zhao <shutting06@gmail.com> * fix bug - namespace is not returned properly Signed-off-by: Shuting Zhao <shutting06@gmail.com> * reduce throttling - list resource using lister * refactor resource cache * fix test Signed-off-by: Shuting Zhao <shutting06@gmail.com> * fix label selector Signed-off-by: Shuting Zhao <shutting06@gmail.com> * fix build failure Signed-off-by: Shuting Zhao <shutting06@gmail.com> Signed-off-by: Jim Bugwadia <jim@nirmata.com> * fix merge issues Signed-off-by: Jim Bugwadia <jim@nirmata.com> * fix unit test Signed-off-by: Jim Bugwadia <jim@nirmata.com> * add nil check for API client Signed-off-by: Jim Bugwadia <jim@nirmata.com> Co-authored-by: Raj Babu Das <mail.rajdas@gmail.com> Co-authored-by: shuting <shutting06@gmail.com>
2021-02-01 12:59:13 -08:00
var err error
2020-10-14 17:39:45 -07:00
if entry.ConfigMap != nil {
api server lookups (#1514) * initial commit for api server lookups Signed-off-by: Jim Bugwadia <jim@nirmata.com> * initial commit for API server lookups Signed-off-by: Jim Bugwadia <jim@nirmata.com> * Enhancing dockerfiles (multi-stage) of kyverno components and adding non-root user to the docker images (#1495) * Dockerfile refactored Signed-off-by: Raj Babu Das <mail.rajdas@gmail.com> * Adding non-root commands to docker images and enhanced the dockerfiles Signed-off-by: Raj Babu Das <mail.rajdas@gmail.com> * changing base image to scratch Signed-off-by: Raj Babu Das <mail.rajdas@gmail.com> * Minor typo fix Signed-off-by: Raj Babu Das <mail.rajdas@gmail.com> * changing dockerfiles to use /etc/passwd to use non-root user' Signed-off-by: Raj Babu Das <mail.rajdas@gmail.com> * minor typo Signed-off-by: Raj Babu Das <mail.rajdas@gmail.com> * minor typo Signed-off-by: Raj Babu Das <mail.rajdas@gmail.com> Signed-off-by: Jim Bugwadia <jim@nirmata.com> * revert cli image name (#1507) Signed-off-by: Raj Babu Das <mail.rajdas@gmail.com> Signed-off-by: Jim Bugwadia <jim@nirmata.com> * Refactor resourceCache; Reduce throttling requests (background controller) (#1500) * skip sending API request for filtered resource * fix PR comment Signed-off-by: Shuting Zhao <shutting06@gmail.com> * fixes https://github.com/kyverno/kyverno/issues/1490 Signed-off-by: Shuting Zhao <shutting06@gmail.com> * fix bug - namespace is not returned properly Signed-off-by: Shuting Zhao <shutting06@gmail.com> * reduce throttling - list resource using lister * refactor resource cache * fix test Signed-off-by: Shuting Zhao <shutting06@gmail.com> * fix label selector Signed-off-by: Shuting Zhao <shutting06@gmail.com> * fix build failure Signed-off-by: Shuting Zhao <shutting06@gmail.com> Signed-off-by: Jim Bugwadia <jim@nirmata.com> * fix merge issues Signed-off-by: Jim Bugwadia <jim@nirmata.com> * fix unit test Signed-off-by: Jim Bugwadia <jim@nirmata.com> * add nil check for API client Signed-off-by: Jim Bugwadia <jim@nirmata.com> Co-authored-by: Raj Babu Das <mail.rajdas@gmail.com> Co-authored-by: shuting <shutting06@gmail.com>
2021-02-01 12:59:13 -08:00
err = validateConfigMap(entry)
} else if entry.APICall != nil {
err = validateAPICall(entry)
} else {
return fmt.Errorf("a configMap or apiCall is required for context entries")
}
2020-10-14 17:39:45 -07:00
api server lookups (#1514) * initial commit for api server lookups Signed-off-by: Jim Bugwadia <jim@nirmata.com> * initial commit for API server lookups Signed-off-by: Jim Bugwadia <jim@nirmata.com> * Enhancing dockerfiles (multi-stage) of kyverno components and adding non-root user to the docker images (#1495) * Dockerfile refactored Signed-off-by: Raj Babu Das <mail.rajdas@gmail.com> * Adding non-root commands to docker images and enhanced the dockerfiles Signed-off-by: Raj Babu Das <mail.rajdas@gmail.com> * changing base image to scratch Signed-off-by: Raj Babu Das <mail.rajdas@gmail.com> * Minor typo fix Signed-off-by: Raj Babu Das <mail.rajdas@gmail.com> * changing dockerfiles to use /etc/passwd to use non-root user' Signed-off-by: Raj Babu Das <mail.rajdas@gmail.com> * minor typo Signed-off-by: Raj Babu Das <mail.rajdas@gmail.com> * minor typo Signed-off-by: Raj Babu Das <mail.rajdas@gmail.com> Signed-off-by: Jim Bugwadia <jim@nirmata.com> * revert cli image name (#1507) Signed-off-by: Raj Babu Das <mail.rajdas@gmail.com> Signed-off-by: Jim Bugwadia <jim@nirmata.com> * Refactor resourceCache; Reduce throttling requests (background controller) (#1500) * skip sending API request for filtered resource * fix PR comment Signed-off-by: Shuting Zhao <shutting06@gmail.com> * fixes https://github.com/kyverno/kyverno/issues/1490 Signed-off-by: Shuting Zhao <shutting06@gmail.com> * fix bug - namespace is not returned properly Signed-off-by: Shuting Zhao <shutting06@gmail.com> * reduce throttling - list resource using lister * refactor resource cache * fix test Signed-off-by: Shuting Zhao <shutting06@gmail.com> * fix label selector Signed-off-by: Shuting Zhao <shutting06@gmail.com> * fix build failure Signed-off-by: Shuting Zhao <shutting06@gmail.com> Signed-off-by: Jim Bugwadia <jim@nirmata.com> * fix merge issues Signed-off-by: Jim Bugwadia <jim@nirmata.com> * fix unit test Signed-off-by: Jim Bugwadia <jim@nirmata.com> * add nil check for API client Signed-off-by: Jim Bugwadia <jim@nirmata.com> Co-authored-by: Raj Babu Das <mail.rajdas@gmail.com> Co-authored-by: shuting <shutting06@gmail.com>
2021-02-01 12:59:13 -08:00
if err != nil {
return err
}
}
ruleBytes, _ := json.Marshal(rule)
ruleString := strings.ReplaceAll(string(ruleBytes), " ", "")
for _, contextName := range contextNames {
if !strings.Contains(ruleString, fmt.Sprintf("{{"+contextName)) && !strings.Contains(ruleString, fmt.Sprintf("{{\\\""+contextName)) {
return fmt.Errorf("context variable `%s` is not used in the policy", contextName)
}
}
api server lookups (#1514) * initial commit for api server lookups Signed-off-by: Jim Bugwadia <jim@nirmata.com> * initial commit for API server lookups Signed-off-by: Jim Bugwadia <jim@nirmata.com> * Enhancing dockerfiles (multi-stage) of kyverno components and adding non-root user to the docker images (#1495) * Dockerfile refactored Signed-off-by: Raj Babu Das <mail.rajdas@gmail.com> * Adding non-root commands to docker images and enhanced the dockerfiles Signed-off-by: Raj Babu Das <mail.rajdas@gmail.com> * changing base image to scratch Signed-off-by: Raj Babu Das <mail.rajdas@gmail.com> * Minor typo fix Signed-off-by: Raj Babu Das <mail.rajdas@gmail.com> * changing dockerfiles to use /etc/passwd to use non-root user' Signed-off-by: Raj Babu Das <mail.rajdas@gmail.com> * minor typo Signed-off-by: Raj Babu Das <mail.rajdas@gmail.com> * minor typo Signed-off-by: Raj Babu Das <mail.rajdas@gmail.com> Signed-off-by: Jim Bugwadia <jim@nirmata.com> * revert cli image name (#1507) Signed-off-by: Raj Babu Das <mail.rajdas@gmail.com> Signed-off-by: Jim Bugwadia <jim@nirmata.com> * Refactor resourceCache; Reduce throttling requests (background controller) (#1500) * skip sending API request for filtered resource * fix PR comment Signed-off-by: Shuting Zhao <shutting06@gmail.com> * fixes https://github.com/kyverno/kyverno/issues/1490 Signed-off-by: Shuting Zhao <shutting06@gmail.com> * fix bug - namespace is not returned properly Signed-off-by: Shuting Zhao <shutting06@gmail.com> * reduce throttling - list resource using lister * refactor resource cache * fix test Signed-off-by: Shuting Zhao <shutting06@gmail.com> * fix label selector Signed-off-by: Shuting Zhao <shutting06@gmail.com> * fix build failure Signed-off-by: Shuting Zhao <shutting06@gmail.com> Signed-off-by: Jim Bugwadia <jim@nirmata.com> * fix merge issues Signed-off-by: Jim Bugwadia <jim@nirmata.com> * fix unit test Signed-off-by: Jim Bugwadia <jim@nirmata.com> * add nil check for API client Signed-off-by: Jim Bugwadia <jim@nirmata.com> Co-authored-by: Raj Babu Das <mail.rajdas@gmail.com> Co-authored-by: shuting <shutting06@gmail.com>
2021-02-01 12:59:13 -08:00
return nil
}
func validateConfigMap(entry kyverno.ContextEntry) error {
if entry.ConfigMap == nil {
return fmt.Errorf("configMap is empty")
}
if entry.APICall != nil {
return fmt.Errorf("both configMap and apiCall are not allowed in a context entry")
}
if entry.ConfigMap.Name == "" {
return fmt.Errorf("a name is required for configMap context entry")
}
if entry.ConfigMap.Namespace == "" {
return fmt.Errorf("a namespace is required for configMap context entry")
}
return nil
}
func validateAPICall(entry kyverno.ContextEntry) error {
if entry.APICall == nil {
return fmt.Errorf("apiCall is empty")
}
if entry.ConfigMap != nil {
return fmt.Errorf("both configMap and apiCall are not allowed in a context entry")
}
// Replace all variables to prevent validation failing on variable keys.
urlPath := variables.ReplaceAllVars(entry.APICall.URLPath, func(s string) string { return "kyvernoapicallvariable" })
if _, err := engine.NewAPIPath(urlPath); err != nil {
api server lookups (#1514) * initial commit for api server lookups Signed-off-by: Jim Bugwadia <jim@nirmata.com> * initial commit for API server lookups Signed-off-by: Jim Bugwadia <jim@nirmata.com> * Enhancing dockerfiles (multi-stage) of kyverno components and adding non-root user to the docker images (#1495) * Dockerfile refactored Signed-off-by: Raj Babu Das <mail.rajdas@gmail.com> * Adding non-root commands to docker images and enhanced the dockerfiles Signed-off-by: Raj Babu Das <mail.rajdas@gmail.com> * changing base image to scratch Signed-off-by: Raj Babu Das <mail.rajdas@gmail.com> * Minor typo fix Signed-off-by: Raj Babu Das <mail.rajdas@gmail.com> * changing dockerfiles to use /etc/passwd to use non-root user' Signed-off-by: Raj Babu Das <mail.rajdas@gmail.com> * minor typo Signed-off-by: Raj Babu Das <mail.rajdas@gmail.com> * minor typo Signed-off-by: Raj Babu Das <mail.rajdas@gmail.com> Signed-off-by: Jim Bugwadia <jim@nirmata.com> * revert cli image name (#1507) Signed-off-by: Raj Babu Das <mail.rajdas@gmail.com> Signed-off-by: Jim Bugwadia <jim@nirmata.com> * Refactor resourceCache; Reduce throttling requests (background controller) (#1500) * skip sending API request for filtered resource * fix PR comment Signed-off-by: Shuting Zhao <shutting06@gmail.com> * fixes https://github.com/kyverno/kyverno/issues/1490 Signed-off-by: Shuting Zhao <shutting06@gmail.com> * fix bug - namespace is not returned properly Signed-off-by: Shuting Zhao <shutting06@gmail.com> * reduce throttling - list resource using lister * refactor resource cache * fix test Signed-off-by: Shuting Zhao <shutting06@gmail.com> * fix label selector Signed-off-by: Shuting Zhao <shutting06@gmail.com> * fix build failure Signed-off-by: Shuting Zhao <shutting06@gmail.com> Signed-off-by: Jim Bugwadia <jim@nirmata.com> * fix merge issues Signed-off-by: Jim Bugwadia <jim@nirmata.com> * fix unit test Signed-off-by: Jim Bugwadia <jim@nirmata.com> * add nil check for API client Signed-off-by: Jim Bugwadia <jim@nirmata.com> Co-authored-by: Raj Babu Das <mail.rajdas@gmail.com> Co-authored-by: shuting <shutting06@gmail.com>
2021-02-01 12:59:13 -08:00
return err
}
// If JMESPath contains variables, the validation will fail because it's not possible to infer which value
// will be inserted by the variable
// Skip validation if a variable is detected
jmesPath := variables.ReplaceAllVars(entry.APICall.JMESPath, func(s string) string { return "kyvernojmespathvariable" })
if !strings.Contains(jmesPath, "kyvernojmespathvariable") && entry.APICall.JMESPath != "" {
api server lookups (#1514) * initial commit for api server lookups Signed-off-by: Jim Bugwadia <jim@nirmata.com> * initial commit for API server lookups Signed-off-by: Jim Bugwadia <jim@nirmata.com> * Enhancing dockerfiles (multi-stage) of kyverno components and adding non-root user to the docker images (#1495) * Dockerfile refactored Signed-off-by: Raj Babu Das <mail.rajdas@gmail.com> * Adding non-root commands to docker images and enhanced the dockerfiles Signed-off-by: Raj Babu Das <mail.rajdas@gmail.com> * changing base image to scratch Signed-off-by: Raj Babu Das <mail.rajdas@gmail.com> * Minor typo fix Signed-off-by: Raj Babu Das <mail.rajdas@gmail.com> * changing dockerfiles to use /etc/passwd to use non-root user' Signed-off-by: Raj Babu Das <mail.rajdas@gmail.com> * minor typo Signed-off-by: Raj Babu Das <mail.rajdas@gmail.com> * minor typo Signed-off-by: Raj Babu Das <mail.rajdas@gmail.com> Signed-off-by: Jim Bugwadia <jim@nirmata.com> * revert cli image name (#1507) Signed-off-by: Raj Babu Das <mail.rajdas@gmail.com> Signed-off-by: Jim Bugwadia <jim@nirmata.com> * Refactor resourceCache; Reduce throttling requests (background controller) (#1500) * skip sending API request for filtered resource * fix PR comment Signed-off-by: Shuting Zhao <shutting06@gmail.com> * fixes https://github.com/kyverno/kyverno/issues/1490 Signed-off-by: Shuting Zhao <shutting06@gmail.com> * fix bug - namespace is not returned properly Signed-off-by: Shuting Zhao <shutting06@gmail.com> * reduce throttling - list resource using lister * refactor resource cache * fix test Signed-off-by: Shuting Zhao <shutting06@gmail.com> * fix label selector Signed-off-by: Shuting Zhao <shutting06@gmail.com> * fix build failure Signed-off-by: Shuting Zhao <shutting06@gmail.com> Signed-off-by: Jim Bugwadia <jim@nirmata.com> * fix merge issues Signed-off-by: Jim Bugwadia <jim@nirmata.com> * fix unit test Signed-off-by: Jim Bugwadia <jim@nirmata.com> * add nil check for API client Signed-off-by: Jim Bugwadia <jim@nirmata.com> Co-authored-by: Raj Babu Das <mail.rajdas@gmail.com> Co-authored-by: shuting <shutting06@gmail.com>
2021-02-01 12:59:13 -08:00
if _, err := jmespath.NewParser().Parse(entry.APICall.JMESPath); err != nil {
return fmt.Errorf("failed to parse JMESPath %s: %v", entry.APICall.JMESPath, err)
2020-10-14 17:39:45 -07:00
}
}
return nil
}
// validateResourceDescription checks if all necessary fields are present and have values. Also checks a Selector.
// field type is checked through openapi
// Returns error if
// - kinds is empty array in matched resource block, i.e. kinds: []
// - selector is invalid
2019-10-21 14:22:31 -07:00
func validateMatchedResourceDescription(rd kyverno.ResourceDescription) (string, error) {
if reflect.DeepEqual(rd, kyverno.ResourceDescription{}) {
2019-10-21 14:22:31 -07:00
return "", fmt.Errorf("match resources not specified")
}
if rd.Name != "" && len(rd.Names) > 0 {
return "", fmt.Errorf("both name and names can not be specified together")
}
2019-10-21 14:22:31 -07:00
if err := validateResourceDescription(rd); err != nil {
return "match", err
}
return "", nil
}
2019-12-04 18:50:51 -08:00
func validateUserInfo(rule kyverno.Rule) (string, error) {
if err := validateRoles(rule.MatchResources.Roles); err != nil {
return "match.roles", err
}
if err := validateSubjects(rule.MatchResources.Subjects); err != nil {
return "match.subjects", err
}
if err := validateRoles(rule.ExcludeResources.Roles); err != nil {
return "exclude.roles", err
}
if err := validateSubjects(rule.ExcludeResources.Subjects); err != nil {
return "exclude.subjects", err
}
return "", nil
}
// a role must in format namespace:name
func validateRoles(roles []string) error {
if len(roles) == 0 {
return nil
}
for _, r := range roles {
role := strings.Split(r, ":")
if len(role) != 2 {
return fmt.Errorf("invalid role %s, expect namespace:name", r)
}
}
return nil
}
2019-12-05 11:55:00 -08:00
// a namespace should be set in kind ServiceAccount of a subject
2019-12-04 18:50:51 -08:00
func validateSubjects(subjects []rbacv1.Subject) error {
if len(subjects) == 0 {
return nil
}
for _, subject := range subjects {
2019-12-05 11:55:00 -08:00
if subject.Kind == "ServiceAccount" {
2019-12-04 18:50:51 -08:00
if subject.Namespace == "" {
2019-12-05 11:57:34 -08:00
return fmt.Errorf("service account %s in subject expects a namespace", subject.Name)
2019-12-04 18:50:51 -08:00
}
}
}
return nil
}
2019-10-21 14:22:31 -07:00
func validateExcludeResourceDescription(rd kyverno.ResourceDescription) (string, error) {
if reflect.DeepEqual(rd, kyverno.ResourceDescription{}) {
// exclude is not mandatory
return "", nil
}
if rd.Name != "" && len(rd.Names) > 0 {
return "", fmt.Errorf("both name and names can not be specified together")
}
2019-10-21 14:22:31 -07:00
if err := validateResourceDescription(rd); err != nil {
return "exclude", err
}
return "", nil
2019-10-03 18:19:47 -07:00
}
// validateResourceDescription returns error if selector is invalid
// field type is checked through openapi
func validateResourceDescription(rd kyverno.ResourceDescription) error {
if rd.Selector != nil {
selector, err := metav1.LabelSelectorAsSelector(rd.Selector)
if err != nil {
return err
}
requirements, _ := selector.Requirements()
if len(requirements) == 0 {
return errors.New("the requirements are not specified in selector")
}
}
return nil
}
// checkClusterResourceInMatchAndExclude returns false if namespaced ClusterPolicy contains cluster wide resources in
// Match and Exclude block
func checkClusterResourceInMatchAndExclude(rule kyverno.Rule, clusterResources []string) error {
// Contains Namespaces in Match->ResourceDescription
if len(rule.MatchResources.ResourceDescription.Namespaces) > 0 {
return fmt.Errorf("namespaced cluster policy : field namespaces not allowed in match.resources")
}
// Contains Namespaces in Exclude->ResourceDescription
if len(rule.ExcludeResources.ResourceDescription.Namespaces) > 0 {
return fmt.Errorf("namespaced cluster policy : field namespaces not allowed in exclude.resources")
}
// Contains "Cluster Wide Resources" in Match->ResourceDescription->Kinds
for _, kind := range rule.MatchResources.ResourceDescription.Kinds {
for _, k := range clusterResources {
if kind == k {
return fmt.Errorf("namespaced policy : cluster type value '%s' not allowed in match.resources.kinds", kind)
}
}
}
// Contains "Cluster Wide Resources" in Exclude->ResourceDescription->Kinds
for _, kind := range rule.ExcludeResources.ResourceDescription.Kinds {
for _, k := range clusterResources {
if kind == k {
return fmt.Errorf("namespaced policy : cluster type value '%s' not allowed in exclude.resources.kinds", kind)
}
}
}
return nil
}
// jsonPatchOnPod checks if a rule applies JSON patches to Pod
func jsonPatchOnPod(rule kyverno.Rule) bool {
if !rule.HasMutate() {
return false
}
2020-12-15 15:21:39 -08:00
if utils.ContainsString(rule.MatchResources.Kinds, "Pod") && rule.Mutation.PatchesJSON6902 != "" {
return true
}
return false
}