mirror of
https://github.com/kyverno/kyverno.git
synced 2024-12-15 17:51:20 +00:00
Merge pull request #246 from nirmata/244_bug
existing resources checks all namespace, instead of jst default it left blank
This commit is contained in:
commit
55716624ca
2 changed files with 129 additions and 123 deletions
|
@ -3,140 +3,17 @@ package engine
|
|||
import (
|
||||
jsonpatch "github.com/evanphx/json-patch"
|
||||
"github.com/golang/glog"
|
||||
"github.com/minio/minio/pkg/wildcard"
|
||||
types "github.com/nirmata/kyverno/pkg/apis/policy/v1alpha1"
|
||||
client "github.com/nirmata/kyverno/pkg/dclient"
|
||||
"github.com/nirmata/kyverno/pkg/info"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
v1helper "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
)
|
||||
|
||||
func ListResourcesThatApplyToPolicy(client *client.Client, policy *types.Policy) map[string]resourceInfo {
|
||||
// key uid
|
||||
resourceMap := map[string]resourceInfo{}
|
||||
for _, rule := range policy.Spec.Rules {
|
||||
// Match
|
||||
for _, k := range rule.MatchResources.Kinds {
|
||||
// kind -> resource
|
||||
gvr := client.DiscoveryClient.GetGVRFromKind(k)
|
||||
// Namespace
|
||||
namespace := "default"
|
||||
if rule.MatchResources.Namespace != nil {
|
||||
namespace = *rule.MatchResources.Namespace
|
||||
}
|
||||
if k == "Namespace" {
|
||||
namespace = ""
|
||||
}
|
||||
// Check if exclude namespace is not clashing
|
||||
if rule.ExcludeResources.Namespace != nil && *rule.ExcludeResources.Namespace == namespace {
|
||||
// as the namespace is excluded
|
||||
continue
|
||||
}
|
||||
|
||||
// List resources
|
||||
list, err := client.ListResource(k, namespace, rule.MatchResources.Selector)
|
||||
if err != nil {
|
||||
glog.Errorf("unable to list resource for %s with label selector %s", gvr.Resource, rule.MatchResources.Selector.String())
|
||||
glog.Errorf("unable to apply policy %s rule %s. err: %s", policy.Name, rule.Name, err)
|
||||
continue
|
||||
}
|
||||
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 != nil {
|
||||
// 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}}
|
||||
|
||||
resourceMap[string(res.GetUID())] = ri
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
return resourceMap
|
||||
}
|
||||
|
||||
// ProcessExisting checks for mutation and validation violations of existing resources
|
||||
func ProcessExisting(client *client.Client, policy *types.Policy) []*info.PolicyInfo {
|
||||
glog.Infof("Applying policy %s on existing resources", policy.Name)
|
||||
// key uid
|
||||
resourceMap := ListResourcesThatApplyToPolicy(client, policy)
|
||||
|
||||
// for _, rule := range policy.Spec.Rules {
|
||||
// for _, k := range rule.Kinds {
|
||||
// // kind -> resource
|
||||
// gvr := client.DiscoveryClient.GetGVRFromKind(k)
|
||||
// // label selectors
|
||||
// // namespace ? should it be default or allow policy to specify it
|
||||
// namespace := "default"
|
||||
// if rule.ResourceDescription.Namespace != nil {
|
||||
// namespace = *rule.ResourceDescription.Namespace
|
||||
// }
|
||||
// if k == "Namespace" {
|
||||
// namespace = ""
|
||||
// }
|
||||
|
||||
// list, err := client.ListResource(k, namespace, rule.ResourceDescription.Selector)
|
||||
// if err != nil {
|
||||
// glog.Errorf("unable to list resource for %s with label selector %s", gvr.Resource, rule.Selector.String())
|
||||
// glog.Errorf("unable to apply policy %s rule %s. err: %s", policy.Name, rule.Name, err)
|
||||
// continue
|
||||
// }
|
||||
// for _, res := range list.Items {
|
||||
// name := rule.ResourceDescription.Name
|
||||
// gvk := res.GroupVersionKind()
|
||||
// if name != nil {
|
||||
// // wild card matching
|
||||
// if !wildcard.Match(*name, res.GetName()) {
|
||||
// continue
|
||||
// }
|
||||
// }
|
||||
// ri := resourceInfo{resource: res, gvk: &metav1.GroupVersionKind{Group: gvk.Group,
|
||||
// Version: gvk.Version,
|
||||
// Kind: gvk.Kind}}
|
||||
|
||||
// resourceMap[string(res.GetUID())] = ri
|
||||
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
policyInfos := []*info.PolicyInfo{}
|
||||
// for the filtered resource apply policy
|
||||
for _, v := range resourceMap {
|
||||
|
|
|
@ -9,13 +9,142 @@ import (
|
|||
"github.com/golang/glog"
|
||||
|
||||
"github.com/minio/minio/pkg/wildcard"
|
||||
types "github.com/nirmata/kyverno/pkg/apis/policy/v1alpha1"
|
||||
v1alpha1 "github.com/nirmata/kyverno/pkg/apis/policy/v1alpha1"
|
||||
client "github.com/nirmata/kyverno/pkg/dclient"
|
||||
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 *types.Policy) 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 != nil {
|
||||
// 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)
|
||||
mergeresources(resourceMap, rMap)
|
||||
}
|
||||
}
|
||||
}
|
||||
return resourceMap
|
||||
}
|
||||
|
||||
func getResourcesPerNamespace(kind string, client *client.Client, namespace string, rule types.Rule) 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 != nil {
|
||||
// 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}}
|
||||
|
||||
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 == nil {
|
||||
return namespaces
|
||||
}
|
||||
filteredNamespaces := []string{}
|
||||
for _, n := range namespaces {
|
||||
if n == *excludeNs {
|
||||
continue
|
||||
}
|
||||
filteredNamespaces = append(filteredNamespaces, n)
|
||||
}
|
||||
return filteredNamespaces
|
||||
}
|
||||
|
||||
// ResourceMeetsDescription checks requests kind, name and labels to fit the policy rule
|
||||
func ResourceMeetsDescription(resourceRaw []byte, matches v1alpha1.ResourceDescription, exclude v1alpha1.ResourceDescription, gvk metav1.GroupVersionKind) bool {
|
||||
if !findKind(matches.Kinds, gvk.Kind) {
|
||||
|
|
Loading…
Reference in a new issue