Elliot Pryde
Elliot Pryde

Reputation: 90

Assert that every string in a set has an associated key in an object

After reading through the Open Policy Agent introduction documentation a few times, I'm having trouble writing a rule which asserts that for every element in a set, the specified object has an associated key.

Here's a simplified example what I'm currently trying to get working

https://play.openpolicyagent.org/p/oWBumjRkWX

package example

my_object = {
  "lemon": ""
}

fruits = {
  "orange",
  "lemon",
  "banana"
}

has_key(x, k) { _ = x[k] }

default has_lemon = false
has_lemon = has_key(my_object, "lemon") # this works as you'd expect

default all_fruits_have_entries_in_my_object = false
all_fruits_have_entries_in_my_object { # this is never false for some reason
  some fruit
  fruits[fruit]
  has_key(my_object, fruit) # each fruit have a key in the my_object object
}

From what I understand, has_lemon should be false when the fruits does not contain the "lemon" element and I've tested that this is working. However, I also thought that the all_fruits_have_entries_in_my_object rule should evaluate to false here since my_object is missing keys for "orange" and "banana". Am I doing something stupid here?

Upvotes: 1

Views: 491

Answers (1)

Blokje5
Blokje5

Reputation: 5003

Rego is existentially quantified. That means rules are declared to check if there exists some fruit that is a key of the object.

One way to solve the problem: you can first gather all unexpected keys using a comprehension and then count the result:

package example

my_object = {
  "lemon": ""
}

fruits = {
  "orange",
  "lemon",
  "banana"
}

has_key(x, k) { _ = x[k] }

default has_lemon = false
has_lemon = has_key(my_object, "lemon") # this works as you'd expect

default all_fruits_have_entries_in_my_object = false
all_fruits_have_entries_in_my_object { # this is never false for some reason
  non_fruit_keys := { key | my_object[key]; !fruits[key] }
  count(non_fruit_keys) > 0
}

You can evaluate this example in the Rego Playground.

See also the documentation on Universal Quantification in Rego

Upvotes: 3

Related Questions