opa: In the rego playground, any() does not work as expected when used with functions

Expected Behavior

When using any() with a list of functions, any() should return true when any one of the functions returns true.

Actual Behavior

Behaves like all() and only returns true when all of the functions return true.

Steps to Reproduce the Problem

I have recreated this issue in the rego playground: https://play.openpolicyagent.org/p/50fMxIWvNV

package play

default allow = false

allow {
    any([
    	foo,
        bar
    ])
}

foo {
	false
}

bar {
	true
}

Additional

I’m not actually sure whether this is a bug with any(), a bug with the rego playground, or intended behavior.

About this issue

  • Original URL
  • State: closed
  • Created 3 years ago
  • Comments: 17 (10 by maintainers)

Most upvoted comments

I’m surprised to see that any() and all() are still in the built-in reference. I thought we hid them and deprecated them. Just write:

allow { foo }
allow { bar }
foo { false }
bar { true }

There isn’t really a good reason for any() to exist because it’s just expressing existential quantification which rule bodies already do by default…for example, if the body was instead allow { any(arr) } we could just say allow { arr[_] } and mean the same thing.

all() is slightly more useful because universal quantification isn’t first-class, however, I think that the behaviour that @anderseknert pointed out is worse than the usefulness of the built-in function. Once we support a keyword for universal quantification (e.g., every x) the need will go away.

You wouldn’t be able to create a set of undefined values, if that’s what you mean. Something like:

user_can_access := {
    "foo",
    input.bar,
}

Would have the whole set be undefined if input.bar was undefined.

Tangentially related, but these days it’d be considered better form to use in to check for membership:

# Prefer
true in my_set

# Over
my_set[true]

https://docs.styra.com/regal/rules/idiomatic/use-in-operator

What’s happening here is that the foo rule does not evaluate to false but is rather undefined (as that is the default for non-truthy rules) and the presence of an undefined condition in the allow rule halts evaluation of the rule and the default value is used.

If you set default foo = false you’ll see the allow rule evaluate to true as intended.