mirror of
https://github.com/kyverno/kyverno.git
synced 2025-03-28 02:18:15 +00:00
fix: match wildcard names for generateExisting policies (#10945)
* fix: match wildcard names for generateExisting policies Signed-off-by: Mariam Fahmy <mariam.fahmy@nirmata.com> * fix chainsaw test Signed-off-by: Mariam Fahmy <mariam.fahmy@nirmata.com> * chore: add unit tests Signed-off-by: Mariam Fahmy <mariam.fahmy@nirmata.com> --------- Signed-off-by: Mariam Fahmy <mariam.fahmy@nirmata.com>
This commit is contained in:
parent
2cd462570a
commit
e00596a551
9 changed files with 199 additions and 3 deletions
|
@ -2,16 +2,28 @@ package policy
|
|||
|
||||
import (
|
||||
kyvernov1 "github.com/kyverno/kyverno/api/kyverno/v1"
|
||||
"github.com/kyverno/kyverno/ext/wildcard"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
)
|
||||
|
||||
func resourceMatches(match kyvernov1.ResourceDescription, res unstructured.Unstructured, isNamespacedPolicy bool) bool {
|
||||
if match.Name != "" && res.GetName() != match.Name {
|
||||
if match.Name != "" && !wildcard.Match(match.Name, res.GetName()) {
|
||||
return false
|
||||
}
|
||||
if len(match.Names) > 0 && !contains(match.Names, res.GetName()) {
|
||||
return false
|
||||
|
||||
if len(match.Names) > 0 {
|
||||
isMatch := false
|
||||
for _, name := range match.Names {
|
||||
if wildcard.Match(name, res.GetName()) {
|
||||
isMatch = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !isMatch {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
if !isNamespacedPolicy && len(match.Namespaces) > 0 && !contains(match.Namespaces, res.GetNamespace()) {
|
||||
return false
|
||||
}
|
||||
|
|
|
@ -51,6 +51,78 @@ func Test_resourceMatches(t *testing.T) {
|
|||
isNamespacedPolicy: false,
|
||||
want: false,
|
||||
},
|
||||
{
|
||||
name: "Matching resource with a wildcard name",
|
||||
match: kyverno.ResourceDescription{
|
||||
Kinds: []string{"Pod"},
|
||||
Name: "my-*",
|
||||
},
|
||||
res: unstructured.Unstructured{
|
||||
Object: map[string]interface{}{
|
||||
"apiVersion": "v1",
|
||||
"kind": "Pod",
|
||||
"metadata": map[string]interface{}{
|
||||
"name": "my-pod",
|
||||
},
|
||||
},
|
||||
},
|
||||
isNamespacedPolicy: false,
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
name: "Non-matching resource with a wildcard name",
|
||||
match: kyverno.ResourceDescription{
|
||||
Kinds: []string{"Pod"},
|
||||
Name: "my-*",
|
||||
},
|
||||
res: unstructured.Unstructured{
|
||||
Object: map[string]interface{}{
|
||||
"apiVersion": "v1",
|
||||
"kind": "Pod",
|
||||
"metadata": map[string]interface{}{
|
||||
"name": "test-pod",
|
||||
},
|
||||
},
|
||||
},
|
||||
isNamespacedPolicy: false,
|
||||
want: false,
|
||||
},
|
||||
{
|
||||
name: "Matching resource with multiple wildcard names",
|
||||
match: kyverno.ResourceDescription{
|
||||
Kinds: []string{"Pod"},
|
||||
Names: []string{"my-*", "test-pod"},
|
||||
},
|
||||
res: unstructured.Unstructured{
|
||||
Object: map[string]interface{}{
|
||||
"apiVersion": "v1",
|
||||
"kind": "Pod",
|
||||
"metadata": map[string]interface{}{
|
||||
"name": "my-pod",
|
||||
},
|
||||
},
|
||||
},
|
||||
isNamespacedPolicy: false,
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
name: "Non-matching resource with multiple wildcard names",
|
||||
match: kyverno.ResourceDescription{
|
||||
Kinds: []string{"Pod"},
|
||||
Names: []string{"my-*", "test-pod"},
|
||||
},
|
||||
res: unstructured.Unstructured{
|
||||
Object: map[string]interface{}{
|
||||
"apiVersion": "v1",
|
||||
"kind": "Pod",
|
||||
"metadata": map[string]interface{}{
|
||||
"name": "pod",
|
||||
},
|
||||
},
|
||||
},
|
||||
isNamespacedPolicy: false,
|
||||
want: false,
|
||||
},
|
||||
{
|
||||
name: "Matching resource based on its namespace",
|
||||
match: kyverno.ResourceDescription{
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
## Description
|
||||
|
||||
This test makes sure that a generate existing policy that matches wildcard names in the `match` block works as expected. The policy should only generate resources for the existing resources that match the wildcard name.
|
||||
|
||||
|
||||
## Expected Behavior
|
||||
|
||||
1. Create two Namespaces: `tst-home-dev` and `tst-mobile-dev`.
|
||||
|
||||
2. Create a policy that generates a ServiceAccount for all existing namespaces whose name matches the wildcard `tst-*`.
|
||||
|
||||
3. Two ServiceAccounts are generated in `tst-home-dev` and `tst-mobile-dev`.
|
||||
|
||||
## Reference Issue(s)
|
||||
|
||||
#10886
|
|
@ -0,0 +1,27 @@
|
|||
apiVersion: chainsaw.kyverno.io/v1alpha1
|
||||
kind: Test
|
||||
metadata:
|
||||
creationTimestamp: null
|
||||
name: existing-with-wildcard-name-matching
|
||||
spec:
|
||||
steps:
|
||||
- name: step-01
|
||||
try:
|
||||
- apply:
|
||||
file: permissions.yaml
|
||||
- apply:
|
||||
file: existing-resources.yaml
|
||||
- name: step-02
|
||||
try:
|
||||
- apply:
|
||||
file: policy.yaml
|
||||
- assert:
|
||||
file: policy-ready.yaml
|
||||
- name: step-03
|
||||
try:
|
||||
- sleep:
|
||||
duration: 3s
|
||||
- name: step-04
|
||||
try:
|
||||
- assert:
|
||||
file: generated-resources.yaml
|
|
@ -0,0 +1,9 @@
|
|||
apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
name: tst-home-dev
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
name: tst-mobile-dev
|
|
@ -0,0 +1,11 @@
|
|||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: home
|
||||
namespace: tst-home-dev
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: mobile
|
||||
namespace: tst-mobile-dev
|
|
@ -0,0 +1,19 @@
|
|||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRole
|
||||
metadata:
|
||||
name: kyverno:serviceaccount
|
||||
labels:
|
||||
rbac.kyverno.io/aggregate-to-background-controller: "true"
|
||||
rbac.kyverno.io/aggregate-to-reports-controller: "true"
|
||||
rbac.kyverno.io/aggregate-to-admission-controller: "true"
|
||||
rules:
|
||||
- apiGroups:
|
||||
- ''
|
||||
resources:
|
||||
- serviceaccounts
|
||||
verbs:
|
||||
- get
|
||||
- watch
|
||||
- list
|
||||
- delete
|
||||
- create
|
|
@ -0,0 +1,9 @@
|
|||
apiVersion: kyverno.io/v1
|
||||
kind: ClusterPolicy
|
||||
metadata:
|
||||
name: create-default-serviceaccount
|
||||
status:
|
||||
conditions:
|
||||
- reason: Succeeded
|
||||
status: "True"
|
||||
type: Ready
|
|
@ -0,0 +1,21 @@
|
|||
apiVersion: kyverno.io/v1
|
||||
kind: ClusterPolicy
|
||||
metadata:
|
||||
name: create-default-serviceaccount
|
||||
spec:
|
||||
rules:
|
||||
- name: default-service-account
|
||||
match:
|
||||
any:
|
||||
- resources:
|
||||
kinds:
|
||||
- Namespace
|
||||
names:
|
||||
- "tst-*"
|
||||
generate:
|
||||
generateExisting: true
|
||||
synchronize: false
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
namespace: "{{request.object.metadata.name}}"
|
||||
name: "{{to_lower(request.object.metadata.name | to_string(@) | split(@, '-') | [1])}}"
|
Loading…
Add table
Reference in a new issue