Intro to Polar + Oso
In this guide, we'll cover:
- Basic authorization policy construction
- Managing facts stored in Oso Cloud
- Using the
oso-cloud
binary to understand how authorization will work in your application
Note that this is meant only to be a simple tutorial. This guide does not include best practices for using Oso in production!
Setup
To get started, you'll need a few things:
- An Oso Cloud account. You can get one at https://ui.osohq.com (opens in a new tab).
- The Oso Cloud CLI.
Be mindful when choosing which environment you want to use through the CLI. This tutorial asks you to add facts to your Oso account, which you will likely want to delete when you're done.
Frame of reference
Every Oso deployment consists of a policy, data, and a client. The shortest way to describe Oso is in these terms: Oso makes authorization decisions based on your policy with the data it's been provided whenever a client asks.
In this tutorial, we'll store our policy in Oso Cloud, and then make some other decision's for simplicity's sake:
Component | Tutorial version |
---|---|
Data | We'll store all data in your Oso Cloud's centralized database. This is convenient, but does not necessarily reflect what you will do when using Oso in production. |
Client | Rather than using a full-fledged application, we'll use oso-cloud tool to interact with the Oso Cloud API. |
These are decisions we're making simply because this is a tutorial. In production, you will almost certainly make other choices.
Build a policy
Policies contain the rules you want Oso to abide by when making authorization decisions, such as "only admins and account owners can edit accounts." All users (including you!) write policies in Polar.
Define resources
When building a policy, a good place to start is to determine the objects that exist in your domain model (which is a fancy way of saying how you express what your application does within Polar).
Here's an example of a bare bones policy that only defines objects.
actor User {}resource Organization {}
To follow along, enter the Oso Cloud Rules editor (opens in a new tab), and paste in the policy.
In Polar, we refer to these as "resources." You can define resources with this kind of syntax:
(actor|resource) <ResourceName> {}
This is to say you define whether the resource is an actor
or a resource
,
give the resource a name, and then end the definition with curly braces. In this
tutorial, we won't bother with placing anything inside the curly braces, though
rest assured they serve a purpose.
What's the difference between actor
and resource
?
In short, actor
s represent the "who" of your policy and resource
s represent
the "what". When your client makes an authorization request, it's typically
asking, "Can this actor
perform some action on this resource
?"
We call both actor
s and resource
s "resources" because actor
s are just a
special type of resource
. This shouldn't affect much for you right now, but if
you are curious, see Polar: Polymorphism.
Define rules
Now that you have resources in your policy, you can describe rules to correlate them. For this tutorial, we'll model these resources as having role-based access control (RBAC).
In an RBAC model, you assign each user a set of roles which determine the actions they may perform on resources.
To model an RBAC relationship, you can define a few rules:
# Members can view organizationshas_permission(user: User, "view", organization: Organization) if has_role(user, "member", organization);# Admins can edit organizationshas_permission(user: User, "edit", organization: Organization) if has_role(user, "admin", organization);# Admins inherit all permissions from membershas_role(user: User, "member", organization: Organization) if has_role(user, "admin", organization);
You can paste these right below the lines defining Actor
and Resource
, and
then Deploy the policy.
You might be able to infer this, but defining a rule requires:
- A name (also known as a predicate)
- A set of arguments to evaluate whether or not the rule passes
- A conditional expression to evaluate if the rule passes or not
A few notes might help you understand these rules a little more clearly:
- Rules often follow something akin to the subject verb object format common
in English. For example,
has_permission(user: User, "view", organization: Organization)
is equivalent to a rule stating "Users (subject) can view (verb) an organization (object)", followed by a qualification. - While your rules' actors and resources are defined in the policy, actions and roles just use literal strings. As you work with Polar more, you'll see this convention used everywhere.
That's it for the policy; you'll now learn more about managing data used to make authorization decisions.
Use authorization data
With your policy deployed, use the oso-cloud
CLI to make an authorization
request. We'll see if the user Alice can view the organization Acme.
oso-cloud authorize User:alice view Organization:acme
You'll receive a Denied
response. Why? Oso is a pessimistic system and without
knowing anything about the user Alice, Oso will not authorize them to do
anything. In fact, with our given policy, Oso will not authorize anything at
all until we start providing data.
Facts as data
Facts are simply rules that are unconditionally true. For example, you could imagine a fact:
capital_city("New York", "Albany");
You'll know that it's a fact because the last argument to the predicate isn't
followed by an if
clause.
Given the RBAC model in your policy, you'll need to provide facts expressing the
roles that users have at an organization. We can do this with oso-cloud
through the tell
subcommand.
oso-cloud tell has_role User:alice admin Organization:acme
You can ensure the client wrote the fact using the get
subcommand, which
returns all facts from an environment.
oso-cloud get
Where should I store facts?
You might have noticed that facts look like rules, and that rules are stored in your policy. Does that mean you should store facts in your policy?
In short, no. While you could place facts in your policy, it isn't ideal. For example, you wouldn't want an admin account to have to deploy your policy every time a new user signs up.
Instead, Oso expects you to manage facts as data. That can take many different shapes, as we explain and explore throughout the docs. For simplicity in this tutorial, though, we'll simply store the facts in a database available inside your Oso account.
Authorize requests using data
Now that your account has fact data in addition to its policy, we can begin authorizing requests.
Try your last request again, authorizing Alice to view Acme.
oso-cloud authorize User:alice view Organization:acme
You'll receive an Allowed
response. But why is that?
As you learned earlier, Polar is a logic programming language, which means it's able draw inferences based on your rules and data. In this case:
- We want to see if
User:alice
has theview
permission onOrganization:acme
. - Users have the
view
permission on an organization if they have themember
role. - Users have the
member
role if they have theadmin
role on the organization. User:alice
has the roleadmin
onOrganization:acme
.
This means that Polar was able to infer through a series of rules that
User:alice
's role of admin
grants her the view
permission on
Organization:acme
.
What about the delete
action?
oso-cloud authorize User:alice delete Organization:acme
You'll receive the Denied
response because Polar doesn't know anything about
delete
actions; it defaults to prohibiting anything you haven't allowed in
your policy.
You can imagine the same scenarios for users without roles, or roles that are not referenced in the policy, or on organizations which the user does not have a role on. The number of things that are disallowed is nearly endless––that's how Oso keeps your application safe.
Clean up
Because we added facts to your account's centralized fact database, you likely want to remove them. The simplest and most precise way is through the Oso Cloud UI.
- Go to the Facts tab in Oso Cloud (opens in a new tab).
- Click the fact
has_role(User, "admin", Organization)
. - Next to the facts you want to remove from your account, click Delete.
Up Next
Now that you know more about Polar, see Modeling in Polar.