kyverno: [BUG] Mutating `image` with custom JMESPath function `regex_replace_all` overwrites all instances

Software version numbers State the version numbers of applications involved in the bug.

  • Kubernetes version: v1.21.3+k3s1
  • Kyverno version: v1.4.2-rc3

Describe the bug When using a mutate rule with regex_replace_all on a Pod with multiple containers, the mutated image name of the first container’s image is used to overwrite all subsequent container images.

To Reproduce Steps to reproduce the behavior:

  1. Apply the sample policy here.
  2. Apply this Pod definition with two containers.
apiVersion: v1
kind: Pod
metadata:
  annotations:
    annotation.corp.com/restrict1: foo1
  labels:
    app: busybox
  name: mypod
spec:
  automountServiceAccountToken: false
  containers:
  - name: nginx
    image: ghcr.io/nginx:1.28
  - name: busybox
    image: quay.io/busybox:1.1241
  1. See the mutation occur successfully in the logs and check the result.
  2. See the result:
$ k get po mypod -o yaml | yq e .spec.containers[].image -
myregistry.corp.com/nginx:1.28
myregistry.corp.com/nginx:1.28
  1. Notice that both images in the Pod were replaced with the same mutated image name rather than just the first.

Expected behavior Each image is mutated independently given the field’s original input.

Screenshots If applicable, add screenshots to help explain your problem.

Additional context This was initially described in this Slack thread and further fleshed out here. The first thread links to https://github.com/kyverno/kyverno/issues/2028 as the description but it’s not applicable.

About this issue

  • Original URL
  • State: closed
  • Created 3 years ago
  • Reactions: 4
  • Comments: 26 (22 by maintainers)

Most upvoted comments

@realshuting. I think I know where to look to fix the issue, so my high level estimate is half a day.

@sjentzsch @chipzoller Good to know. I’m closing the issue . Please feel free to reopen if you face any other issue regarding this. Thanks.

@sjentzsch can you please test with following image: vyankatesh/kyverno:foreach-initcontainer

apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: mutate-images
  annotations:
    pod-policies.kyverno.io/autogen-controllers: none
spec:
  background: false
  rules:
  - name: test
    match:
      resources:
        kinds:
        - Pod
    mutate:
      foreach:
      - list: "request.object.spec.containers"
        patchStrategicMerge:
          spec:
            containers:
            - name: "{{ element.name }}"
              image: |-    
                                {{ regex_replace_all('^[^/]+', '{{element.image}}', 'myregistry.corp.com' )}}
      - list: "request.object.spec.initContainers"
        patchStrategicMerge:
          spec:
            initContainers:
            - name: "{{ element.name }}"
              image: |-    
                                {{ regex_replace_all('^[^/]+', '{{element.image}}', 'myregistry.corp.com' )}}
apiVersion: v1
kind: Pod
metadata:
  annotations:
    annotation.corp.com/restrict1: foo1
  labels:
    app: busybox
  name: best
spec:
  automountServiceAccountToken: false
  containers:
  - name: busybox1
    image: busybox1:1.1241
  initContainers:
  - name: nginx
    image: nginx:1.1242    

result.yaml

apiVersion: v1
items:
- apiVersion: v1
  kind: Pod
  metadata:
    annotations:
      annotation.corp.com/restrict1: foo1
      kubectl.kubernetes.io/last-applied-configuration: |
        {"apiVersion":"v1","kind":"Pod","metadata":{"annotations":{"annotation.corp.com/restrict1":"foo1"},"labels":{"app":"busybox"},"name":"best","namespace":"default"},"spec":{"automountServiceAccountToken":false,"containers":[{"image":"busybox1:1.1241","name":"busybox1"}],"initContainers":[{"image":"nginx:1.1242","name":"nginx"}]}}
      policies.kyverno.io/last-applied-patches: |
        test.mutate-images.kyverno.io: replaced /spec/initContainers/0/image
    creationTimestamp: "2022-01-04T11:58:10Z"
    labels:
      app: busybox
    name: best
    namespace: default
    resourceVersion: "1461163"
    uid: bdc36ffb-7d75-4637-9c8c-2a139924045b
  spec:
    automountServiceAccountToken: false
    containers:
    - image: myregistry.corp.com/busybox1:1.1241
      imagePullPolicy: IfNotPresent
      name: busybox1
      resources: {}
      terminationMessagePath: /dev/termination-log
      terminationMessagePolicy: File
    dnsPolicy: ClusterFirst
    enableServiceLinks: true
    initContainers:
    - image: myregistry.corp.com/nginx:1.1242
      imagePullPolicy: IfNotPresent
      name: nginx
      resources: {}
      terminationMessagePath: /dev/termination-log
      terminationMessagePolicy: File