kyverno / kyverno

Cloud Native Policy Management
https://kyverno.io
Apache License 2.0
5.64k stars 858 forks source link

[BUG] Foreach fails the whole policy if the list is not there #2552

Closed Subreptivus closed 2 years ago

Subreptivus commented 2 years ago

Software version numbers

Describe the bug Trying to iterate over the non existent list with foreach leads to an error.

To Reproduce Steps to reproduce the behavior:

  1. Apply Policy:
    apiVersion : kyverno.io/v1
    kind: ClusterPolicy
    metadata:
    name: check-images
    spec:
    validationFailureAction: enforce
    background: false
    rules:
    - name: check-registry
    match:
      resources:
        kinds:
        - Pod
    validate:
      message: "unknown registry"  
      foreach:
        - list: "request.object.spec.containers"
          pattern:
             image: "nginx"
        - list: "request.object.spec.initContainers"
          pattern:
             image: "trusted-registry.io/*"
  2. Apply Deployment:
    apiVersion: apps/v1
    kind: Deployment
    metadata:
    labels:
    app: nginx
    name: nginx
    spec:
    replicas: 1
    selector:
    matchLabels:
      app: nginx
    template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - image: nginx
        name: nginx
  3. See that Deployment is blocked due to:
    check-images:
    autogen-check-registry: 'validation failed in foreach rule for validation error:
    unknown registry. Rule autogen-check-registry failed at path /image/'
  4. Check the logs to see that wrong item (it checks an item from containters against initContainers pattern) has been checked for pattern:
    I1018 12:21:41.303645       1 validation.go:434] EngineValidate "msg"="validation error" "kind"="Deployment" "name"="nginx" "namespace"="default" "policy"="check-images" "rule"="autogen-check-registry" "error"="resource value 'nginx' does not match 'trusted-registry.io/*' at path /image/" "path"="/image/"

    Expected behavior It would be logical to have the whole iteration skipped or silently ignore it if there is nothing to iterate over. @vyankyGH as you was one who was implementing the list for foreach it might be easier for you to extend it?

Additional context In our scenarios we don't know the contents of objects in advance, hence we're trying to use universal policies. As of now we're using constructions like contains(to_string(keys(request.object.spec.template.spec)), 'initContainers') yet foreach iterator makes policies much clearer and more readable, so we would prefer to migrate to fully migrate to it.

Trying to use Deny declaration leads to different error, and more specific and right then with Pattern. Policy example:

---
apiVersion : kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: check-images
spec:
  validationFailureAction: enforce
  background: false
  rules:
    - match:
        resources:
          kinds:
          - Pod
      name: validate-registries-per-pod-bare
      validate:
        message: Unknown image registry.
        foreach:
          - list: request.object.spec.containers
            deny:
              conditions:
                any:
                - key: >-
                   {{ regex_match('(?P<test>nginx)', '{{element.image}}') }}
                  operator: Equals
                  value: false
          - list: request.object.spec.initContainers
            deny:
              conditions:
                any:
                - key: >-
                    {{ regex_match('(?P<test>nginx)', '{{element.image}}') }}
                  operator: Equals
                  value: false

Using the same Deployment as above results in following error:

autogen-validate-registries-per-pod-bare: 'failed to evaluate list request.object.spec.template.spec.initContainers:
Unknown key "initContainers" in path'

But this error isn't stored in Kyverno's log, it's threw as a response to apply command.

welcome[bot] commented 2 years ago

Thanks for opening your first issue here! Be sure to follow the issue template!