We’re excited to announce new policy test features that let you validate multiple permissions in a single assert
statement!
Oso Cloud policy tests are unit tests for your authorization code. You can define initial conditions and assert authorization results right in your policy code. This lets you confirm that your logic yields the expected results before you deploy changes to your authorization code.
In a (very) simple RBAC policy, that might look something like this:
actor User {}
resource Organization {
roles = ["member"];
permissions = ["view"];
# Members can view organizations
"view" if "member";
}
test "Organization permissions" {
setup {
# Alice is a member of the "acme" Organization
has_role(User{"alice"}, "member", Organization{"acme"});
}
# Alice can view the "Acme" organization, but not edit
assert has_permission(User{"alice"}, "view", Organization{"acme"});
assert_not has_permission(User{"alice"}, "edit", Organization{"acme"});
}
In smaller policies, it doesn’t take much test code to validate the different authorization paths. But as you add resources, roles, and relations, you need more assertions to make sure everything’s doing what you intend. Let’s add a couple roles and permissions to the policy and see what happens.
actor User {}
resource Organization {
roles = ["member", "admin", "owner"];
permissions = ["view", "edit", "delete"];
# Members can view organizations
"view" if "member";
# Admins can edit organizations
"edit" if "admin";
# Owners can delete organizations
"delete" if "owner";
# Admins can do everything members can do
"member" if "admin";
# Owners can do everything admins can do
"admin" if "owner";
}
With just two more roles and two more permissions, you have to test 9 conditions to make sure all the role/permission combinations work.
test "Organization permissions" {
setup {
# Alice is a member of the "acme" Organization
has_role(User{"alice"}, "member", Organization{"acme"});
has_role(User{"bob"}, "admin", Organization{"acme"});
has_role(User{"charlotte"}, "owner", Organization{"acme"});
}
# Alice can view the "Acme" organization, but not edit or delete
assert has_permission(User{"alice"}, "view", Organization{"acme"});
assert_not has_permission(User{"alice"}, "edit", Organization{"acme"});
assert_not has_permission(User{"alice"}, "delete", Organization{"acme"});
# Bob can view or edit the "Acme" organization, but not delete
assert has_permission(User{"bob"}, "view", Organization{"acme"});
assert has_permission(User{"bob"}, "edit", Organization{"acme"});
assert_not has_permission(User{"bob"}, "delete", Organization{"acme"});
# Charlotte can view, edit, and delete the "Acme" organization
assert has_permission(User{"charlotte"}, "view", Organization{"acme"});
assert has_permission(User{"charlotte"}, "edit", Organization{"acme"});
assert has_permission(User{"charlotte"}, "delete", Organization{"acme"});
}
You can see how this can get unwieldy as you add new assert
statements to your tests.
Testing permissions in bulk
To help you keep your tests concise as your policy grows, we’ve introduced two new capabilities:
- Variables in
assert
statements - The
iff
operator
These let you write a single assertion that tests multiple permissions. Let’s look at some examples:
Instead of writing 3 individual assert
statements to confirm that alice
can only read
the organization, we can instead write this single statement:
assert has_permission(User{"alice"}, action: String, Organization{"acme"}) iff action in ["view"];
This simultaneously validates that alice
has the view
permission and that alice
doesn’t have the edit
or delete
permissions.
You can even use wildcards as variables. Suppose you have a global admin role that should always have every permission, including permissions that don’t exist today but that you may add in the future. You can test that with a wildcard:
assert allow(User{"superadmin"}, _action: String, Organization{"acme"});
This will confirm that the superadmin
user will always have permission to perform any action on the acme
repository.
The VSCode extension and web editor will now offer a quickfix to update the permissions in the iff
clause. So if you add a role or change a permission, you can update any affected test with a single click.

Start simplifying your tests
With assert
variables and the iff
operator, you can make your tests easier to read and maintain. For more details and examples, check out our policy testing docs. If you have questions or ideas about how we can make policy tests even better, come talk with us on Slack! We’re always up for a policy testing conversation.