mirror of
https://github.com/kyverno/kyverno.git
synced 2025-03-13 19:28:55 +00:00
Matched list to configure the matched resources (#1844)
* Fix Dev setup * initial commit * add testcases for matchlist * fix e2e issue * fix comment * fix issue * fix lock issue * revert changes * fix cache issue * Fix cache test * fix policy object * fix comments * fix public methos issue Co-authored-by: vyankatesh <vyankatesh@neualto.com>
This commit is contained in:
parent
c0be318788
commit
299547f376
7 changed files with 284 additions and 222 deletions
|
@ -57,7 +57,7 @@ func ConvertPolicyToClusterPolicy(nsPolicies *kyverno.Policy) *kyverno.ClusterPo
|
|||
return &cpol
|
||||
}
|
||||
|
||||
func parseNamespacedPolicy(key string) (string, string, bool) {
|
||||
func ParseNamespacedPolicy(key string) (string, string, bool) {
|
||||
namespace := ""
|
||||
index := strings.Index(key, "/")
|
||||
if index != -1 {
|
||||
|
|
|
@ -474,7 +474,7 @@ func (pc *PolicyController) syncPolicy(key string) error {
|
|||
}
|
||||
|
||||
func (pc *PolicyController) getPolicy(key string) (policy *kyverno.ClusterPolicy, err error) {
|
||||
namespace, key, isNamespacedPolicy := parseNamespacedPolicy(key)
|
||||
namespace, key, isNamespacedPolicy := ParseNamespacedPolicy(key)
|
||||
if !isNamespacedPolicy {
|
||||
return pc.pLister.Get(key)
|
||||
}
|
||||
|
|
|
@ -5,18 +5,18 @@ import (
|
|||
|
||||
"github.com/go-logr/logr"
|
||||
kyverno "github.com/kyverno/kyverno/pkg/api/kyverno/v1"
|
||||
kyvernolister "github.com/kyverno/kyverno/pkg/client/listers/kyverno/v1"
|
||||
policy2 "github.com/kyverno/kyverno/pkg/policy"
|
||||
)
|
||||
|
||||
type pMap struct {
|
||||
sync.RWMutex
|
||||
// dataMap field stores ClusterPolicies
|
||||
dataMap map[PolicyType][]*kyverno.ClusterPolicy
|
||||
// nsDataMap field stores Namespaced Policies for each namespaces.
|
||||
// The Policy is converted internally to ClusterPolicy and stored as a ClusterPolicy
|
||||
// Since both the policy use same type (i.e. Policy), Both policies can be differentiated based on
|
||||
// "Kind" or "namespace". When the Policy is converted it will retain the value of kind as "Policy".
|
||||
// Cluster policy will be having namespace as Blank (""), but Policy will always be having namespace field and "default" value by default
|
||||
nsDataMap map[string]map[PolicyType][]*kyverno.ClusterPolicy
|
||||
|
||||
// kindDataMap field stores names of ClusterPolicies and Namespaced Policies.
|
||||
// Since both the policy name use same type (i.e. string), Both policies can be differentiated based on
|
||||
// "namespace". namespace policy get stored with policy namespace with policy name"
|
||||
// kindDataMap {"kind": {{"policytype" : {"policyName","nsname/policyName}}},"kind2": {{"policytype" : {"nsname/policyName" }}}}
|
||||
kindDataMap map[string]map[PolicyType][]string
|
||||
|
||||
// nameCacheMap stores the names of all existing policies in dataMap
|
||||
// Policy names are stored as <namespace>/<name>
|
||||
|
@ -27,17 +27,24 @@ type pMap struct {
|
|||
type policyCache struct {
|
||||
pMap
|
||||
logr.Logger
|
||||
// list/get cluster policy resource
|
||||
pLister kyvernolister.ClusterPolicyLister
|
||||
|
||||
// npLister can list/get namespace policy from the shared informer's store
|
||||
npLister kyvernolister.PolicyLister
|
||||
}
|
||||
|
||||
// Interface ...
|
||||
// Interface get method use for to get policy names and mostly use to test cache testcases
|
||||
type Interface interface {
|
||||
Add(policy *kyverno.ClusterPolicy)
|
||||
Remove(policy *kyverno.ClusterPolicy)
|
||||
Get(pkey PolicyType, nspace *string) []*kyverno.ClusterPolicy
|
||||
GetPolicyObject(pkey PolicyType, kind *string, nspace *string) []*kyverno.ClusterPolicy
|
||||
get(pkey PolicyType, kind *string, nspace *string) []string
|
||||
}
|
||||
|
||||
// newPolicyCache ...
|
||||
func newPolicyCache(log logr.Logger) Interface {
|
||||
func newPolicyCache(log logr.Logger, pLister kyvernolister.ClusterPolicyLister, npLister kyvernolister.PolicyLister) Interface {
|
||||
namesCache := map[PolicyType]map[string]bool{
|
||||
Mutate: make(map[string]bool),
|
||||
ValidateEnforce: make(map[string]bool),
|
||||
|
@ -47,24 +54,27 @@ func newPolicyCache(log logr.Logger) Interface {
|
|||
|
||||
return &policyCache{
|
||||
pMap{
|
||||
dataMap: make(map[PolicyType][]*kyverno.ClusterPolicy),
|
||||
nsDataMap: make(map[string]map[PolicyType][]*kyverno.ClusterPolicy),
|
||||
nameCacheMap: namesCache,
|
||||
kindDataMap: make(map[string]map[PolicyType][]string),
|
||||
},
|
||||
log,
|
||||
pLister,
|
||||
npLister,
|
||||
}
|
||||
}
|
||||
|
||||
// Add a policy to cache
|
||||
func (pc *policyCache) Add(policy *kyverno.ClusterPolicy) {
|
||||
pc.pMap.add(policy)
|
||||
|
||||
pc.Logger.V(4).Info("policy is added to cache", "name", policy.GetName())
|
||||
}
|
||||
|
||||
// Get the list of matched policies
|
||||
func (pc *policyCache) Get(pkey PolicyType, nspace *string) []*kyverno.ClusterPolicy {
|
||||
return pc.pMap.get(pkey, nspace)
|
||||
func (pc *policyCache) get(pkey PolicyType, kind, nspace *string) []string {
|
||||
return pc.pMap.get(pkey, kind, nspace)
|
||||
}
|
||||
func (pc *policyCache) GetPolicyObject(pkey PolicyType, kind, nspace *string) []*kyverno.ClusterPolicy {
|
||||
return pc.getPolicyObject(pkey, kind, nspace)
|
||||
}
|
||||
|
||||
// Remove a policy from cache
|
||||
|
@ -84,136 +94,121 @@ func (m *pMap) add(policy *kyverno.ClusterPolicy) {
|
|||
generateMap := m.nameCacheMap[Generate]
|
||||
var pName = policy.GetName()
|
||||
pSpace := policy.GetNamespace()
|
||||
isNamespacedPolicy := false
|
||||
if pSpace != "" {
|
||||
pName = pSpace + "/" + pName
|
||||
isNamespacedPolicy = true
|
||||
// Initialize Namespace Cache Map
|
||||
_, ok := m.nsDataMap[policy.GetNamespace()]
|
||||
if !ok {
|
||||
m.nsDataMap[policy.GetNamespace()] = make(map[PolicyType][]*kyverno.ClusterPolicy)
|
||||
}
|
||||
}
|
||||
|
||||
for _, rule := range policy.Spec.Rules {
|
||||
if rule.HasMutate() {
|
||||
if !mutateMap[pName] {
|
||||
mutateMap[pName] = true
|
||||
if isNamespacedPolicy {
|
||||
mutatePolicy := m.nsDataMap[policy.GetNamespace()][Mutate]
|
||||
m.nsDataMap[policy.GetNamespace()][Mutate] = append(mutatePolicy, policy)
|
||||
|
||||
for _, kind := range rule.MatchResources.Kinds {
|
||||
_, ok := m.kindDataMap[kind]
|
||||
if !ok {
|
||||
m.kindDataMap[kind] = make(map[PolicyType][]string)
|
||||
}
|
||||
|
||||
if rule.HasMutate() {
|
||||
if !mutateMap[kind+"/"+pName] {
|
||||
mutateMap[kind+"/"+pName] = true
|
||||
mutatePolicy := m.kindDataMap[kind][Mutate]
|
||||
m.kindDataMap[kind][Mutate] = append(mutatePolicy, pName)
|
||||
}
|
||||
continue
|
||||
}
|
||||
if rule.HasValidate() {
|
||||
if enforcePolicy {
|
||||
if !validateEnforceMap[kind+"/"+pName] {
|
||||
validateEnforceMap[kind+"/"+pName] = true
|
||||
validatePolicy := m.kindDataMap[kind][ValidateEnforce]
|
||||
m.kindDataMap[kind][ValidateEnforce] = append(validatePolicy, pName)
|
||||
}
|
||||
continue
|
||||
}
|
||||
mutatePolicy := m.dataMap[Mutate]
|
||||
m.dataMap[Mutate] = append(mutatePolicy, policy)
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
if rule.HasValidate() {
|
||||
if enforcePolicy {
|
||||
if !validateEnforceMap[pName] {
|
||||
validateEnforceMap[pName] = true
|
||||
if isNamespacedPolicy {
|
||||
validatePolicy := m.nsDataMap[policy.GetNamespace()][ValidateEnforce]
|
||||
m.nsDataMap[policy.GetNamespace()][ValidateEnforce] = append(validatePolicy, policy)
|
||||
continue
|
||||
}
|
||||
validatePolicy := m.dataMap[ValidateEnforce]
|
||||
m.dataMap[ValidateEnforce] = append(validatePolicy, policy)
|
||||
// ValidateAudit
|
||||
if !validateAuditMap[kind+"/"+pName] {
|
||||
validateAuditMap[kind+"/"+pName] = true
|
||||
validatePolicy := m.kindDataMap[kind][ValidateAudit]
|
||||
m.kindDataMap[kind][ValidateAudit] = append(validatePolicy, pName)
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
// ValidateAudit
|
||||
if !validateAuditMap[pName] {
|
||||
validateAuditMap[pName] = true
|
||||
if isNamespacedPolicy {
|
||||
validatePolicy := m.nsDataMap[policy.GetNamespace()][ValidateAudit]
|
||||
m.nsDataMap[policy.GetNamespace()][ValidateAudit] = append(validatePolicy, policy)
|
||||
continue
|
||||
if rule.HasGenerate() {
|
||||
if !generateMap[kind+"/"+pName] {
|
||||
generateMap[kind+"/"+pName] = true
|
||||
generatePolicy := m.kindDataMap[kind][Generate]
|
||||
m.kindDataMap[kind][Generate] = append(generatePolicy, pName)
|
||||
}
|
||||
validatePolicy := m.dataMap[ValidateAudit]
|
||||
m.dataMap[ValidateAudit] = append(validatePolicy, policy)
|
||||
continue
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
if rule.HasGenerate() {
|
||||
if !generateMap[pName] {
|
||||
generateMap[pName] = true
|
||||
if isNamespacedPolicy {
|
||||
generatePolicy := m.nsDataMap[policy.GetNamespace()][Generate]
|
||||
m.nsDataMap[policy.GetNamespace()][Generate] = append(generatePolicy, policy)
|
||||
continue
|
||||
}
|
||||
generatePolicy := m.dataMap[Generate]
|
||||
m.dataMap[Generate] = append(generatePolicy, policy)
|
||||
}
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
m.nameCacheMap[Mutate] = mutateMap
|
||||
m.nameCacheMap[ValidateEnforce] = validateEnforceMap
|
||||
m.nameCacheMap[ValidateAudit] = validateAuditMap
|
||||
m.nameCacheMap[Generate] = generateMap
|
||||
}
|
||||
|
||||
func (m *pMap) get(key PolicyType, nspace *string) []*kyverno.ClusterPolicy {
|
||||
m.RLock()
|
||||
defer m.RUnlock()
|
||||
if nspace == nil || *nspace == "" {
|
||||
return m.dataMap[key]
|
||||
func (pc *pMap) get(key PolicyType, kind, namespace *string) (names []string) {
|
||||
pc.RLock()
|
||||
defer pc.RUnlock()
|
||||
for _, policyName := range pc.kindDataMap[*kind][key] {
|
||||
ns, key, isNamespacedPolicy := policy2.ParseNamespacedPolicy(policyName)
|
||||
if !isNamespacedPolicy {
|
||||
names = append(names, key)
|
||||
} else {
|
||||
if ns == *namespace {
|
||||
names = append(names, policyName)
|
||||
}
|
||||
}
|
||||
}
|
||||
return m.nsDataMap[*nspace][key]
|
||||
|
||||
return names
|
||||
}
|
||||
|
||||
func (m *pMap) remove(policy *kyverno.ClusterPolicy) {
|
||||
m.Lock()
|
||||
defer m.Unlock()
|
||||
|
||||
var pName = policy.GetName()
|
||||
pSpace := policy.GetNamespace()
|
||||
isNamespacedPolicy := false
|
||||
if pSpace != "" {
|
||||
pName = pSpace + "/" + pName
|
||||
isNamespacedPolicy = true
|
||||
}
|
||||
if !isNamespacedPolicy {
|
||||
dataMap := m.dataMap
|
||||
for k, policies := range dataMap {
|
||||
|
||||
var newPolicies []*kyverno.ClusterPolicy
|
||||
for _, p := range policies {
|
||||
if p.GetName() == pName {
|
||||
continue
|
||||
}
|
||||
newPolicies = append(newPolicies, p)
|
||||
}
|
||||
|
||||
m.dataMap[k] = newPolicies
|
||||
}
|
||||
} else {
|
||||
dataMap := m.nsDataMap[pSpace]
|
||||
for k, policies := range dataMap {
|
||||
|
||||
var newPolicies []*kyverno.ClusterPolicy
|
||||
for _, p := range policies {
|
||||
if (p.GetNamespace() + "/" + p.GetName()) == pName {
|
||||
continue
|
||||
}
|
||||
newPolicies = append(newPolicies, p)
|
||||
}
|
||||
|
||||
m.nsDataMap[pSpace][k] = newPolicies
|
||||
}
|
||||
}
|
||||
|
||||
for _, nameCache := range m.nameCacheMap {
|
||||
if _, ok := nameCache[pName]; ok {
|
||||
delete(nameCache, pName)
|
||||
for _, rule := range policy.Spec.Rules {
|
||||
for _, kind := range rule.MatchResources.Kinds {
|
||||
dataMap := m.kindDataMap[kind]
|
||||
for policyType, policies := range dataMap {
|
||||
var newPolicies []string
|
||||
for _, p := range policies {
|
||||
if p == pName {
|
||||
continue
|
||||
}
|
||||
newPolicies = append(newPolicies, p)
|
||||
}
|
||||
m.kindDataMap[kind][policyType] = newPolicies
|
||||
}
|
||||
for _, nameCache := range m.nameCacheMap {
|
||||
if ok := nameCache[kind+"/"+pName]; ok {
|
||||
delete(nameCache, kind+"/"+pName)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
func (m *policyCache) getPolicyObject(key PolicyType, kind *string, nspace *string) (policyObject []*kyverno.ClusterPolicy) {
|
||||
policyNames := m.pMap.get(key, kind, nspace)
|
||||
for _, policyName := range policyNames {
|
||||
var policy *kyverno.ClusterPolicy
|
||||
ns, key, isNamespacedPolicy := policy2.ParseNamespacedPolicy(policyName)
|
||||
if !isNamespacedPolicy {
|
||||
policy, _ = m.pLister.Get(key)
|
||||
} else {
|
||||
if ns == *nspace {
|
||||
nspolicy, _ := m.npLister.Policies(ns).Get(key)
|
||||
policy = policy2.ConvertPolicyToClusterPolicy(nspolicy)
|
||||
}
|
||||
}
|
||||
policyObject = append(policyObject, policy)
|
||||
}
|
||||
return policyObject
|
||||
}
|
||||
|
|
|
@ -2,101 +2,151 @@ package policycache
|
|||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
kyverno "github.com/kyverno/kyverno/pkg/api/kyverno/v1"
|
||||
|
||||
lv1 "github.com/kyverno/kyverno/pkg/client/listers/kyverno/v1"
|
||||
"gotest.tools/assert"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
"sigs.k8s.io/controller-runtime/pkg/log"
|
||||
)
|
||||
|
||||
type dummyLister struct {
|
||||
}
|
||||
|
||||
func (dl dummyLister) List(selector labels.Selector) (ret []*kyverno.ClusterPolicy, err error) {
|
||||
return nil, fmt.Errorf("not implemented")
|
||||
}
|
||||
|
||||
func (dl dummyLister) Get(name string) (*kyverno.ClusterPolicy, error) {
|
||||
return nil, fmt.Errorf("not implemented")
|
||||
}
|
||||
|
||||
func (dl dummyLister) ListResources(selector labels.Selector) (ret []*kyverno.ClusterPolicy, err error) {
|
||||
return nil, fmt.Errorf("not implemented")
|
||||
}
|
||||
|
||||
// type dymmyNsNamespace struct {}
|
||||
|
||||
type dummyNsLister struct {
|
||||
}
|
||||
|
||||
func (dl dummyNsLister) Policies(name string) lv1.PolicyNamespaceLister {
|
||||
return dummyNsLister{}
|
||||
}
|
||||
|
||||
func (dl dummyNsLister) List(selector labels.Selector) (ret []*kyverno.Policy, err error) {
|
||||
return nil, fmt.Errorf("not implemented")
|
||||
}
|
||||
|
||||
func (dl dummyNsLister) Get(name string) (*kyverno.Policy, error) {
|
||||
return nil, fmt.Errorf("not implemented")
|
||||
}
|
||||
|
||||
func Test_All(t *testing.T) {
|
||||
pCache := newPolicyCache(log.Log)
|
||||
pCache := newPolicyCache(log.Log, dummyLister{}, dummyNsLister{})
|
||||
policy := newPolicy(t)
|
||||
|
||||
// add
|
||||
//add
|
||||
pCache.Add(policy)
|
||||
for _, rule := range policy.Spec.Rules {
|
||||
for _, kind := range rule.MatchResources.Kinds {
|
||||
|
||||
// get
|
||||
if len(pCache.Get(Mutate, nil)) != 1 {
|
||||
t.Errorf("expected 1 mutate policy, found %v", len(pCache.Get(Mutate, nil)))
|
||||
}
|
||||
// get
|
||||
mutate := pCache.get(Mutate, &kind, nil)
|
||||
if len(mutate) != 1 {
|
||||
t.Errorf("expected 1 mutate policy, found %v", len(mutate))
|
||||
}
|
||||
|
||||
if len(pCache.Get(ValidateEnforce, nil)) != 1 {
|
||||
t.Errorf("expected 1 validate enforce policy, found %v", len(pCache.Get(ValidateEnforce, nil)))
|
||||
}
|
||||
|
||||
if len(pCache.Get(Generate, nil)) != 1 {
|
||||
t.Errorf("expected 1 generate policy, found %v", len(pCache.Get(Generate, nil)))
|
||||
validateEnforce := pCache.get(ValidateEnforce, &kind, nil)
|
||||
if len(validateEnforce) != 1 {
|
||||
t.Errorf("expected 1 validate policy, found %v", len(validateEnforce))
|
||||
}
|
||||
generate := pCache.get(Generate, &kind, nil)
|
||||
if len(generate) != 1 {
|
||||
t.Errorf("expected 1 generate policy, found %v", len(generate))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// remove
|
||||
pCache.Remove(policy)
|
||||
assert.Assert(t, len(pCache.Get(ValidateEnforce, nil)) == 0)
|
||||
kind := "pod"
|
||||
validateEnforce := pCache.get(ValidateEnforce, &kind, nil)
|
||||
assert.Assert(t, len(validateEnforce) == 0)
|
||||
}
|
||||
|
||||
func Test_Add_Duplicate_Policy(t *testing.T) {
|
||||
pCache := newPolicyCache(log.Log)
|
||||
pCache := newPolicyCache(log.Log, dummyLister{}, dummyNsLister{})
|
||||
policy := newPolicy(t)
|
||||
|
||||
pCache.Add(policy)
|
||||
pCache.Add(policy)
|
||||
pCache.Add(policy)
|
||||
for _, rule := range policy.Spec.Rules {
|
||||
for _, kind := range rule.MatchResources.Kinds {
|
||||
|
||||
if len(pCache.Get(Mutate, nil)) != 1 {
|
||||
t.Errorf("expected 1 mutate policy, found %v", len(pCache.Get(Mutate, nil)))
|
||||
}
|
||||
mutate := pCache.get(Mutate, &kind, nil)
|
||||
if len(mutate) != 1 {
|
||||
t.Errorf("expected 1 mutate policy, found %v", len(mutate))
|
||||
}
|
||||
|
||||
if len(pCache.Get(ValidateEnforce, nil)) != 1 {
|
||||
t.Errorf("expected 1 validate enforce policy, found %v", len(pCache.Get(ValidateEnforce, nil)))
|
||||
}
|
||||
|
||||
if len(pCache.Get(Generate, nil)) != 1 {
|
||||
t.Errorf("expected 1 generate policy, found %v", len(pCache.Get(Generate, nil)))
|
||||
validateEnforce := pCache.get(ValidateEnforce, &kind, nil)
|
||||
if len(validateEnforce) != 1 {
|
||||
t.Errorf("expected 1 validate policy, found %v", len(validateEnforce))
|
||||
}
|
||||
generate := pCache.get(Generate, &kind, nil)
|
||||
if len(generate) != 1 {
|
||||
t.Errorf("expected 1 generate policy, found %v", len(generate))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func Test_Add_Validate_Audit(t *testing.T) {
|
||||
pCache := newPolicyCache(log.Log)
|
||||
pCache := newPolicyCache(log.Log, dummyLister{}, dummyNsLister{})
|
||||
policy := newPolicy(t)
|
||||
|
||||
pCache.Add(policy)
|
||||
pCache.Add(policy)
|
||||
|
||||
policy.Spec.ValidationFailureAction = "audit"
|
||||
pCache.Add(policy)
|
||||
pCache.Add(policy)
|
||||
for _, rule := range policy.Spec.Rules {
|
||||
for _, kind := range rule.MatchResources.Kinds {
|
||||
|
||||
if len(pCache.Get(ValidateEnforce, nil)) != 1 {
|
||||
t.Errorf("expected 1 validate enforce policy, found %v", len(pCache.Get(ValidateEnforce, nil)))
|
||||
}
|
||||
validateEnforce := pCache.get(ValidateEnforce, &kind, nil)
|
||||
if len(validateEnforce) != 1 {
|
||||
t.Errorf("expected 1 mutate policy, found %v", len(validateEnforce))
|
||||
}
|
||||
|
||||
if len(pCache.Get(ValidateAudit, nil)) != 1 {
|
||||
t.Errorf("expected 1 validate audit policy, found %v", len(pCache.Get(ValidateAudit, nil)))
|
||||
validateAudit := pCache.get(ValidateAudit, &kind, nil)
|
||||
if len(validateEnforce) != 1 {
|
||||
t.Errorf("expected 1 validate policy, found %v", len(validateAudit))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func Test_Add_Remove(t *testing.T) {
|
||||
pCache := newPolicyCache(log.Log)
|
||||
pCache := newPolicyCache(log.Log, dummyLister{}, dummyNsLister{})
|
||||
policy := newPolicy(t)
|
||||
|
||||
kind := "Pod"
|
||||
pCache.Add(policy)
|
||||
if len(pCache.Get(ValidateEnforce, nil)) != 1 {
|
||||
t.Errorf("expected 1 validate enforce policy, found %v", len(pCache.Get(ValidateEnforce, nil)))
|
||||
validateEnforce := pCache.get(ValidateEnforce, &kind, nil)
|
||||
if len(validateEnforce) != 1 {
|
||||
t.Errorf("expected 1 validate enforce policy, found %v", len(validateEnforce))
|
||||
}
|
||||
|
||||
pCache.Remove(policy)
|
||||
if len(pCache.Get(ValidateEnforce, nil)) != 0 {
|
||||
t.Errorf("expected 1 validate enforce policy, found %v", len(pCache.Get(ValidateEnforce, nil)))
|
||||
}
|
||||
|
||||
pCache.Add(policy)
|
||||
if len(pCache.Get(ValidateEnforce, nil)) != 1 {
|
||||
t.Errorf("expected 1 validate enforce policy, found %v", len(pCache.Get(ValidateEnforce, nil)))
|
||||
deletedValidateEnforce := pCache.get(ValidateEnforce, &kind, nil)
|
||||
if len(deletedValidateEnforce) != 0 {
|
||||
t.Errorf("expected 0 validate enforce policy, found %v", len(deletedValidateEnforce))
|
||||
}
|
||||
}
|
||||
|
||||
func Test_Remove_From_Empty_Cache(t *testing.T) {
|
||||
pCache := newPolicyCache(log.Log)
|
||||
pCache := newPolicyCache(log.Log, nil, nil)
|
||||
policy := newPolicy(t)
|
||||
|
||||
pCache.Remove(policy)
|
||||
|
@ -115,19 +165,20 @@ func newPolicy(t *testing.T) *kyverno.ClusterPolicy {
|
|||
"match": {
|
||||
"resources": {
|
||||
"kinds": [
|
||||
"Pod"
|
||||
"Pod",
|
||||
"Namespace"
|
||||
]
|
||||
}
|
||||
},
|
||||
"validate": {
|
||||
"deny": {
|
||||
"conditions": {
|
||||
"all": [
|
||||
{
|
||||
"key": "a",
|
||||
"operator": "Equals",
|
||||
"value": "a"
|
||||
}
|
||||
"all": [
|
||||
{
|
||||
"key": "a",
|
||||
"operator": "Equals",
|
||||
"value": "a"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
@ -159,7 +210,8 @@ func newPolicy(t *testing.T) *kyverno.ClusterPolicy {
|
|||
"match": {
|
||||
"resources": {
|
||||
"kinds": [
|
||||
"Pod"
|
||||
"Pod",
|
||||
"Namespace"
|
||||
]
|
||||
}
|
||||
},
|
||||
|
@ -178,7 +230,8 @@ func newPolicy(t *testing.T) *kyverno.ClusterPolicy {
|
|||
"match": {
|
||||
"resources": {
|
||||
"kinds": [
|
||||
"Namespace"
|
||||
"Namespace",
|
||||
"Pod"
|
||||
]
|
||||
}
|
||||
},
|
||||
|
@ -285,7 +338,7 @@ func newNsPolicy(t *testing.T) *kyverno.ClusterPolicy {
|
|||
"match": {
|
||||
"resources": {
|
||||
"kinds": [
|
||||
"Namespace"
|
||||
"Pod"
|
||||
]
|
||||
}
|
||||
},
|
||||
|
@ -316,89 +369,103 @@ func newNsPolicy(t *testing.T) *kyverno.ClusterPolicy {
|
|||
}
|
||||
|
||||
func Test_Ns_All(t *testing.T) {
|
||||
pCache := newPolicyCache(log.Log)
|
||||
pCache := newPolicyCache(log.Log, dummyLister{}, dummyNsLister{})
|
||||
policy := newNsPolicy(t)
|
||||
|
||||
// add
|
||||
//add
|
||||
pCache.Add(policy)
|
||||
nspace := policy.GetNamespace()
|
||||
// get
|
||||
if len(pCache.Get(Mutate, &nspace)) != 1 {
|
||||
t.Errorf("expected 1 mutate policy, found %v", len(pCache.Get(Mutate, &nspace)))
|
||||
}
|
||||
for _, rule := range policy.Spec.Rules {
|
||||
for _, kind := range rule.MatchResources.Kinds {
|
||||
|
||||
if len(pCache.Get(ValidateEnforce, &nspace)) != 1 {
|
||||
t.Errorf("expected 1 validate enforce policy, found %v", len(pCache.Get(ValidateEnforce, &nspace)))
|
||||
}
|
||||
// get
|
||||
mutate := pCache.get(Mutate, &kind, &nspace)
|
||||
if len(mutate) != 1 {
|
||||
t.Errorf("expected 1 mutate policy, found %v", len(mutate))
|
||||
}
|
||||
|
||||
if len(pCache.Get(Generate, &nspace)) != 1 {
|
||||
t.Errorf("expected 1 generate policy, found %v", len(pCache.Get(Generate, &nspace)))
|
||||
validateEnforce := pCache.get(ValidateEnforce, &kind, &nspace)
|
||||
if len(validateEnforce) != 1 {
|
||||
t.Errorf("expected 1 validate policy, found %v", len(validateEnforce))
|
||||
}
|
||||
generate := pCache.get(Generate, &kind, &nspace)
|
||||
if len(generate) != 1 {
|
||||
t.Errorf("expected 1 generate policy, found %v", len(generate))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// remove
|
||||
pCache.Remove(policy)
|
||||
assert.Assert(t, len(pCache.Get(ValidateEnforce, &nspace)) == 0)
|
||||
kind := "pod"
|
||||
validateEnforce := pCache.get(ValidateEnforce, &kind, &nspace)
|
||||
assert.Assert(t, len(validateEnforce) == 0)
|
||||
}
|
||||
|
||||
func Test_Ns_Add_Duplicate_Policy(t *testing.T) {
|
||||
pCache := newPolicyCache(log.Log)
|
||||
pCache := newPolicyCache(log.Log, dummyLister{}, dummyNsLister{})
|
||||
policy := newNsPolicy(t)
|
||||
|
||||
pCache.Add(policy)
|
||||
pCache.Add(policy)
|
||||
pCache.Add(policy)
|
||||
nspace := policy.GetNamespace()
|
||||
if len(pCache.Get(Mutate, &nspace)) != 1 {
|
||||
t.Errorf("expected 1 mutate policy, found %v", len(pCache.Get(Mutate, &nspace)))
|
||||
}
|
||||
for _, rule := range policy.Spec.Rules {
|
||||
for _, kind := range rule.MatchResources.Kinds {
|
||||
|
||||
if len(pCache.Get(ValidateEnforce, &nspace)) != 1 {
|
||||
t.Errorf("expected 1 validate enforce policy, found %v", len(pCache.Get(ValidateEnforce, &nspace)))
|
||||
}
|
||||
mutate := pCache.get(Mutate, &kind, &nspace)
|
||||
if len(mutate) != 1 {
|
||||
t.Errorf("expected 1 mutate policy, found %v", len(mutate))
|
||||
}
|
||||
|
||||
if len(pCache.Get(Generate, &nspace)) != 1 {
|
||||
t.Errorf("expected 1 generate policy, found %v", len(pCache.Get(Generate, &nspace)))
|
||||
validateEnforce := pCache.get(ValidateEnforce, &kind, &nspace)
|
||||
if len(validateEnforce) != 1 {
|
||||
t.Errorf("expected 1 validate policy, found %v", len(validateEnforce))
|
||||
}
|
||||
generate := pCache.get(Generate, &kind, &nspace)
|
||||
if len(generate) != 1 {
|
||||
t.Errorf("expected 1 generate policy, found %v", len(generate))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func Test_Ns_Add_Validate_Audit(t *testing.T) {
|
||||
pCache := newPolicyCache(log.Log)
|
||||
pCache := newPolicyCache(log.Log, dummyLister{}, dummyNsLister{})
|
||||
policy := newNsPolicy(t)
|
||||
pCache.Add(policy)
|
||||
pCache.Add(policy)
|
||||
nspace := policy.GetNamespace()
|
||||
|
||||
pCache.Add(policy)
|
||||
pCache.Add(policy)
|
||||
|
||||
policy.Spec.ValidationFailureAction = "audit"
|
||||
pCache.Add(policy)
|
||||
pCache.Add(policy)
|
||||
for _, rule := range policy.Spec.Rules {
|
||||
for _, kind := range rule.MatchResources.Kinds {
|
||||
|
||||
if len(pCache.Get(ValidateEnforce, &nspace)) != 1 {
|
||||
t.Errorf("expected 1 validate enforce policy, found %v", len(pCache.Get(ValidateEnforce, &nspace)))
|
||||
}
|
||||
validateEnforce := pCache.get(ValidateEnforce, &kind, &nspace)
|
||||
if len(validateEnforce) != 1 {
|
||||
t.Errorf("expected 1 validate policy, found %v", len(validateEnforce))
|
||||
}
|
||||
|
||||
if len(pCache.Get(ValidateAudit, &nspace)) != 1 {
|
||||
t.Errorf("expected 1 validate audit policy, found %v", len(pCache.Get(ValidateAudit, &nspace)))
|
||||
validateAudit := pCache.get(ValidateAudit, &kind, &nspace)
|
||||
if len(validateEnforce) != 1 {
|
||||
t.Errorf("expected 1 validate policy, found %v", len(validateAudit))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func Test_Ns_Add_Remove(t *testing.T) {
|
||||
pCache := newPolicyCache(log.Log)
|
||||
pCache := newPolicyCache(log.Log, dummyLister{}, dummyNsLister{})
|
||||
policy := newNsPolicy(t)
|
||||
|
||||
pCache.Add(policy)
|
||||
nspace := policy.GetNamespace()
|
||||
if len(pCache.Get(ValidateEnforce, &nspace)) != 1 {
|
||||
t.Errorf("expected 1 validate enforce policy, found %v", len(pCache.Get(ValidateEnforce, &nspace)))
|
||||
kind := "Pod"
|
||||
pCache.Add(policy)
|
||||
validateEnforce := pCache.get(ValidateEnforce, &kind, &nspace)
|
||||
if len(validateEnforce) != 1 {
|
||||
t.Errorf("expected 1 validate enforce policy, found %v", len(validateEnforce))
|
||||
}
|
||||
|
||||
pCache.Remove(policy)
|
||||
if len(pCache.Get(ValidateEnforce, &nspace)) != 0 {
|
||||
t.Errorf("expected 1 validate enforce policy, found %v", len(pCache.Get(ValidateEnforce, &nspace)))
|
||||
}
|
||||
|
||||
pCache.Add(policy)
|
||||
if len(pCache.Get(ValidateEnforce, &nspace)) != 1 {
|
||||
t.Errorf("expected 1 validate enforce policy, found %v", len(pCache.Get(ValidateEnforce, &nspace)))
|
||||
deletedValidateEnforce := pCache.get(ValidateEnforce, &kind, &nspace)
|
||||
if len(deletedValidateEnforce) != 0 {
|
||||
t.Errorf("expected 0 validate enforce policy, found %v", len(deletedValidateEnforce))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,7 +28,7 @@ func NewPolicyCacheController(
|
|||
log logr.Logger) *Controller {
|
||||
|
||||
pc := Controller{
|
||||
Cache: newPolicyCache(log),
|
||||
Cache: newPolicyCache(log, pInformer.Lister(), nspInformer.Lister()),
|
||||
log: log,
|
||||
}
|
||||
|
||||
|
|
|
@ -308,11 +308,11 @@ func (ws *WebhookServer) ResourceMutation(request *v1beta1.AdmissionRequest) *v1
|
|||
}
|
||||
|
||||
logger.V(6).Info("received an admission request in mutating webhook")
|
||||
mutatePolicies := ws.pCache.Get(policycache.Mutate, nil)
|
||||
generatePolicies := ws.pCache.Get(policycache.Generate, nil)
|
||||
mutatePolicies := ws.pCache.GetPolicyObject(policycache.Mutate, &request.Kind.Kind, nil)
|
||||
generatePolicies := ws.pCache.GetPolicyObject(policycache.Generate, &request.Kind.Kind, nil)
|
||||
|
||||
// Get namespace policies from the cache for the requested resource namespace
|
||||
nsMutatePolicies := ws.pCache.Get(policycache.Mutate, &request.Namespace)
|
||||
nsMutatePolicies := ws.pCache.GetPolicyObject(policycache.Mutate, &request.Kind.Kind, &request.Namespace)
|
||||
mutatePolicies = append(mutatePolicies, nsMutatePolicies...)
|
||||
|
||||
// convert RAW to unstructured
|
||||
|
@ -395,9 +395,9 @@ func (ws *WebhookServer) resourceValidation(request *v1beta1.AdmissionRequest) *
|
|||
|
||||
logger.V(6).Info("received an admission request in validating webhook")
|
||||
|
||||
policies := ws.pCache.Get(policycache.ValidateEnforce, nil)
|
||||
policies := ws.pCache.GetPolicyObject(policycache.ValidateEnforce, &request.Kind.Kind, nil)
|
||||
// Get namespace policies from the cache for the requested resource namespace
|
||||
nsPolicies := ws.pCache.Get(policycache.ValidateEnforce, &request.Namespace)
|
||||
nsPolicies := ws.pCache.GetPolicyObject(policycache.ValidateEnforce, &request.Kind.Kind, &request.Namespace)
|
||||
policies = append(policies, nsPolicies...)
|
||||
if len(policies) == 0 {
|
||||
// push admission request to audit handler, this won't block the admission request
|
||||
|
|
|
@ -149,9 +149,9 @@ func (h *auditHandler) process(request *v1beta1.AdmissionRequest) error {
|
|||
var err error
|
||||
|
||||
logger := h.log.WithName("process")
|
||||
policies := h.pCache.Get(policycache.ValidateAudit, nil)
|
||||
policies := h.pCache.GetPolicyObject(policycache.ValidateAudit, &request.Kind.Kind, nil)
|
||||
// Get namespace policies from the cache for the requested resource namespace
|
||||
nsPolicies := h.pCache.Get(policycache.ValidateAudit, &request.Namespace)
|
||||
nsPolicies := h.pCache.GetPolicyObject(policycache.ValidateAudit, &request.Kind.Kind, &request.Namespace)
|
||||
policies = append(policies, nsPolicies...)
|
||||
// getRoleRef only if policy has roles/clusterroles defined
|
||||
if containRBACInfo(policies) {
|
||||
|
|
Loading…
Add table
Reference in a new issue