Office Hours: ACL-aware filtering in your own database with SpiceDB and AuthZed Materialize

Top-3 Most Used SpiceDB Caveat Patterns

/assets/team/victor-roldan-betancort.jpg
February 16, 2023|4 min read

In preparation for the general availability of SpiceDB Caveats, planned for the next 1.17.0 release, we thought it would be cool to share some of the recurrent use cases we’ve seen for caveats out in the wild. Caveats allow augmenting your SpiceDB schema with dynamic logic written in Google's CEL.

Here are top-3 most used caveat patterns:

🥉 IP Allowlists

One common use case is to implement conditional access based on the originating IP of an inbound request. Organizations that want to tighten employee access to their systems make sure they can only perform requests from a range of allowed IPs, e.g. as a CIDR block. GitHub’s IP Allowlists functionality provides a good real-world example.

SpiceDB offers first-class support for IP Allowlists via two built-in pieces of functionality: the ipaddress type and the in_cidr method. Let’s see this in action by modeling GitHub’s IP Allowlists! (Playground Link)

definition user {}

caveat expected_ip_range(user_ip ipaddress, cidr string) {
   user_ip.in_cidr(cidr)
}

definition organization {
   relation resources: repository
   relation members: user
   /*
     ip_allowlist_policy is a caveated relationship to members of the organization based on IP Allowlists, and can
     be disabled by setting the relationship to user:*
    */
   relation ip_allowlist_policy: organization#members with expected_ip_range| user:*

   permission policy = ip_allowlist_policy
}

definition repository {
   relation owner: organization | user
   relation reader: user
   relation writer: user
   relation adminer: user

   permission read = (reader + write) & owner->policy
   permission write = (writer + admin) & owner->policy
   permission admin = adminer & owner->policy
}

🥈 Session-bound permissions

Another recurrent use of caveats is implementing access conditioned to the existence of a user session or properties of their session: Enforce a policy to allow access to resources only when users have 2FA set up Authorized based on attributes of SAML Session tags or JWT token claims

In the case of JWTs, after the client application verifies an incoming token, it could forward a subset of the claims as part of the SpiceDB request context to enrich the authorization operation.

One example could be access attenuation based on the audience claim (aud). A user has been granted admin permissions on a highly sensitive resource (e.g. administrative UI), but in order to be authorized we also need to make sure the web session was actually intended for the expected domain.

In this example the client application would write relationships with a stored value for the expected_aud caveat context key, which would take precedence over anything coming from the client-side. Here is the (Playground Link):

definition user {}
definition organization {}

caveat valid_session_audience(aud string, expected_aud string) {
   aud == expected_aud
}

definition control_plane {
   relation granted: user with valid_session_audience

   permission admin = granted
}

🥇 Time-Bound Permissions

And number one goes to limiting access based on time criteria! Organizations use this approach to further reduce the attack surface, in line with the principle of least privilege. This can be the likes of: only allowing employee access during working hours providing temporal access to support staff for a few hours to troubleshoot a customer problem Improving security posture by making all employee entitlements self-expiring

Since we’ve started with the well-understood GitHub model as an example, let’s see how a hypothetical temporal repository access grant could be implemented (Playground Link):

definition user {}
definition organization {}

caveat temporal_grant(grant_duration duration, current_timestamp string, grant_timestamp string) {
   timestamp(current_timestamp) - timestamp(grant_timestamp) < grant_duration
}

definition repository {
   relation owner: organization | user
   relation reader: user | user with temporal_grant
   relation writer: user | user with temporal_grant
   relation adminer: user | user with temporal_grant

   permission read = reader + write
   permission write = writer + admin
   permission admin = adminer
}

Wrap-up

So there you go, the top-3 most used caveat patterns for SpiceDB! 🏆 If you haven’t yet, feel free to check out the documentation 📖 and tinker with it in our recently released playground support! Have a question? Check out the Discord, where we and the community are discussing all things SpiceDB

Additional Reading

If you’re interested in learning more about Authorization and Google Zanzibar, we recommend reading the following posts:

Get started for free

Join 1000s of companies doing authorization the right way.