mirror of
https://github.com/kyverno/kyverno.git
synced 2025-03-06 07:57:07 +00:00
Signed-off-by: slayer321 <sachin.maurya7666@gmail.com> Signed-off-by: slayer321 <sachin.maurya7666@gmail.com>
1005 lines
21 KiB
Go
1005 lines
21 KiB
Go
package mutate
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
"github.com/kyverno/kyverno/test/e2e"
|
|
)
|
|
|
|
var (
|
|
podGVR = e2e.GetGVR("", "v1", "pods")
|
|
deploymentGVR = e2e.GetGVR("apps", "v1", "deployments")
|
|
configmGVR = e2e.GetGVR("", "v1", "configmaps")
|
|
secretGVR = e2e.GetGVR("", "v1", "secrets")
|
|
)
|
|
|
|
func newNamespaceYaml(name string) []byte {
|
|
ns := fmt.Sprintf(`
|
|
apiVersion: v1
|
|
kind: Namespace
|
|
metadata:
|
|
name: %s
|
|
`, name)
|
|
|
|
return []byte(ns)
|
|
}
|
|
|
|
// Cluster Policy to copy the copy me label from one configmap to the target
|
|
var configMapMutationYaml = []byte(`
|
|
apiVersion: kyverno.io/v1
|
|
kind: ClusterPolicy
|
|
metadata:
|
|
name: "mutate-policy"
|
|
spec:
|
|
rules:
|
|
- name: "gen-role"
|
|
match:
|
|
resources:
|
|
kinds:
|
|
- ConfigMap
|
|
context:
|
|
- name: labelValue
|
|
apiCall:
|
|
urlPath: "/api/v1/namespaces/{{ request.object.metadata.namespace }}/configmaps"
|
|
jmesPath: "items[*]"
|
|
mutate:
|
|
patchStrategicMerge:
|
|
metadata:
|
|
labels:
|
|
+(kyverno.key/copy-me): "{{ labelValue[?metadata.name == 'source'].metadata.labels.\"kyverno.key/copy-me\" | [0] }}"
|
|
`)
|
|
|
|
var configMapMutationWithContextLogicYaml = []byte(`
|
|
apiVersion: kyverno.io/v1
|
|
kind: ClusterPolicy
|
|
metadata:
|
|
name: "mutate-policy"
|
|
spec:
|
|
rules:
|
|
- name: "gen-role"
|
|
match:
|
|
resources:
|
|
kinds:
|
|
- ConfigMap
|
|
context:
|
|
- name: labelValue
|
|
apiCall:
|
|
urlPath: "/api/v1/namespaces/{{ request.object.metadata.namespace }}/configmaps"
|
|
jmesPath: "items[?metadata.name == 'source'].metadata.labels.\"kyverno.key/copy-me\" | [0]"
|
|
mutate:
|
|
patchStrategicMerge:
|
|
metadata:
|
|
labels:
|
|
+(kyverno.key/copy-me): "{{ labelValue }}"
|
|
`)
|
|
|
|
var configMapMutationWithContextLabelSelectionYaml = []byte(`
|
|
apiVersion: kyverno.io/v1
|
|
kind: ClusterPolicy
|
|
metadata:
|
|
name: "mutate-policy"
|
|
spec:
|
|
rules:
|
|
- name: "gen-role"
|
|
match:
|
|
resources:
|
|
kinds:
|
|
- ConfigMap
|
|
context:
|
|
- name: labelValue
|
|
apiCall:
|
|
urlPath: "/api/v1/namespaces/{{ request.object.metadata.namespace }}/configmaps"
|
|
jmesPath: "items[?metadata.name == '{{ request.object.metadata.labels.\"kyverno.key/copy-from\" }}'].metadata.labels.\"kyverno.key/copy-me\" | [0]"
|
|
mutate:
|
|
patchStrategicMerge:
|
|
metadata:
|
|
labels:
|
|
+(kyverno.key/copy-me): "{{ labelValue }}"
|
|
`)
|
|
|
|
// Source ConfigMap from which data is taken to copy
|
|
var sourceConfigMapYaml = []byte(`
|
|
apiVersion: v1
|
|
kind: ConfigMap
|
|
metadata:
|
|
name: source
|
|
namespace: test-mutate
|
|
labels:
|
|
kyverno.key/copy-me: sample-value
|
|
data:
|
|
data.yaml: |
|
|
some: data
|
|
`)
|
|
|
|
// Target ConfigMap which is mutated
|
|
var targetConfigMapYaml = []byte(`
|
|
apiVersion: v1
|
|
kind: ConfigMap
|
|
metadata:
|
|
name: target
|
|
namespace: test-mutate
|
|
labels:
|
|
kyverno.key/copy-from: source
|
|
data:
|
|
data.yaml: |
|
|
some: data
|
|
`)
|
|
|
|
var mutateIngressCpol = []byte(`
|
|
apiVersion: kyverno.io/v1
|
|
kind: ClusterPolicy
|
|
metadata:
|
|
name: mutate-ingress-host
|
|
spec:
|
|
rules:
|
|
- name: mutate-rules-host
|
|
match:
|
|
resources:
|
|
kinds:
|
|
- Ingress
|
|
namespaces:
|
|
- test-ingress
|
|
mutate:
|
|
patchesJson6902: |-
|
|
- op: replace
|
|
path: /spec/rules/0/host
|
|
value: "{{request.object.spec.rules[0].host}}.mycompany.com"
|
|
`)
|
|
|
|
var ingressNetworkingV1 = []byte(`
|
|
apiVersion: networking.k8s.io/v1
|
|
kind: Ingress
|
|
metadata:
|
|
name: kuard-v1
|
|
namespace: test-ingress
|
|
labels:
|
|
app: kuard
|
|
spec:
|
|
rules:
|
|
- host: kuard
|
|
http:
|
|
paths:
|
|
- backend:
|
|
service:
|
|
name: kuard
|
|
port:
|
|
number: 8080
|
|
path: /
|
|
pathType: ImplementationSpecific
|
|
tls:
|
|
- hosts:
|
|
- kuard
|
|
`)
|
|
|
|
var ingressNetworkingV1beta1 = []byte(`
|
|
apiVersion: networking.k8s.io/v1beta1
|
|
kind: Ingress
|
|
metadata:
|
|
labels:
|
|
app: kuard
|
|
name: kuard-v1beta1
|
|
namespace: test-ingress
|
|
spec:
|
|
rules:
|
|
- host: kuard
|
|
http:
|
|
paths:
|
|
- backend:
|
|
serviceName: kuard
|
|
servicePort: 8080
|
|
path: /
|
|
pathType: ImplementationSpecific
|
|
tls:
|
|
- hosts:
|
|
- kuard
|
|
`)
|
|
|
|
var setRunAsNonRootTrue = []byte(`
|
|
apiVersion: kyverno.io/v1
|
|
kind: ClusterPolicy
|
|
metadata:
|
|
name: set-runasnonroot-true
|
|
spec:
|
|
rules:
|
|
- name: set-runasnonroot-true
|
|
match:
|
|
resources:
|
|
kinds:
|
|
- Pod
|
|
mutate:
|
|
patchStrategicMerge:
|
|
spec:
|
|
securityContext:
|
|
runAsNonRoot: true
|
|
initContainers:
|
|
- (name): "*"
|
|
securityContext:
|
|
runAsNonRoot: true
|
|
containers:
|
|
- (name): "*"
|
|
securityContext:
|
|
runAsNonRoot: true
|
|
`)
|
|
|
|
var podWithContainers = []byte(`
|
|
apiVersion: v1
|
|
kind: Pod
|
|
metadata:
|
|
name: foo
|
|
namespace: test-mutate
|
|
labels:
|
|
app: foo
|
|
spec:
|
|
containers:
|
|
- image: abc:1.28
|
|
name: busybox
|
|
`)
|
|
|
|
var podWithContainersPattern = []byte(`
|
|
apiVersion: v1
|
|
kind: Pod
|
|
metadata:
|
|
name: foo
|
|
namespace: test-mutate
|
|
labels:
|
|
app: foo
|
|
spec:
|
|
securityContext:
|
|
runAsNonRoot: true
|
|
containers:
|
|
- (name): "*"
|
|
securityContext:
|
|
runAsNonRoot: true
|
|
`)
|
|
|
|
var podWithContainersAndInitContainers = []byte(`
|
|
apiVersion: v1
|
|
kind: Pod
|
|
metadata:
|
|
name: foo
|
|
namespace: test-mutate1
|
|
labels:
|
|
app: foo
|
|
spec:
|
|
containers:
|
|
- image: abc:1.28
|
|
name: busybox
|
|
initContainers:
|
|
- image: bcd:1.29
|
|
name: nginx
|
|
`)
|
|
|
|
var podWithContainersAndInitContainersPattern = []byte(`
|
|
apiVersion: v1
|
|
kind: Pod
|
|
metadata:
|
|
name: foo
|
|
namespace: test-mutate1
|
|
labels:
|
|
app: foo
|
|
spec:
|
|
securityContext:
|
|
runAsNonRoot: true
|
|
containers:
|
|
- (name): "*"
|
|
securityContext:
|
|
runAsNonRoot: true
|
|
initContainers:
|
|
- (name): "*"
|
|
securityContext:
|
|
runAsNonRoot: true
|
|
`)
|
|
|
|
var kyverno_mutate_json_patch = []byte(`
|
|
apiVersion: kyverno.io/v1
|
|
kind: ClusterPolicy
|
|
metadata:
|
|
name: add-image-as-env-var
|
|
# env array needs to exist (least one env var is present)
|
|
annotations:
|
|
pod-policies.kyverno.io/autogen-controllers: None
|
|
policies.kyverno.io/title: Add Image as Environment Variable
|
|
policies.kyverno.io/category: Other
|
|
policies.kyverno.io/severity: medium
|
|
policies.kyverno.io/minversion: 1.4.3
|
|
policies.kyverno.io/subject: Pod, Deployment
|
|
policies.kyverno.io/description: >-
|
|
The Kubernetes downward API only has the ability to express so many
|
|
options as environment variables. The image consumed in a Pod is commonly
|
|
needed to make the application aware of some logic it must take. This policy
|
|
takes the value of the 'image' field and adds it as an environment variable
|
|
to bare Pods and Deployments having no more than two containers. The 'env' array must already exist for the policy
|
|
to operate correctly. This policy may be easily extended to support other higher-level
|
|
Pod controllers as well as more containers by following the established rules.
|
|
spec:
|
|
background: false
|
|
schemaValidation: false
|
|
rules:
|
|
# One Pod
|
|
- name: pod-containers-1-inject-image
|
|
match:
|
|
resources:
|
|
kinds:
|
|
- Pod
|
|
preconditions:
|
|
all:
|
|
- key: "{{request.object.spec.containers[] | length(@)}}"
|
|
operator: GreaterThanOrEquals
|
|
value: 1
|
|
mutate:
|
|
patchesJson6902: |-
|
|
- op: add
|
|
path: "/spec/containers/0/env/-"
|
|
value: {"name":"K8S_IMAGE","value":"{{request.object.spec.containers[0].image}}"}
|
|
# Two or more Pods
|
|
- name: pod-containers-2-inject-image
|
|
match:
|
|
resources:
|
|
kinds:
|
|
- Pod
|
|
preconditions:
|
|
all:
|
|
- key: "{{request.object.spec.containers[] | length(@)}}"
|
|
operator: GreaterThanOrEquals
|
|
value: 2
|
|
mutate:
|
|
patchesJson6902: |-
|
|
- op: add
|
|
path: "/spec/containers/1/env/-"
|
|
value: {"name":"K8S_IMAGE","value":"{{request.object.spec.containers[1].image}}"}
|
|
# Deployment with one Pod
|
|
- name: deploy-containers-1-inject-image
|
|
match:
|
|
resources:
|
|
kinds:
|
|
- Deployment
|
|
preconditions:
|
|
all:
|
|
- key: "{{request.object.spec.template.spec.containers[] | length(@)}}"
|
|
operator: GreaterThanOrEquals
|
|
value: 1
|
|
mutate:
|
|
patchesJson6902: |-
|
|
- op: add
|
|
path: "/spec/template/spec/containers/0/env/-"
|
|
value: {"name":"K8S_IMAGE","value":"{{request.object.spec.template.spec.containers[0].image}}"}
|
|
# Deployment with two or more Pods
|
|
- name: deploy-containers-2-inject-image
|
|
match:
|
|
resources:
|
|
kinds:
|
|
- Deployment
|
|
preconditions:
|
|
all:
|
|
- key: "{{request.object.spec.template.spec.containers[] | length(@)}}"
|
|
operator: GreaterThanOrEquals
|
|
value: 2
|
|
mutate:
|
|
patchesJson6902: |-
|
|
- op: add
|
|
path: "/spec/template/spec/containers/1/env/-"
|
|
value: {"name":"K8S_IMAGE","value":"{{request.object.spec.template.spec.containers[1].image}}"}
|
|
`)
|
|
|
|
var podWithEnvVar = []byte(`
|
|
apiVersion: v1
|
|
kind: Pod
|
|
metadata:
|
|
name: foo
|
|
namespace: test-mutate-env-array
|
|
spec:
|
|
containers:
|
|
- command:
|
|
- sleep infinity
|
|
env:
|
|
- name: K8S_IMAGE
|
|
value: docker.io/busybox:1.11
|
|
image: busybox:1.11
|
|
name: busybox
|
|
securityContext:
|
|
capabilities:
|
|
drop:
|
|
- SETUID
|
|
initContainers:
|
|
- command:
|
|
- sleep infinity
|
|
image: nginx:1.14
|
|
name: nginx
|
|
securityContext:
|
|
capabilities:
|
|
drop:
|
|
- SETUID
|
|
`)
|
|
|
|
var podWithEnvVarPattern = []byte(`
|
|
apiVersion: v1
|
|
kind: Pod
|
|
metadata:
|
|
name: foo
|
|
namespace: test-mutate-env-array
|
|
spec:
|
|
containers:
|
|
- command:
|
|
- sleep infinity
|
|
env:
|
|
- name: K8S_IMAGE
|
|
value: docker.io/busybox:1.11
|
|
image: busybox:1.11
|
|
name: busybox
|
|
securityContext:
|
|
capabilities:
|
|
drop:
|
|
- SETUID
|
|
- command:
|
|
- sleep infinity
|
|
env:
|
|
- name: K8S_IMAGE
|
|
value: linkerd:1.21
|
|
image: linkerd:1.21
|
|
name: linkerd
|
|
securityContext:
|
|
capabilities:
|
|
drop:
|
|
- NET_RAW
|
|
- SOME_THING
|
|
initContainers:
|
|
- command:
|
|
- sleep infinity
|
|
image: nginx:1.14
|
|
name: nginx
|
|
securityContext:
|
|
capabilities:
|
|
drop:
|
|
- SETUID
|
|
`)
|
|
|
|
var kyverno_2316_policy = []byte(`
|
|
apiVersion: kyverno.io/v1
|
|
kind: ClusterPolicy
|
|
metadata:
|
|
name: structured-logs-sidecar
|
|
spec:
|
|
background: false
|
|
rules:
|
|
- name: add-annotations
|
|
match:
|
|
resources:
|
|
kinds:
|
|
- Deployment
|
|
annotations:
|
|
structured-logs: "true"
|
|
mutate:
|
|
patchStrategicMerge:
|
|
metadata:
|
|
annotations:
|
|
"fluentbit.io/exclude-{{request.object.spec.template.spec.containers[0].name}}": "true"
|
|
`)
|
|
|
|
var kyverno_2316_resource = []byte(`
|
|
apiVersion: apps/v1
|
|
kind: Deployment
|
|
metadata:
|
|
name: busybox
|
|
namespace: test-mutate2
|
|
annotations:
|
|
structured-logs: "true"
|
|
labels:
|
|
# app: busybox
|
|
color: red
|
|
animal: bear
|
|
food: pizza
|
|
car: jeep
|
|
env: qa
|
|
# foo: blaaah
|
|
spec:
|
|
replicas: 1
|
|
selector:
|
|
matchLabels:
|
|
app: busybox
|
|
template:
|
|
metadata:
|
|
labels:
|
|
app: busybox
|
|
# foo: blaaah
|
|
spec:
|
|
containers:
|
|
- image: busybox:1.28
|
|
name: busybox
|
|
command: ["sleep", "9999"]
|
|
resources:
|
|
requests:
|
|
cpu: 100m
|
|
memory: 10Mi
|
|
limits:
|
|
cpu: 100m
|
|
memory: 10Mi
|
|
- image: busybox:1.28
|
|
name: busybox1
|
|
command: ["sleep", "9999"]
|
|
resources:
|
|
requests:
|
|
cpu: 100m
|
|
memory: 10Mi
|
|
limits:
|
|
cpu: 100m
|
|
memory: 20Mi
|
|
`)
|
|
|
|
var kyverno_2316_pattern = []byte(`
|
|
metadata:
|
|
annotations:
|
|
fluentbit.io/exclude-busybox: "true"
|
|
`)
|
|
|
|
var kyverno_2971_policy = []byte(`
|
|
apiVersion : kyverno.io/v1
|
|
kind: ClusterPolicy
|
|
metadata:
|
|
name: replace-docker-hub
|
|
spec:
|
|
rules:
|
|
- name: replace-docker-hub
|
|
match:
|
|
resources:
|
|
kinds:
|
|
- Pod
|
|
preconditions:
|
|
all:
|
|
- key: "{{request.operation}}"
|
|
operator: In
|
|
value:
|
|
- CREATE
|
|
- UPDATE
|
|
mutate:
|
|
foreach:
|
|
- list: "request.object.spec.containers"
|
|
preconditions:
|
|
all:
|
|
- key: '{{images.containers."{{element.name}}".registry}}'
|
|
operator: Equals
|
|
value: 'docker.io'
|
|
patchStrategicMerge:
|
|
spec:
|
|
containers:
|
|
- name: "{{ element.name }}"
|
|
image: 'my-private-registry/{{images.containers."{{element.name}}".path}}:{{images.containers."{{element.name}}".tag}}'
|
|
`)
|
|
|
|
var kyverno_2971_resource = []byte(`
|
|
apiVersion: v1
|
|
kind: Pod
|
|
metadata:
|
|
name: nginx
|
|
namespace: test-mutate-img
|
|
spec:
|
|
containers:
|
|
- name: nginx
|
|
image: nginx:1.14.2
|
|
`)
|
|
|
|
var kyverno_2971_pattern = []byte(`
|
|
spec:
|
|
containers:
|
|
- name: "nginx"
|
|
image: 'my-private-registry/nginx:1.14.2'
|
|
`)
|
|
|
|
var annotate_host_path_policy = []byte(`
|
|
apiVersion: kyverno.io/v1
|
|
kind: ClusterPolicy
|
|
metadata:
|
|
name: add-safe-to-evict
|
|
annotations:
|
|
policies.kyverno.io/category: Workload Management
|
|
policies.kyverno.io/description: The Kubernetes cluster autoscaler does not evict pods that
|
|
use hostPath or emptyDir volumes. To allow eviction of these pods, the annotation
|
|
cluster-autoscaler.kubernetes.io/safe-to-evict=true must be added to the pods.
|
|
spec:
|
|
rules:
|
|
- name: annotate-empty-dir
|
|
match:
|
|
resources:
|
|
kinds:
|
|
- Pod
|
|
mutate:
|
|
patchStrategicMerge:
|
|
metadata:
|
|
annotations:
|
|
+(cluster-autoscaler.kubernetes.io/safe-to-evict): "true"
|
|
spec:
|
|
volumes:
|
|
- <(emptyDir): {}
|
|
- name: annotate-host-path
|
|
match:
|
|
resources:
|
|
kinds:
|
|
- Pod
|
|
mutate:
|
|
patchStrategicMerge:
|
|
metadata:
|
|
annotations:
|
|
+(cluster-autoscaler.kubernetes.io/safe-to-evict): "true"
|
|
spec:
|
|
volumes:
|
|
- hostPath:
|
|
<(path): "*"
|
|
`)
|
|
|
|
var setImagePullSecret = []byte(`
|
|
apiVersion: kyverno.io/v1
|
|
kind: ClusterPolicy
|
|
metadata:
|
|
name: set-image-pull-secret
|
|
spec:
|
|
background: false
|
|
rules:
|
|
- name: set-image-pull-secret
|
|
match:
|
|
resources:
|
|
kinds:
|
|
- Pod
|
|
mutate:
|
|
patchStrategicMerge:
|
|
spec:
|
|
containers:
|
|
# match images that are from our registry
|
|
- <(image): "registry.corp.com/*"
|
|
# set the imagePullSecrets
|
|
imagePullSecrets:
|
|
- name: regcred
|
|
`)
|
|
|
|
var podWithNoSecrets = []byte(`
|
|
apiVersion: v1
|
|
kind: Pod
|
|
metadata:
|
|
name: nginx
|
|
namespace: test-run
|
|
spec:
|
|
containers:
|
|
- name: nginx
|
|
image: registry.corp.com/nginx:1.14.2
|
|
`)
|
|
|
|
var podWithNoSecretPattern = []byte(`
|
|
apiVersion: v1
|
|
kind: Pod
|
|
metadata:
|
|
name: nginx
|
|
namespace: test-run
|
|
spec:
|
|
containers:
|
|
- name: nginx
|
|
image: registry.corp.com/nginx:1.14.2
|
|
imagePullSecrets:
|
|
- name: regcred
|
|
`)
|
|
|
|
var podWithEmptyDirAsVolume = []byte(`
|
|
apiVersion: v1
|
|
kind: Pod
|
|
metadata:
|
|
name: pod-with-emptydir
|
|
namespace: emptydir
|
|
labels:
|
|
foo: bar
|
|
spec:
|
|
containers:
|
|
- image: nginx
|
|
name: nginx
|
|
volumeMounts:
|
|
- mountPath: /cache
|
|
name: cache-volume
|
|
volumes:
|
|
- name: cache-volume
|
|
emptyDir: {}
|
|
`)
|
|
|
|
var podWithVolumePattern = []byte(`
|
|
metadata:
|
|
annotations:
|
|
cluster-autoscaler.kubernetes.io/safe-to-evict: "true"
|
|
`)
|
|
|
|
var podWithHostPathAsVolume = []byte(`
|
|
apiVersion: v1
|
|
kind: Pod
|
|
metadata:
|
|
name: pod-with-hostpath
|
|
namespace: hostpath
|
|
labels:
|
|
foo: bar
|
|
spec:
|
|
containers:
|
|
- image: nginx
|
|
name: nginx
|
|
volumeMounts:
|
|
- mountPath: /usr/share/nginx/html
|
|
name: test-volume
|
|
volumes:
|
|
- hostPath:
|
|
path: /var/local/aaa
|
|
type: DirectoryOrCreate
|
|
name: test-volume
|
|
`)
|
|
|
|
var policyCreateTrigger = []byte(`
|
|
apiVersion: kyverno.io/v1
|
|
kind: ClusterPolicy
|
|
metadata:
|
|
name: "test-post-mutation-create-trigger"
|
|
spec:
|
|
mutateExistingOnPolicyUpdate: false
|
|
rules:
|
|
- name: "mutate-deploy-on-configmap-create"
|
|
match:
|
|
any:
|
|
- resources:
|
|
kinds:
|
|
- ConfigMap
|
|
names:
|
|
- dictionary-1
|
|
namespaces:
|
|
- staging-1
|
|
mutate:
|
|
targets:
|
|
- apiVersion: v1
|
|
kind: Secret
|
|
name: test-secret-1
|
|
namespace: "{{ request.object.metadata.namespace }}"
|
|
patchStrategicMerge:
|
|
metadata:
|
|
labels:
|
|
foo: "{{ request.object.metadata.name }}"
|
|
`)
|
|
|
|
var triggerCreateTrigger = []byte(`
|
|
apiVersion: v1
|
|
data:
|
|
foo: bar
|
|
kind: ConfigMap
|
|
metadata:
|
|
labels:
|
|
test: createTrigger
|
|
name: dictionary-1
|
|
namespace: staging-1
|
|
`)
|
|
|
|
var targetCreateTrigger = []byte(`
|
|
apiVersion: v1
|
|
kind: Secret
|
|
metadata:
|
|
name: test-secret-1
|
|
namespace: staging-1
|
|
labels:
|
|
test: createTrigger
|
|
type: Opaque
|
|
data:
|
|
value: Z29vZGJ5ZQ==
|
|
`)
|
|
|
|
var expectedTargetCreateTrigger = []byte(`
|
|
apiVersion: v1
|
|
kind: Secret
|
|
metadata:
|
|
name: test-secret-1
|
|
namespace: staging-1
|
|
labels:
|
|
test: createTrigger
|
|
foo: dictionary-1
|
|
type: Opaque
|
|
data:
|
|
value: Z29vZGJ5ZQ==
|
|
`)
|
|
|
|
var policyDeleteTrigger = []byte(`
|
|
apiVersion: kyverno.io/v1
|
|
kind: ClusterPolicy
|
|
metadata:
|
|
name: "test-post-mutation-delete-trigger"
|
|
spec:
|
|
mutateExistingOnPolicyUpdate: false
|
|
rules:
|
|
- name: "mutate-deploy-on-configmap-delete"
|
|
match:
|
|
any:
|
|
- resources:
|
|
kinds:
|
|
- ConfigMap
|
|
names:
|
|
- dictionary-2
|
|
namespaces:
|
|
- staging-2
|
|
preconditions:
|
|
any:
|
|
- key: "{{ request.operation }}"
|
|
operator: Equals
|
|
value: DELETE
|
|
mutate:
|
|
targets:
|
|
- apiVersion: v1
|
|
kind: Secret
|
|
name: test-secret-2
|
|
namespace: "{{ request.object.metadata.namespace }}"
|
|
patchStrategicMerge:
|
|
metadata:
|
|
labels:
|
|
foo: "{{ request.object.metadata.name }}"
|
|
`)
|
|
|
|
var triggerDeleteTrigger = []byte(`
|
|
apiVersion: v1
|
|
data:
|
|
foo: bar
|
|
kind: ConfigMap
|
|
metadata:
|
|
labels:
|
|
test: deleteTrigger
|
|
name: dictionary-2
|
|
namespace: staging-2
|
|
`)
|
|
|
|
var targetDeleteTrigger = []byte(`
|
|
apiVersion: v1
|
|
kind: Secret
|
|
metadata:
|
|
name: test-secret-2
|
|
namespace: staging-2
|
|
labels:
|
|
test: deleteTrigger
|
|
type: Opaque
|
|
data:
|
|
value: Z29vZGJ5ZQ==
|
|
`)
|
|
|
|
var expectedTargetDeleteTrigger = []byte(`
|
|
apiVersion: v1
|
|
kind: Secret
|
|
metadata:
|
|
name: test-secret-2
|
|
namespace: staging-2
|
|
labels:
|
|
test: deleteTrigger
|
|
foo: dictionary-2
|
|
type: Opaque
|
|
data:
|
|
value: Z29vZGJ5ZQ==
|
|
`)
|
|
|
|
var policyCreatePolicy = []byte(`
|
|
apiVersion: kyverno.io/v1
|
|
kind: ClusterPolicy
|
|
metadata:
|
|
name: "test-post-mutation-create-policy"
|
|
spec:
|
|
mutateExistingOnPolicyUpdate: true
|
|
rules:
|
|
- name: "mutate-deploy-on-policy-create"
|
|
match:
|
|
any:
|
|
- resources:
|
|
kinds:
|
|
- ConfigMap
|
|
names:
|
|
- dictionary-3
|
|
namespaces:
|
|
- staging-3
|
|
mutate:
|
|
targets:
|
|
- apiVersion: v1
|
|
kind: Secret
|
|
name: test-secret-3
|
|
namespace: "{{ request.object.metadata.namespace }}"
|
|
patchStrategicMerge:
|
|
metadata:
|
|
labels:
|
|
foo: "{{ request.object.metadata.name }}"
|
|
`)
|
|
|
|
var triggerCreatePolicy = []byte(`
|
|
apiVersion: v1
|
|
data:
|
|
foo: bar
|
|
kind: ConfigMap
|
|
metadata:
|
|
labels:
|
|
test: createPolicy
|
|
name: dictionary-3
|
|
namespace: staging-3
|
|
`)
|
|
|
|
var targetCreatePolicy = []byte(`
|
|
apiVersion: v1
|
|
kind: Secret
|
|
metadata:
|
|
name: test-secret-3
|
|
namespace: staging-3
|
|
labels:
|
|
test: createPolicy
|
|
type: Opaque
|
|
data:
|
|
value: Z29vZGJ5ZQ==
|
|
`)
|
|
|
|
var expectedTargetCreatePolicy = []byte(`
|
|
apiVersion: v1
|
|
kind: Secret
|
|
metadata:
|
|
name: test-secret-3
|
|
namespace: staging-3
|
|
labels:
|
|
test: createPolicy
|
|
foo: dictionary-3
|
|
type: Opaque
|
|
data:
|
|
value: Z29vZGJ5ZQ==
|
|
`)
|
|
|
|
var policyCreateTriggerJsonPatch = []byte(`
|
|
apiVersion: kyverno.io/v1
|
|
kind: ClusterPolicy
|
|
metadata:
|
|
name: "test-post-mutation"
|
|
spec:
|
|
mutateExistingOnPolicyUpdate: false
|
|
rules:
|
|
- name: "mutate-deploy-on-configmap-update"
|
|
match:
|
|
any:
|
|
- resources:
|
|
kinds:
|
|
- ConfigMap
|
|
names:
|
|
- dictionary-4
|
|
namespaces:
|
|
- staging-4
|
|
mutate:
|
|
targets:
|
|
- apiVersion: v1
|
|
kind: Secret
|
|
name: test-secret-4
|
|
namespace: "{{ request.object.metadata.namespace }}"
|
|
patchesJson6902: |-
|
|
- op: add
|
|
path: "/metadata/labels/env"
|
|
value: "{{ request.object.metadata.namespace }}"
|
|
`)
|
|
|
|
var triggerCreateTriggerJsonPatch = []byte(`
|
|
apiVersion: v1
|
|
data:
|
|
foo: bar
|
|
kind: ConfigMap
|
|
metadata:
|
|
labels:
|
|
test: createTrigger
|
|
name: dictionary-4
|
|
namespace: staging-4
|
|
`)
|
|
|
|
var targetCreateTriggerJsonPatch = []byte(`
|
|
apiVersion: v1
|
|
kind: Secret
|
|
metadata:
|
|
name: test-secret-4
|
|
namespace: staging-4
|
|
labels:
|
|
test: createTrigger
|
|
type: Opaque
|
|
data:
|
|
value: Z29vZGJ5ZQ==
|
|
`)
|
|
|
|
var expectedCreateTriggerJsonPatch = []byte(`
|
|
apiVersion: v1
|
|
kind: Secret
|
|
metadata:
|
|
name: test-secret-4
|
|
namespace: staging-4
|
|
labels:
|
|
test: createTrigger
|
|
env: staging-4
|
|
type: Opaque
|
|
data:
|
|
value: Z29vZGJ5ZQ==
|
|
`)
|