Search code examples
open-policy-agentrego

Rego to check if a map, contains a key that is defined in a separate list


Given a map, we would like to check if any of the keys in that map matches any item in a list.

In the case of kubernetes annotations being the "map":

metadata:
  annotations:
    external-dns.alpha.kubernetes.io/hostname: something
    external-dns.alpha.kubernetes.io/ttl: 60

Let's say that we want to trigger a violation if external-dns.alpha.kubernetes.io/ttl is used. For that, we would add that item in a list of denied annotations. The value is not relevant.

denied:
  - external-dns.alpha.kubernetes.io/ttl
  - other-denied-annotation-1
  - other-denied-annotation-2

Violation should trigger if any of the denied annotations is present in the .metadata.annotations of the resource.

Although I searched and tried it, I was not able to. The already asked questions do not address this exactly and I was not able to make it work. We are using Gatekeeper.


Solution

  • You'd normally use a set for the "deny" list, and then simply check each annotation for membership:

    package play
    
    import future.keywords
    
    denied_annotations := {
        "external-dns.alpha.kubernetes.io/ttl",
        "other-denied-annotation-1",
        "other-denied-annotation-2",
    }
    
    deny[reason] {
        # iterate over all annotations in input
        input.review.object.metadata.annotations[key] 
    
        # for each key, check if it's present in deny list -
        # if using older OPA, you may need to use
        # `denied_annotations[key]` instead, which does the same
        key in denied_annotations       
        
        reason = sprintf("%s in denied annotations", [key])
    }
    

    Playground example here.