Manage Authorization Data
Sync and Export Data

Sync and Export Data

Oso Cloud uses data from your application to make authorization decisions. Your authorization rules declare abstract logic like anyone with the "member" role on an organization is allowed to view it, but it doesn't say which users have the "member" role on which organizations. That's where authorization data comes in, in the form of facts.

Facts are pieces of authorization data that your application sends to Oso Cloud. Facts consist of a name and generally 2-3 arguments. Here are some examples of facts:


# Alice has the "member" role on the ACME organization.
has_role(User{"Alice"}, "member", Organization{"ACME"});
# The Anvils repository's parent organization is ACME.
has_relation(Repository{"Anvils"}, "parent_organization", Organization{"ACME"});

The Oso Cloud Data Model guide contains more details about what facts are. The rest of this guide focuses on managing facts in Oso Cloud from development to production.

Sync Facts in Development

Whether starting fresh or making changes to existing rules, the quickest way to iterate on the facts stored in Oso Cloud is via the Fact Schema (opens in a new tab) in the UI. The Fact Schema lists the types of facts referenced in your policy; these are the types of facts Oso Cloud expects you to send.

Fact Schema

To add a new fact, click + Add next to the type of fact you want to add. To remove an existing fact, click ▼ Show matching facts and then the Delete button next to the fact you want to delete.

Sync Facts in Production

In production, all fact management should happen via Oso Cloud's Bulk API.

Add and Remove Facts

Whenever you insert, update, or delete authorization-relevant data in your application, you should use Oso Cloud's Bulk API to mirror that update in Oso Cloud.

💡

This "dual writes" approach is similar to updating an Elasticsearch index to provide up-to-date search results. Oso Cloud is a fast and flexible index for your authorization data that's optimized for producing sub-millisecond authorization decisions.

For example, in our GitCloud (opens in a new tab) example app, when a user creates a new repository, we send a pair of facts to Oso Cloud:


def create_repository(org_id):
org = Organization(org_id)
repo = Repository(payload["name"], org)
# Open a transaction to persist the repository to our datastore.
session.add(repo)
# Send facts to Oso Cloud.
oso.bulk([
# No facts to remove:
delete=[],
# Two facts to add:
tell=[
# The parent organization of `repo` is `org`.
["has_relation", repo, "organization", org],
# The creating user gets the "admin" role on the new repository.
["has_role", current_user, "admin", repo]
]
])
# Once the bulk update to Oso Cloud succeeds, commit the transaction.
session.commit()
return repo.as_json(), 201

When deleting a repository, the process is identical, but the facts in the Bulk API call go in the removal array. Additionally, we can use wildcards to remove all facts matching a pattern:


oso.bulk([
# Two fact patterns to remove:
delete=[
# Remove all `has_relation` facts for the repository.
["has_relation", repo, None, None],
# Remove all `has_role` facts for the repository.
["has_role", None, None, repo]
],
# No facts to add:
tell=[]
])

Wildcards are represented as None in Python, null in JavaScript, nil in Ruby, and so on.

💡

When creating new resources, send corresponding facts to Oso Cloud before closing the local transaction. This way, we tell the user we’ve created the new resource once they’re able to access it.

When deleting existing resources, remove corresponding facts from Oso Cloud after closing the local transaction. We wait to remove access until we’re sure the resource no longer exists.

To add and remove facts in a single transaction — for example, when updating a user's role from "member" to "admin" — use the Bulk API:


oso.bulk([
# Remove all existing roles for the user:
delete=[["has_role", user, None, repo]],
# Add the new role:
tell=[["has_role", user, "admin", repo]]
])

The Bulk API processes fact removals before additions, so after the above call the user will have exactly one role on the repository: "admin".

Keep Facts in Sync

To ensure authorization data remains in sync with application data, it's good practice to periodically refresh the facts in Oso Cloud when modifying resources locally. For example, when updating a repository, use the Bulk API to re-sync all facts:


oso.bulk([
# Remove existing facts:
delete=[
# Remove all `has_relation` facts for the repository.
["has_relation", repo, None, None],
# Remove all `has_role` facts for the repository.
["has_role", None, None, repo]
],
# Add back the same facts:
tell=[
["has_relation", repo, "organization", org],
["has_role", current_user, "admin", repo]
]
])

We’re working on new solutions for keeping data synchronized between your application and Oso Cloud. Reach out if you’re interested in learning more:

Export Facts from Oso Cloud

You own your data and can take it with you anytime. Use the Get API to export all of your facts:


# Export all `has_role` facts
$ oso-cloud get has_role _ _ _
Retrieving has_role(_, _, _) from Oso at https://cloud.osohq.com/
has_role(User:Alice, String:admin, Repository:Anvils)
...
# Export all `has_relation` facts
$ oso-cloud get has_relation _ _ _
Retrieving has_relation(_, _, _) from Oso at https://cloud.osohq.com/
has_relation(Repository:Anvils, String:organization, Organization:ACME)
...

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.

Get started with Oso Cloud →