1
0
Fork 0
mirror of https://github.com/kyverno/kyverno.git synced 2025-03-28 10:28:36 +00:00

resource description: support list of namespaces

This commit is contained in:
shivkumar dudhani 2019-08-17 09:45:57 -07:00
parent 63a5337c9b
commit 44db8b064e
11 changed files with 394 additions and 669 deletions

View file

@ -45,10 +45,10 @@ type ExcludeResources struct {
// ResourceDescription describes the resource to which the PolicyRule will be applied.
type ResourceDescription struct {
Kinds []string `json:"kinds"`
Name string `json:"name"`
Namespace string `json:"namespace,omitempty"`
Selector *metav1.LabelSelector `json:"selector"`
Kinds []string `json:"kinds"`
Name string `json:"name"`
Namespaces []string `json:"namespace,omitempty"`
Selector *metav1.LabelSelector `json:"selector"`
}
// Mutation describes the way how Mutating Webhook will react on resource creation

View file

@ -280,6 +280,11 @@ func (in *ResourceDescription) DeepCopyInto(out *ResourceDescription) {
*out = make([]string, len(*in))
copy(*out, *in)
}
if in.Namespaces != nil {
in, out := &in.Namespaces, &out.Namespaces
*out = make([]string, len(*in))
copy(*out, *in)
}
if in.Selector != nil {
in, out := &in.Selector, &out.Selector
*out = new(v1.LabelSelector)

View file

@ -1,105 +0,0 @@
package engine
import (
kyverno "github.com/nirmata/kyverno/pkg/api/kyverno/v1alpha1"
client "github.com/nirmata/kyverno/pkg/dclient"
"github.com/nirmata/kyverno/pkg/info"
"github.com/nirmata/kyverno/pkg/utils"
)
// ProcessExisting checks for mutation and validation violations of existing resources
func ProcessExisting(client *client.Client, policy *kyverno.Policy, filterK8Resources []utils.K8Resource) []info.PolicyInfo {
return nil
// glog.Infof("Applying policy %s on existing resources", policy.Name)
// // key uid
// resourceMap := ListResourcesThatApplyToPolicy(client, policy, filterK8Resources)
// policyInfos := []info.PolicyInfo{}
// // for the filtered resource apply policy
// for _, v := range resourceMap {
// policyInfo, err := applyPolicy(client, policy, v)
// if err != nil {
// glog.Errorf("unable to apply policy %s on resource %s/%s", policy.Name, v.Resource.GetName(), v.Resource.GetNamespace())
// glog.Error(err)
// continue
// }
// policyInfos = append(policyInfos, policyInfo)
// }
// return policyInfos
}
// func applyPolicy(client *client.Client, policy *kyverno.Policy, res resourceInfo) (info.PolicyInfo, error) {
// var policyInfo info.PolicyInfo
// glog.Infof("Applying policy %s with %d rules\n", policy.ObjectMeta.Name, len(policy.Spec.Rules))
// rawResource, err := res.Resource.MarshalJSON()
// if err != nil {
// return policyInfo, err
// }
// // Mutate
// mruleInfos, err := mutation(policy, rawResource, res.Gvk)
// policyInfo.AddRuleInfos(mruleInfos)
// if err != nil {
// return policyInfo, err
// }
// // Validation
// //TODO check by value or pointer
// vruleInfos, err := Validate(*policy, rawResource, *res.Gvk)
// if err != nil {
// return policyInfo, err
// }
// policyInfo.AddRuleInfos(vruleInfos)
// policyInfo = info.NewPolicyInfo(policy.Name, res.Gvk.Kind, res.Resource.GetName(), res.Resource.GetNamespace(), policy.Spec.ValidationFailureAction)
// if res.Gvk.Kind == "Namespace" {
// // Generation
// gruleInfos := Generate(client, policy, res.Resource)
// policyInfo.AddRuleInfos(gruleInfos)
// }
// return policyInfo, nil
// }
// func mutation(p *kyverno.Policy, rawResource []byte, gvk *metav1.GroupVersionKind) ([]*info.RuleInfo, error) {
// patches, ruleInfos := Mutate(*p, rawResource, *gvk)
// if len(ruleInfos) == 0 {
// // no rules were processed
// return nil, nil
// }
// // if there are any errors return
// for _, r := range ruleInfos {
// if !r.IsSuccessful() {
// return ruleInfos, nil
// }
// }
// // if there are no patches // for overlay
// if len(patches) == 0 {
// return ruleInfos, nil
// }
// // option 2: (original Resource + patch) compare with (original resource)
// mergePatches := JoinPatches(patches)
// // merge the patches
// patch, err := jsonpatch.DecodePatch(mergePatches)
// if err != nil {
// return nil, err
// }
// // apply the patches returned by mutate to the original resource
// patchedResource, err := patch.Apply(rawResource)
// if err != nil {
// return nil, err
// }
// // compare (original Resource + patch) vs (original resource)
// // to verify if they are equal
// ruleInfo := info.NewRuleInfo("over-all mutation", info.Mutation)
// if !jsonpatch.Equal(patchedResource, rawResource) {
// //resource does not match so there was a mutation rule violated
// // TODO : check the rule name "mutation rules"
// ruleInfo.Fail()
// ruleInfo.Add("resource does not satisfy mutation rules")
// } else {
// ruleInfo.Add("resource satisfys the mutation rule")
// }
// ruleInfos = append(ruleInfos, ruleInfo)
// return ruleInfos, nil
// }

View file

@ -31,11 +31,9 @@ func processOverlay(resourceUnstr unstructured.Unstructured, rule kyverno.Rule)
return nil, err
}
// resourceInfo := ParseResourceInfoFromObject(rawResource)
patches, err := processOverlayPatches(resource, rule.Mutation.Overlay)
if err != nil && strings.Contains(err.Error(), "Conditions are not met") {
glog.V(4).Infof("overlay pattern %s does not match resource %s/%s", rule.Mutation.Overlay, resourceUnstr.GetNamespace(), resourceUnstr.GetName())
// glog.Infof("Resource does not meet conditions in overlay pattern, resource=%s, rule=%s\n", resourceInfo, rule.Name)
return nil, nil
}

View file

@ -13,7 +13,7 @@ func patchOverlay(rule kyverno.Rule, rawResource []byte) ([][]byte, error) {
if err := json.Unmarshal(rawResource, &resource); err != nil {
return nil, err
}
//TODO: evaluate, Unmarshall called thrice
resourceInfo := ParseResourceInfoFromObject(rawResource)
patches, err := processOverlayPatches(resource, rule.Mutation.Overlay)
if err != nil && strings.Contains(err.Error(), "Conditions are not met") {

View file

@ -10,145 +10,13 @@ import (
"github.com/minio/minio/pkg/wildcard"
kyverno "github.com/nirmata/kyverno/pkg/api/kyverno/v1alpha1"
client "github.com/nirmata/kyverno/pkg/dclient"
"github.com/nirmata/kyverno/pkg/utils"
v1helper "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/labels"
)
//ListResourcesThatApplyToPolicy returns list of resources that are filtered by policy rules
func ListResourcesThatApplyToPolicy(client *client.Client, policy *kyverno.Policy, filterK8Resources []utils.K8Resource) map[string]resourceInfo {
// key uid
resourceMap := map[string]resourceInfo{}
for _, rule := range policy.Spec.Rules {
// Match
for _, k := range rule.MatchResources.Kinds {
namespaces := []string{}
if k == "Namespace" {
namespaces = []string{""}
} else {
if rule.MatchResources.Namespace != "" {
// if namespace is specified then we add the namespace
namespaces = append(namespaces, rule.MatchResources.Namespace)
} else {
// no namespace specified, refer to all namespaces
namespaces = getAllNamespaces(client)
}
// Check if exclude namespace is not clashing
namespaces = excludeNamespaces(namespaces, rule.ExcludeResources.Namespace)
}
// If kind is namespace then namespace is "", override
// Get resources in the namespace
for _, ns := range namespaces {
rMap := getResourcesPerNamespace(k, client, ns, rule, filterK8Resources)
mergeresources(resourceMap, rMap)
}
}
}
return resourceMap
}
func getResourcesPerNamespace(kind string, client *client.Client, namespace string, rule kyverno.Rule, filterK8Resources []utils.K8Resource) map[string]resourceInfo {
resourceMap := map[string]resourceInfo{}
// List resources
list, err := client.ListResource(kind, namespace, rule.MatchResources.Selector)
if err != nil {
glog.Errorf("unable to list resource for %s with label selector %s", kind, rule.MatchResources.Selector.String())
return nil
}
var selector labels.Selector
// exclude label selector
if rule.ExcludeResources.Selector != nil {
selector, err = v1helper.LabelSelectorAsSelector(rule.ExcludeResources.Selector)
if err != nil {
glog.Error(err)
}
}
for _, res := range list.Items {
// exclude label selectors
if selector != nil {
set := labels.Set(res.GetLabels())
if selector.Matches(set) {
// if matches
continue
}
}
var name string
// match
// name
// wild card matching
name = rule.MatchResources.Name
if name != "" {
// if does not match then we skip
if !wildcard.Match(name, res.GetName()) {
continue
}
}
// exclude
// name
// wild card matching
name = rule.ExcludeResources.Name
if name != "nil" {
// if matches then we skip
if wildcard.Match(name, res.GetName()) {
continue
}
}
gvk := res.GroupVersionKind()
ri := resourceInfo{Resource: res, Gvk: &metav1.GroupVersionKind{Group: gvk.Group,
Version: gvk.Version,
Kind: gvk.Kind}}
// Skip the filtered resources
if utils.SkipFilteredResources(gvk.Kind, res.GetNamespace(), res.GetName(), filterK8Resources) {
continue
}
resourceMap[string(res.GetUID())] = ri
}
return resourceMap
}
// merge b into a map
func mergeresources(a, b map[string]resourceInfo) {
for k, v := range b {
a[k] = v
}
}
func getAllNamespaces(client *client.Client) []string {
namespaces := []string{}
// get all namespaces
nsList, err := client.ListResource("Namespace", "", nil)
if err != nil {
glog.Error(err)
return namespaces
}
for _, ns := range nsList.Items {
namespaces = append(namespaces, ns.GetName())
}
return namespaces
}
func excludeNamespaces(namespaces []string, excludeNs string) []string {
if excludeNs == "" {
return namespaces
}
filteredNamespaces := []string{}
for _, n := range namespaces {
if n == excludeNs {
continue
}
filteredNamespaces = append(filteredNamespaces, n)
}
return filteredNamespaces
}
//MatchesResourceDescription checks if the resource matches resource desription of the rule or not
func MatchesResourceDescription(resource unstructured.Unstructured, rule kyverno.Rule) bool {
matches := rule.MatchResources.ResourceDescription
@ -158,8 +26,8 @@ func MatchesResourceDescription(resource unstructured.Unstructured, rule kyverno
return false
}
// meta := parseMetadataFromObject(resourceRaw)
name := resource.GetName()
namespace := resource.GetNamespace()
if matches.Name != "" {
@ -175,14 +43,18 @@ func MatchesResourceDescription(resource unstructured.Unstructured, rule kyverno
return false
}
}
// Matches
if matches.Namespace != "" && matches.Namespace != namespace {
// check if the resource namespace is defined in the list of namespaces for inclusion
if len(matches.Namespaces) > 0 && !utils.Contains(matches.Namespaces, namespace) {
return false
}
// Exclude
if exclude.Namespace != "" && exclude.Namespace == namespace {
// check if the resource namespace is defined in the list of namespace for exclusion
if len(exclude.Namespaces) > 0 && utils.Contains(exclude.Namespaces, namespace) {
return false
}
// Matches
if matches.Selector != nil {
selector, err := metav1.LabelSelectorAsSelector(matches.Selector)
@ -209,82 +81,74 @@ func MatchesResourceDescription(resource unstructured.Unstructured, rule kyverno
return true
}
// ResourceMeetsDescription checks requests kind, name and labels to fit the policy rule
func ResourceMeetsDescription(resourceRaw []byte, matches kyverno.ResourceDescription, exclude kyverno.ResourceDescription, gvk metav1.GroupVersionKind) bool {
if !findKind(matches.Kinds, gvk.Kind) {
return false
}
// // ResourceMeetsDescription checks requests kind, name and labels to fit the policy rule
// func ResourceMeetsDescription(resourceRaw []byte, matches kyverno.ResourceDescription, exclude kyverno.ResourceDescription, gvk metav1.GroupVersionKind) bool {
// if !findKind(matches.Kinds, gvk.Kind) {
// return false
// }
if resourceRaw != nil {
meta := parseMetadataFromObject(resourceRaw)
name := ParseNameFromObject(resourceRaw)
namespace := ParseNamespaceFromObject(resourceRaw)
// if resourceRaw != nil {
// meta := parseMetadataFromObject(resourceRaw)
// name := ParseNameFromObject(resourceRaw)
// namespace := ParseNamespaceFromObject(resourceRaw)
if matches.Name != "" {
// Matches
if !wildcard.Match(matches.Name, name) {
return false
}
}
// Exclude
// the resource name matches the exclude resource name then reject
if exclude.Name != "" {
if wildcard.Match(exclude.Name, name) {
return false
}
}
// Matches
if matches.Namespace != "" && matches.Namespace != namespace {
return false
}
// Exclude
if exclude.Namespace != "" && exclude.Namespace == namespace {
return false
}
// Matches
if matches.Selector != nil {
selector, err := metav1.LabelSelectorAsSelector(matches.Selector)
if err != nil {
glog.Error(err)
return false
}
if meta != nil {
labelMap := parseLabelsFromMetadata(meta)
if !selector.Matches(labelMap) {
return false
}
}
}
// Exclude
if exclude.Selector != nil {
selector, err := metav1.LabelSelectorAsSelector(exclude.Selector)
// if the label selector is incorrect, should be fail or
if err != nil {
glog.Error(err)
return false
}
// if matches.Name != "" {
// // Matches
// if !wildcard.Match(matches.Name, name) {
// return false
// }
// }
// // Exclude
// // the resource name matches the exclude resource name then reject
// if exclude.Name != "" {
// if wildcard.Match(exclude.Name, name) {
// return false
// }
// }
// // Matches
// // check if the resource namespace is defined in the list of namespaces for inclusion
// if len(matches.Namespaces) > 0 && !utils.Contains(matches.Namespaces, namespace) {
// return false
// }
// // Exclude
// // check if the resource namespace is defined in the list of namespace for exclusion
// if len(exclude.Namespaces) > 0 && utils.Contains(exclude.Namespaces, namespace) {
// return false
// }
// // Matches
// if matches.Selector != nil {
// selector, err := metav1.LabelSelectorAsSelector(matches.Selector)
// if err != nil {
// glog.Error(err)
// return false
// }
// if meta != nil {
// labelMap := parseLabelsFromMetadata(meta)
// if !selector.Matches(labelMap) {
// return false
// }
// }
// }
// // Exclude
// if exclude.Selector != nil {
// selector, err := metav1.LabelSelectorAsSelector(exclude.Selector)
// // if the label selector is incorrect, should be fail or
// if err != nil {
// glog.Error(err)
// return false
// }
if meta != nil {
labelMap := parseLabelsFromMetadata(meta)
if selector.Matches(labelMap) {
return false
}
}
}
// if meta != nil {
// labelMap := parseLabelsFromMetadata(meta)
// if selector.Matches(labelMap) {
// return false
// }
// }
// }
}
return true
}
func parseMetadataFromObject(bytes []byte) map[string]interface{} {
var objectJSON map[string]interface{}
json.Unmarshal(bytes, &objectJSON)
meta, ok := objectJSON["metadata"].(map[string]interface{})
if !ok {
return nil
}
return meta
}
// }
// return true
// }
// ParseResourceInfoFromObject get kind/namepace/name from resource
func ParseResourceInfoFromObject(rawResource []byte) string {
@ -303,18 +167,6 @@ func ParseKindFromObject(bytes []byte) string {
return objectJSON["kind"].(string)
}
func parseLabelsFromMetadata(meta map[string]interface{}) labels.Set {
if interfaceMap, ok := meta["labels"].(map[string]interface{}); ok {
labelMap := make(labels.Set, len(interfaceMap))
for key, value := range interfaceMap {
labelMap[key] = value.(string)
}
return labelMap
}
return nil
}
//ParseNameFromObject extracts resource name from JSON obj
func ParseNameFromObject(bytes []byte) string {
var objectJSON map[string]interface{}
@ -354,15 +206,6 @@ func ParseNamespaceFromObject(bytes []byte) string {
return ""
}
// ParseRegexPolicyResourceName returns true if policyResourceName is a regexp
func ParseRegexPolicyResourceName(policyResourceName string) (string, bool) {
regex := strings.Split(policyResourceName, "regex:")
if len(regex) == 1 {
return regex[0], false
}
return strings.Trim(regex[1], " "), true
}
func getAnchorsFromMap(anchorsMap map[string]interface{}) map[string]interface{} {
result := make(map[string]interface{})
@ -512,8 +355,3 @@ func convertToFloat(value interface{}) (float64, error) {
return 0, fmt.Errorf("Could not convert %T to float64", value)
}
}
type resourceInfo struct {
Resource unstructured.Unstructured
Gvk *metav1.GroupVersionKind
}

View file

@ -3,341 +3,339 @@ package engine
import (
"testing"
types "github.com/nirmata/kyverno/pkg/apis/policy/v1alpha1"
"gotest.tools/assert"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
func TestResourceMeetsDescription_Kind(t *testing.T) {
resourceName := "test-config-map"
resourceDescription := types.ResourceDescription{
Kinds: []string{"ConfigMap"},
Name: &resourceName,
Selector: &metav1.LabelSelector{
MatchLabels: nil,
MatchExpressions: nil,
},
}
excludeResourcesResourceDesc := types.ResourceDescription{}
groupVersionKind := metav1.GroupVersionKind{Kind: "ConfigMap"}
// func TestResourceMeetsDescription_Kind(t *testing.T) {
// resourceName := "test-config-map"
// resourceDescription := types.ResourceDescription{
// Kinds: []string{"ConfigMap"},
// Name: &resourceName,
// Selector: &metav1.LabelSelector{
// MatchLabels: nil,
// MatchExpressions: nil,
// },
// }
// excludeResourcesResourceDesc := types.ResourceDescription{}
// groupVersionKind := metav1.GroupVersionKind{Kind: "ConfigMap"}
rawResource := []byte(`{
"metadata":{
"name":"test-config-map",
"namespace":"default",
"creationTimestamp":null,
"labels":{
"label1":"test1",
"label2":"test2"
}
}
}`)
// rawResource := []byte(`{
// "metadata":{
// "name":"test-config-map",
// "namespace":"default",
// "creationTimestamp":null,
// "labels":{
// "label1":"test1",
// "label2":"test2"
// }
// }
// }`)
assert.Assert(t, ResourceMeetsDescription(rawResource, resourceDescription, excludeResourcesResourceDesc, groupVersionKind))
resourceDescription.Kinds[0] = "Deployment"
assert.Assert(t, false == ResourceMeetsDescription(rawResource, resourceDescription, excludeResourcesResourceDesc, groupVersionKind))
resourceDescription.Kinds[0] = "ConfigMap"
groupVersionKind.Kind = "Deployment"
assert.Assert(t, false == ResourceMeetsDescription(rawResource, resourceDescription, excludeResourcesResourceDesc, groupVersionKind))
}
// assert.Assert(t, ResourceMeetsDescription(rawResource, resourceDescription, excludeResourcesResourceDesc, groupVersionKind))
// resourceDescription.Kinds[0] = "Deployment"
// assert.Assert(t, false == ResourceMeetsDescription(rawResource, resourceDescription, excludeResourcesResourceDesc, groupVersionKind))
// resourceDescription.Kinds[0] = "ConfigMap"
// groupVersionKind.Kind = "Deployment"
// assert.Assert(t, false == ResourceMeetsDescription(rawResource, resourceDescription, excludeResourcesResourceDesc, groupVersionKind))
// }
func TestResourceMeetsDescription_Name(t *testing.T) {
resourceName := "test-config-map"
resourceDescription := types.ResourceDescription{
Kinds: []string{"ConfigMap"},
Name: &resourceName,
Selector: &metav1.LabelSelector{
MatchLabels: nil,
MatchExpressions: nil,
},
}
excludeResourcesResourceDesc := types.ResourceDescription{}
// func TestResourceMeetsDescription_Name(t *testing.T) {
// resourceName := "test-config-map"
// resourceDescription := types.ResourceDescription{
// Kinds: []string{"ConfigMap"},
// Name: &resourceName,
// Selector: &metav1.LabelSelector{
// MatchLabels: nil,
// MatchExpressions: nil,
// },
// }
// excludeResourcesResourceDesc := types.ResourceDescription{}
groupVersionKind := metav1.GroupVersionKind{Kind: "ConfigMap"}
// groupVersionKind := metav1.GroupVersionKind{Kind: "ConfigMap"}
rawResource := []byte(`{
"metadata":{
"name":"test-config-map",
"namespace":"default",
"creationTimestamp":null,
"labels":{
"label1":"test1",
"label2":"test2"
}
}
}`)
// rawResource := []byte(`{
// "metadata":{
// "name":"test-config-map",
// "namespace":"default",
// "creationTimestamp":null,
// "labels":{
// "label1":"test1",
// "label2":"test2"
// }
// }
// }`)
assert.Assert(t, ResourceMeetsDescription(rawResource, resourceDescription, excludeResourcesResourceDesc, groupVersionKind))
resourceName = "test-config-map-new"
assert.Assert(t, false == ResourceMeetsDescription(rawResource, resourceDescription, excludeResourcesResourceDesc, groupVersionKind))
// assert.Assert(t, ResourceMeetsDescription(rawResource, resourceDescription, excludeResourcesResourceDesc, groupVersionKind))
// resourceName = "test-config-map-new"
// assert.Assert(t, false == ResourceMeetsDescription(rawResource, resourceDescription, excludeResourcesResourceDesc, groupVersionKind))
rawResource = []byte(`{
"metadata":{
"name":"test-config-map-new",
"namespace":"default",
"creationTimestamp":null,
"labels":{
"label1":"test1",
"label2":"test2"
}
}
}`)
assert.Assert(t, ResourceMeetsDescription(rawResource, resourceDescription, excludeResourcesResourceDesc, groupVersionKind))
// rawResource = []byte(`{
// "metadata":{
// "name":"test-config-map-new",
// "namespace":"default",
// "creationTimestamp":null,
// "labels":{
// "label1":"test1",
// "label2":"test2"
// }
// }
// }`)
// assert.Assert(t, ResourceMeetsDescription(rawResource, resourceDescription, excludeResourcesResourceDesc, groupVersionKind))
rawResource = []byte(`{
"metadata":{
"name":"",
"namespace":"default",
"creationTimestamp":null,
"labels":{
"label1":"test1",
"label2":"test2"
}
}
}`)
assert.Assert(t, false == ResourceMeetsDescription(rawResource, resourceDescription, excludeResourcesResourceDesc, groupVersionKind))
}
// rawResource = []byte(`{
// "metadata":{
// "name":"",
// "namespace":"default",
// "creationTimestamp":null,
// "labels":{
// "label1":"test1",
// "label2":"test2"
// }
// }
// }`)
// assert.Assert(t, false == ResourceMeetsDescription(rawResource, resourceDescription, excludeResourcesResourceDesc, groupVersionKind))
// }
func TestResourceMeetsDescription_MatchExpressions(t *testing.T) {
resourceName := "test-config-map"
resourceDescription := types.ResourceDescription{
Kinds: []string{"ConfigMap"},
Name: &resourceName,
Selector: &metav1.LabelSelector{
MatchLabels: nil,
MatchExpressions: []metav1.LabelSelectorRequirement{
metav1.LabelSelectorRequirement{
Key: "label2",
Operator: "NotIn",
Values: []string{
"sometest1",
},
},
metav1.LabelSelectorRequirement{
Key: "label1",
Operator: "In",
Values: []string{
"test1",
"test8",
"test201",
},
},
metav1.LabelSelectorRequirement{
Key: "label3",
Operator: "DoesNotExist",
Values: nil,
},
metav1.LabelSelectorRequirement{
Key: "label2",
Operator: "In",
Values: []string{
"test2",
},
},
},
},
}
excludeResourcesResourceDesc := types.ResourceDescription{}
// func TestResourceMeetsDescription_MatchExpressions(t *testing.T) {
// resourceName := "test-config-map"
// resourceDescription := types.ResourceDescription{
// Kinds: []string{"ConfigMap"},
// Name: &resourceName,
// Selector: &metav1.LabelSelector{
// MatchLabels: nil,
// MatchExpressions: []metav1.LabelSelectorRequirement{
// metav1.LabelSelectorRequirement{
// Key: "label2",
// Operator: "NotIn",
// Values: []string{
// "sometest1",
// },
// },
// metav1.LabelSelectorRequirement{
// Key: "label1",
// Operator: "In",
// Values: []string{
// "test1",
// "test8",
// "test201",
// },
// },
// metav1.LabelSelectorRequirement{
// Key: "label3",
// Operator: "DoesNotExist",
// Values: nil,
// },
// metav1.LabelSelectorRequirement{
// Key: "label2",
// Operator: "In",
// Values: []string{
// "test2",
// },
// },
// },
// },
// }
// excludeResourcesResourceDesc := types.ResourceDescription{}
groupVersionKind := metav1.GroupVersionKind{Kind: "ConfigMap"}
rawResource := []byte(`{
"metadata":{
"name":"test-config-map",
"namespace":"default",
"creationTimestamp":null,
"labels":{
"label1":"test1",
"label2":"test2"
}
}
}`)
// groupVersionKind := metav1.GroupVersionKind{Kind: "ConfigMap"}
// rawResource := []byte(`{
// "metadata":{
// "name":"test-config-map",
// "namespace":"default",
// "creationTimestamp":null,
// "labels":{
// "label1":"test1",
// "label2":"test2"
// }
// }
// }`)
assert.Assert(t, ResourceMeetsDescription(rawResource, resourceDescription, excludeResourcesResourceDesc, groupVersionKind))
// assert.Assert(t, ResourceMeetsDescription(rawResource, resourceDescription, excludeResourcesResourceDesc, groupVersionKind))
rawResource = []byte(`{
"metadata":{
"name":"test-config-map",
"namespace":"default",
"creationTimestamp":null,
"labels":{
"label1":"test1234567890",
"label2":"test2"
}
}
}`)
// rawResource = []byte(`{
// "metadata":{
// "name":"test-config-map",
// "namespace":"default",
// "creationTimestamp":null,
// "labels":{
// "label1":"test1234567890",
// "label2":"test2"
// }
// }
// }`)
assert.Assert(t, false == ResourceMeetsDescription(rawResource, resourceDescription, excludeResourcesResourceDesc, groupVersionKind))
}
// assert.Assert(t, false == ResourceMeetsDescription(rawResource, resourceDescription, excludeResourcesResourceDesc, groupVersionKind))
// }
func TestResourceMeetsDescription_MatchLabels(t *testing.T) {
resourceName := "test-config-map"
resourceDescription := types.ResourceDescription{
Kinds: []string{"ConfigMap"},
Name: &resourceName,
Selector: &metav1.LabelSelector{
MatchLabels: map[string]string{
"label1": "test1",
"label2": "test2",
},
MatchExpressions: nil,
},
}
groupVersionKind := metav1.GroupVersionKind{Kind: "ConfigMap"}
excludeResourcesResourceDesc := types.ResourceDescription{}
// func TestResourceMeetsDescription_MatchLabels(t *testing.T) {
// resourceName := "test-config-map"
// resourceDescription := types.ResourceDescription{
// Kinds: []string{"ConfigMap"},
// Name: &resourceName,
// Selector: &metav1.LabelSelector{
// MatchLabels: map[string]string{
// "label1": "test1",
// "label2": "test2",
// },
// MatchExpressions: nil,
// },
// }
// groupVersionKind := metav1.GroupVersionKind{Kind: "ConfigMap"}
// excludeResourcesResourceDesc := types.ResourceDescription{}
rawResource := []byte(`{
"metadata":{
"name":"test-config-map",
"namespace":"default",
"creationTimestamp":null,
"labels":{
"label1":"test1",
"label2":"test2"
}
}
}`)
assert.Assert(t, ResourceMeetsDescription(rawResource, resourceDescription, excludeResourcesResourceDesc, groupVersionKind))
// rawResource := []byte(`{
// "metadata":{
// "name":"test-config-map",
// "namespace":"default",
// "creationTimestamp":null,
// "labels":{
// "label1":"test1",
// "label2":"test2"
// }
// }
// }`)
// assert.Assert(t, ResourceMeetsDescription(rawResource, resourceDescription, excludeResourcesResourceDesc, groupVersionKind))
rawResource = []byte(`{
"metadata":{
"name":"test-config-map",
"namespace":"default",
"creationTimestamp":null,
"labels":{
"label3":"test1",
"label2":"test2"
}
}
}`)
assert.Assert(t, false == ResourceMeetsDescription(rawResource, resourceDescription, excludeResourcesResourceDesc, groupVersionKind))
// rawResource = []byte(`{
// "metadata":{
// "name":"test-config-map",
// "namespace":"default",
// "creationTimestamp":null,
// "labels":{
// "label3":"test1",
// "label2":"test2"
// }
// }
// }`)
// assert.Assert(t, false == ResourceMeetsDescription(rawResource, resourceDescription, excludeResourcesResourceDesc, groupVersionKind))
resourceDescription = types.ResourceDescription{
Kinds: []string{"ConfigMap"},
Name: &resourceName,
Selector: &metav1.LabelSelector{
MatchLabels: map[string]string{
"label3": "test1",
"label2": "test2",
},
MatchExpressions: nil,
},
}
// resourceDescription = types.ResourceDescription{
// Kinds: []string{"ConfigMap"},
// Name: &resourceName,
// Selector: &metav1.LabelSelector{
// MatchLabels: map[string]string{
// "label3": "test1",
// "label2": "test2",
// },
// MatchExpressions: nil,
// },
// }
assert.Assert(t, ResourceMeetsDescription(rawResource, resourceDescription, excludeResourcesResourceDesc, groupVersionKind))
}
// assert.Assert(t, ResourceMeetsDescription(rawResource, resourceDescription, excludeResourcesResourceDesc, groupVersionKind))
// }
func TestResourceMeetsDescription_MatchLabelsAndMatchExpressions(t *testing.T) {
resourceName := "test-config-map"
resourceDescription := types.ResourceDescription{
Kinds: []string{"ConfigMap"},
Name: &resourceName,
Selector: &metav1.LabelSelector{
MatchLabels: map[string]string{
"label1": "test1",
},
MatchExpressions: []metav1.LabelSelectorRequirement{
metav1.LabelSelectorRequirement{
Key: "label2",
Operator: "In",
Values: []string{
"test2",
},
},
},
},
}
groupVersionKind := metav1.GroupVersionKind{Kind: "ConfigMap"}
excludeResourcesResourceDesc := types.ResourceDescription{}
// func TestResourceMeetsDescription_MatchLabelsAndMatchExpressions(t *testing.T) {
// resourceName := "test-config-map"
// resourceDescription := types.ResourceDescription{
// Kinds: []string{"ConfigMap"},
// Name: &resourceName,
// Selector: &metav1.LabelSelector{
// MatchLabels: map[string]string{
// "label1": "test1",
// },
// MatchExpressions: []metav1.LabelSelectorRequirement{
// metav1.LabelSelectorRequirement{
// Key: "label2",
// Operator: "In",
// Values: []string{
// "test2",
// },
// },
// },
// },
// }
// groupVersionKind := metav1.GroupVersionKind{Kind: "ConfigMap"}
// excludeResourcesResourceDesc := types.ResourceDescription{}
rawResource := []byte(`{
"metadata":{
"name":"test-config-map",
"namespace":"default",
"creationTimestamp":null,
"labels":{
"label1":"test1",
"label2":"test2"
}
}
}`)
// rawResource := []byte(`{
// "metadata":{
// "name":"test-config-map",
// "namespace":"default",
// "creationTimestamp":null,
// "labels":{
// "label1":"test1",
// "label2":"test2"
// }
// }
// }`)
assert.Assert(t, ResourceMeetsDescription(rawResource, resourceDescription, excludeResourcesResourceDesc, groupVersionKind))
// assert.Assert(t, ResourceMeetsDescription(rawResource, resourceDescription, excludeResourcesResourceDesc, groupVersionKind))
resourceDescription = types.ResourceDescription{
Kinds: []string{"ConfigMap"},
Name: &resourceName,
Selector: &metav1.LabelSelector{
MatchLabels: map[string]string{
"label1": "test1",
},
MatchExpressions: []metav1.LabelSelectorRequirement{
metav1.LabelSelectorRequirement{
Key: "label2",
Operator: "NotIn",
Values: []string{
"sometest1",
},
},
},
},
}
// resourceDescription = types.ResourceDescription{
// Kinds: []string{"ConfigMap"},
// Name: &resourceName,
// Selector: &metav1.LabelSelector{
// MatchLabels: map[string]string{
// "label1": "test1",
// },
// MatchExpressions: []metav1.LabelSelectorRequirement{
// metav1.LabelSelectorRequirement{
// Key: "label2",
// Operator: "NotIn",
// Values: []string{
// "sometest1",
// },
// },
// },
// },
// }
rawResource = []byte(`{
"metadata":{
"name":"test-config-map",
"namespace":"default",
"creationTimestamp":null,
"labels":{
"label1":"test1",
"label2":"test2"
}
}
}`)
assert.Assert(t, ResourceMeetsDescription(rawResource, resourceDescription, excludeResourcesResourceDesc, groupVersionKind))
// rawResource = []byte(`{
// "metadata":{
// "name":"test-config-map",
// "namespace":"default",
// "creationTimestamp":null,
// "labels":{
// "label1":"test1",
// "label2":"test2"
// }
// }
// }`)
// assert.Assert(t, ResourceMeetsDescription(rawResource, resourceDescription, excludeResourcesResourceDesc, groupVersionKind))
resourceDescription = types.ResourceDescription{
Kinds: []string{"ConfigMap"},
Name: &resourceName,
Selector: &metav1.LabelSelector{
MatchLabels: map[string]string{
"label1": "test1",
},
MatchExpressions: []metav1.LabelSelectorRequirement{
metav1.LabelSelectorRequirement{
Key: "label2",
Operator: "In",
Values: []string{
"sometest1",
},
},
},
},
}
// resourceDescription = types.ResourceDescription{
// Kinds: []string{"ConfigMap"},
// Name: &resourceName,
// Selector: &metav1.LabelSelector{
// MatchLabels: map[string]string{
// "label1": "test1",
// },
// MatchExpressions: []metav1.LabelSelectorRequirement{
// metav1.LabelSelectorRequirement{
// Key: "label2",
// Operator: "In",
// Values: []string{
// "sometest1",
// },
// },
// },
// },
// }
assert.Assert(t, false == ResourceMeetsDescription(rawResource, resourceDescription, excludeResourcesResourceDesc, groupVersionKind))
// assert.Assert(t, false == ResourceMeetsDescription(rawResource, resourceDescription, excludeResourcesResourceDesc, groupVersionKind))
resourceDescription = types.ResourceDescription{
Kinds: []string{"ConfigMap"},
Name: &resourceName,
Selector: &metav1.LabelSelector{
MatchLabels: map[string]string{
"label1": "test1",
"label3": "test3",
},
MatchExpressions: []metav1.LabelSelectorRequirement{
metav1.LabelSelectorRequirement{
Key: "label2",
Operator: "In",
Values: []string{
"test2",
},
},
},
},
}
// resourceDescription = types.ResourceDescription{
// Kinds: []string{"ConfigMap"},
// Name: &resourceName,
// Selector: &metav1.LabelSelector{
// MatchLabels: map[string]string{
// "label1": "test1",
// "label3": "test3",
// },
// MatchExpressions: []metav1.LabelSelectorRequirement{
// metav1.LabelSelectorRequirement{
// Key: "label2",
// Operator: "In",
// Values: []string{
// "test2",
// },
// },
// },
// },
// }
assert.Assert(t, false == ResourceMeetsDescription(rawResource, resourceDescription, excludeResourcesResourceDesc, groupVersionKind))
}
// assert.Assert(t, false == ResourceMeetsDescription(rawResource, resourceDescription, excludeResourcesResourceDesc, groupVersionKind))
// }
func TestWrappedWithParentheses_StringIsWrappedWithParentheses(t *testing.T) {
str := "(something)"

View file

@ -64,16 +64,15 @@ func listResources(client *client.Client, policy kyverno.Policy, filterK8Resourc
glog.V(4).Infof("skipping processing policy %s rule %s for kind Namespace", policy.Name, rule.Name)
continue
}
//TODO: if namespace is not define can we default to *
if rule.MatchResources.Namespace != "" {
namespaces = append(namespaces, rule.MatchResources.Namespace)
if len(rule.MatchResources.Namespaces) > 0 {
namespaces = append(namespaces, rule.MatchResources.Namespaces...)
} else {
glog.V(4).Infof("processing policy %s rule %s, namespace not defined, getting all namespaces ", policy.Name, rule.Name)
// get all namespaces
namespaces = getAllNamespaces(client)
}
// check if exclude namespace is not clashing
namespaces = excludeNamespaces(namespaces, rule.ExcludeResources.Namespace)
namespaces = excludeNamespaces(namespaces, rule.ExcludeResources.Namespaces)
// get resources in the namespaces
for _, ns := range namespaces {
@ -158,13 +157,13 @@ func kindIsExcluded(kind string, list []string) bool {
return false
}
func excludeNamespaces(namespaces []string, excludeNs string) []string {
if excludeNs == "" {
func excludeNamespaces(namespaces, excludeNs []string) []string {
if len(excludeNs) == 0 {
return namespaces
}
filteredNamespaces := []string{}
for _, n := range namespaces {
if n == excludeNs {
if utils.Contains(excludeNs, n) {
continue
}
filteredNamespaces = append(filteredNamespaces, n)

View file

@ -4,6 +4,7 @@ import (
"github.com/golang/glog"
engine "github.com/nirmata/kyverno/pkg/engine"
"github.com/nirmata/kyverno/pkg/info"
"github.com/nirmata/kyverno/pkg/utils"
v1beta1 "k8s.io/api/admission/v1beta1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/labels"
@ -42,7 +43,7 @@ func (ws *WebhookServer) HandleMutation(request *v1beta1.AdmissionRequest) *v1be
for _, policy := range policies {
// check if policy has a rule for the admission request kind
if !StringInSlice(request.Kind.Kind, getApplicableKindsForPolicy(policy)) {
if !utils.Contains(getApplicableKindsForPolicy(policy), request.Kind.Kind) {
continue
}
policyInfo := info.NewPolicyInfo(policy.Name, resource.GetKind(), resource.GetName(), resource.GetNamespace(), policy.Spec.ValidationFailureAction)

View file

@ -27,16 +27,6 @@ func isAdmSuccesful(policyInfos []info.PolicyInfo) (bool, string) {
return admSuccess, strings.Join(errMsgs, ";")
}
//StringInSlice checks if string is present in slice of strings
func StringInSlice(kind string, list []string) bool {
for _, b := range list {
if b == kind {
return true
}
}
return false
}
//ArrayFlags to store filterkinds
type ArrayFlags []string

View file

@ -5,6 +5,7 @@ import (
engine "github.com/nirmata/kyverno/pkg/engine"
"github.com/nirmata/kyverno/pkg/info"
"github.com/nirmata/kyverno/pkg/policyviolation"
"github.com/nirmata/kyverno/pkg/utils"
v1beta1 "k8s.io/api/admission/v1beta1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/labels"
@ -42,7 +43,7 @@ func (ws *WebhookServer) HandleValidation(request *v1beta1.AdmissionRequest) *v1
for _, policy := range policies {
if !StringInSlice(request.Kind.Kind, getApplicableKindsForPolicy(policy)) {
if !utils.Contains(getApplicableKindsForPolicy(policy), request.Kind.Kind) {
continue
}