1
0
Fork 0
mirror of https://github.com/kyverno/kyverno.git synced 2025-03-06 07:57:07 +00:00
kyverno/test/e2e/mutate/resources.go
Sachin Maurya bec5632344
e2e test for mutate policy (#3383)
Signed-off-by: slayer321 <sachin.maurya7666@gmail.com>

Signed-off-by: slayer321 <sachin.maurya7666@gmail.com>
2022-10-08 10:57:41 -04:00

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==
`)