Get Started
Quickstart

Quickstart

This guide will walk you through deploying your first policy and making your first authorization checks with Oso Cloud. You’ll use the Oso Cloud CLI, which is a thin wrapper around the HTTP API. If you want to go through this guide with an Oso engineer, schedule a 1x1.

Get Your Oso API Key

Login to your Oso Cloud Sandbox account at https://cloud.osohq.com/. The UI will prompt you to create an API Key that you can use to experiment with Oso Cloud. Set the OSO_AUTH environment variable to your API key:

$ export OSO_AUTH=<your_oso_api_key>

Setup the Oso CLI

Install the Oso Cloud CLI (and make sure that oso-cloud is in your system PATH):

$ curl -L https://cloud.osohq.com/install.sh | bash

Verify the Oso Cloud CLI is installed and that your Oso API Key is properly set:

$ oso-cloud inspect Actor:hello
(no results)

Write your first policy

Create a new file named quickstart.polar and add the following code:

actor User {}
 
resource Organization {
  permissions = ["read"];
  roles = ["owner"];
 
  "read" if "owner";
}

The logic here is pretty straightforward. We declare types User and Organization, and we declare that actors possessing the owner role on organizations are allowed to perform the read action on those organizations.

The "read" if "owner"; line is a shorthand syntax that declares the following rule:

has_permission(actor: Actor, "read", resource: Organization) if
  has_role(actor, "owner", resource);

You can read more about shorthand rules.

Load your policy file to your Oso Cloud server with the oso-cloud policy command:

$ oso-cloud policy quickstart.polar
Policy successfully loaded.

The server is now ready to authorize requests. Try to authorize an action: User bob is trying to read Organization acme.

$ oso-cloud authorize User:bob read Organization:acme
Denied.

No dice. There’s no data that indicates that bob can read Organization acme. Oso Cloud is deny-by-default, meaning that you must explicitly allow an action using your policy logic and the right authorization data.

You have the policy logic in place (in quickstart.polar) — now you just need data.

Grant Bob an owner role:

$ oso-cloud tell has_role User:bob owner Organization:acme
Writing has_role(User:bob, String:owner, Organization:acme) to Oso at https://cloud.osohq.com/
Success.

Now, run the same check again:

$ oso-cloud authorize User:bob read Organization:acme
Allowed.

Cool. Bob is an owner of the Acme organization, so he is allowed to read the organization. This is the basic idea behind Oso Cloud: you define implications in your policy (”read” if “owner”, etc), and then you insert your roles and relations data. The combination of those things determine which actions are allowed.

Relations: a more complex policy

It’s time to add some complexity to your policy and introduce the concept of relations. Edit quickstart.polar to contain the following:

actor User {}
 
resource Organization {
  permissions = ["read"];
  roles = ["owner"];
 
  "read" if "owner";
}
 
resource Repository {
  permissions = ["push"];
  roles = ["maintainer"];
  relations = { parent: Organization };
 
  "maintainer" if "owner" on "parent";
  "push" if "maintainer";
}

This added a Repository type which belongs to the Organization type (through a relation called parent). The rule "maintainer" if "owner" on "parent"; means that an owner role on an organization implicitly grants the maintainer role on any repository related to that organization.

Now, update our policy in Oso Cloud:

$ oso-cloud policy quickstart.polar
Policy successfully loaded.

While Bob is still an owner of the Acme organization, he cannot push to any repositories yet:

$ oso-cloud authorize User:bob push Repository:anvils
Denied.

There is not yet any repository-related data in Oso Cloud that would grant any repository permissions. Now, create a parent relation between Organization:acme with Repository:anvils using oso-cloud add relation:

$ oso-cloud tell has_relation Repository:anvils parent Organization:acme
Writing has_relation(Repository:anvils, String:parent, Organization:acme) to Oso at https://cloud.osohq.com/
Success.

Now, the same authorization check (can User:bob perform the push action on Repository:anvils?) should succeed:

$ oso-cloud authorize User:bob push Repository:anvils
Allowed.

The action was allowed because of two “edges” in the graph:

  1. An edge connecting User:bob to Organization:acme with the owner role.
  2. An edge connecting Repository:anvils to Organization:acme with the parent relation.

Together with the policy in quickstart.polar, Oso is able to determine that User:bob has an implicit maintainer role on Repository:anvils and therefore is granted push permission.

Repository-specific roles

You can also give a user a role directly on a repository! Imagine that Bob has been made a maintainer of Repository:oso, which belongs to a different organization:

$ oso-cloud tell has_role User:bob "maintainer" Repository:oso
Writing has_role(User:bob, String:maintainer, Repository:oso) to Oso at https://cloud.osohq.com/
Success.

Now, list all of the repositories that Bob can perform the push action on:

$ oso-cloud list User:bob push Repository
[anvils, oso]

Two results! Bob can push to Repository:anvils because of his role on Organization:acme, and also to Repository:oso because of a direct role on the oso repository.

Try adding more edges and see how they affect results! You can also change around the policy in quickstart.polar to add additional roles, relationships, and resource types.

What's next?

Take a look at the API docs to learn more about how to integrate Oso with your app.

If you have any questions, or would like to talk through any details of your implementation, schedule a 1x1 with an Oso Engineer.