What is Oso Cloud?
Oso Cloud is authorization as a service. It helps you model common authorization patterns, test your configuration, and check authorization decisions at runtime.
Concretely, it consists of the following pieces:
-
Workbench, a visual rules editor for describing who’s allowed to do what in your app. Under the hood, this is fully extensible and backed by Polar, our declarative configuration language for authorization.
-
Oso Cloud, the service (built in Rust 🦀), which stores authorization data (like roles) and responds to permission checks and related questions over an HTTP API. Our servers are replicated globally for <10ms latency and >99.99% uptime.
-
Clients for Node.js, Python, Go, Ruby, .NET (Java coming soon!)
-
Tools to give you short and tight feedback loops, like a VS Code extension, unit tests, a debugger, and logging.
This document explains how Oso Cloud works, answering questions like:
- What types of questions can your applications ask Oso Cloud?
- Where does Oso Cloud fit into your infrastructure?
- How does Oso Cloud store data about resources in your applications?
- How does Oso Cloud use permissions and resource data to make access decisions?
- How should your applications insert and update data in Oso Cloud?
What questions can Oso Cloud answer?
Many authorization questions take the form of simple permission checks. Oso Cloud can reliably respond to queries like “can user X perform action Y on resource Z?” in less than 10ms (excluding network latency).
Though permission checks are the core of an authorization service, Oso Cloud can answer more than just yes/no questions. Oso Cloud provides several other authorization APIs that let you answer questions like:
- What are all of the resources that User X can perform action Y on?
- What are all of the actions that User X can perform on resource Z?
- What are all of User X’s roles on any organization?
- What groups is User X a member of?
...and just about any other question you can think of.
Where does Oso Cloud fit into your infrastructure?
Oso Cloud is a managed service, meaning that Oso, Inc. runs it for you – we handle deployment, upgrades, and maintenance. Your applications talk to Oso Cloud over an HTTP API to perform authorization checks, query authorization-related data, or make changes to data stored in Oso Cloud. While your apps can communicate directly with the HTTP endpoints, we also provide wrapper clients (currently in Node, Python, Go, and Ruby).
Because just about every user action requires at least one authorization check, minimizing latency for an authorization service is crucial — production deployments of Oso Cloud are deployed in regions close to your infrastructure to keep latency low (<20ms total).
How does Oso Cloud store data?
In order to provide reliably fast answers to authorization checks, Oso Cloud stores data that is relevant to authorization. Oso represents data as facts that describe relationships between objects in your applications. Facts have a name and up to 5 arguments (they look a bit like function calls). The vast majority of facts will have 1-3 arguments. Some examples of facts in a GitHub-style application are:
- Bob can explicitly edit the "docs" repo:
has_permission(User{"bob"}, "edit", Repository{"docs"})
. - Bob is an owner of the Acme organization:
has_role(User{"bob"}, "owner", Organization{"acme"})
. - The Anvils repository belongs to the Acme organization:
has_parent(Repository{"anvils"}, Organization{"acme"})
. - The Oso repository is public:
is_public(Repository{"oso"})
.
Extending your data with a policy
Without a way to write logic over your data, you’d have to insert a single has_permission
fact for every single (Actor, Action, Resource)
combination that might be allowed in your apps — a combinatorial explosion that would quickly get out of hand!
Writing a policy allows you to derive permissions from other data (like roles, relationships, and attributes). Oso Cloud stores your policy (written in the Polar language) alongside your data and uses it to make access decisions.
A policy consists of rules that extend your facts. Oso Cloud uses the rules in your policy to infer other facts about your data. Some examples of rules that you might write in a policy for a GitHub-style application:
Any user that has a reader
role on a repository can perform the read
action.
has_permission(user: User, "read", repo: Repo) if has_role(user, "reader", repo);
A user that has an owner
role on a organization
inherits an reader
role on any repository belonging
to that organization.
has_role(user: User, "reader", repo: Repo) if has_role(user, "owner", org) and has_parent(repo, org);
Any user can perform the read
action on a public
repository.
has_permission(_: User, "read", repo: Repo) if is_public(repo);
Want to learn more about writing Polar rules? Check out the Polar syntax guide.
How does Oso Cloud answer authorization questions?
When your application asks an authorization question, like "can User:1
read Org:1
?", Oso Cloud uses your policy and facts to determine whether there is a match for has_permission(User:1, "read", Org:1)
:
Under the hood, Oso Cloud queries the Polar policy engine to determine all of the combinations of facts that would need to exist for the actor to have that particular permission — in other words, all of the ways that the actor might have that permission. Then it queries your facts to check if the actor actually has the facts that would grant the permission in any of those ways. If there is a match, Oso Cloud records why that match occurred along with the data that supported the decision, so that all decisions are auditable. Oso Cloud handles the complexity of indexing your facts so that these checks can happen efficiently.
Inserting facts into Oso Cloud
Oso Cloud exposes a fact management API with HTTP endpoints that let you create and delete facts. Your applications call these APIs on any user action that changes authorization-related data. Oso Cloud provides clients in Node, Python, Go, and Ruby to wrap the HTTP APIs, but you can also use the HTTP API directly to update data in Oso Cloud from any application.
Some examples of scenarios where a GitHub-style application might insert or delete facts:
- When an admin invites a collaborator to a repository, the app inserts a
has_role
fact, likehas_role(User{"some_coder"}, "collaborator", Repo{"anvils"})
. - When a repository is created, the app inserts a
has_parent
fact, likehas_parent(Repo{"anvils"}, Org{"acme"})
. - When a user leaves an organization, the app deletes the
has_role
fact linking them with that organization.
In situations where it doesn't make sense to store all authorization data in Oso Cloud, you can also send context facts at authorization time. For more details, read more about context facts.
Ready to get started?
- Sign up for a developer account (opens in a new tab) to try out the Oso Cloud APIs today.
- Read the quickstart guide to learn how to write your first policy.
Talk to an Oso Engineer
If you'd like to learn more about using Oso Cloud in your app or have any questions about this guide, connect with us on Slack. We're happy to help.