Writing Facts
Facts only apply to rules that exist in your policy. Oso Cloud prevents you from uploading facts that are not supported by your policy. Therefore, when you begin writing facts you should have in mind the rule that you are writing facts for. The rule itself provides much of the structure and information you’ll need to write your facts.
From Rules to Facts
In this section we'll cover some common variations of rule and their corresponding facts. The process for creating facts from rules is the same regardless of the rule. With one exception: short-form rules.
With shorthand rules there is a trade-off between the simplicity of writing the rule and the information that gets thrown under the hood. When working with shorthand rules, use the equivalent expanded rule to guide you in writing your facts.
How Facts and Rules are Related
Rule Statements
Here is a simple rule statement with three arguments.
<RULE_NAME> ( var1: $Type1, var2: $Type2, var3: $Type3);
A fact related to this rule must have the same name as the rule. Also, the arguments must have the same order and type as the rule.
Example Fact
oso-cloud tell <RULE_NAME> $Type1:ID-1 $Type2:ID-2 $Type3:ID-3
Conditional Rules
In this example we've added a condition to the rule.
<RULE_NAME> ( var1: $Type1, var2: $Type2, var3: $Type3) if <CONDITIONAL_RULE_1> (var1: $Type1, var4: $Type4, var3: $Type3);
When you write facts for conditional rules you have two options:
-
Write a fact that is explicit to the rule itself (<RULE_NAME>).
Example Fact
oso-cloud tell <RULE_NAME> $Type1:ID-1 $Type2:ID-2 $Type3:ID-3
-
Write a fact, or set of facts, that satisfy all the conditions for the rule (the rules that come after
if
).Example Fact
oso-cloud tell <CONDITIONAL_RULE_1> $Type1:ID-1 $Type4:ID-2 $Type3:ID-3
You have the flexibility to use whatever facts you want to achieve your authorization needs. However, the authorization patterns you chose will guide you to the best facts to add to Oso Cloud.
Facts that Grant Role Based Permissions
...resource Organization { ... "write" if "admin";}
This is a shorthand roles based access pattern. The rule is contained within a resource block and it only applies to resources matching its type. In this example, the type is Organizations.
Equivalent Longhand Rule
has_permission(actor: Actor, "write", org: Organization) if has_role(actor, "admin", org);
These rules only require the appropriate has_role
fact to exist.
You'll write facts that:
- Use any actor type defined in your policy
- Use the role defined in the conditional rule (in this example: admin)
- Use only the resource type defined in the rule (in this case Organization)
Example Fact
oso-cloud tell has_role User:bob admin Organization:resource_1
Facts that Grant Role Based Permissions with Relations
... resource Organization { ... } resource Repository { ... relations = {parent_org: Organization}; "write" if "admin" on "parent_org"; }
This is a shorthand roles based access pattern that grants permissions based on a resource-resource relationship.
Equivalent Longhand Rule
has_permission(actor: Actor, "write", repo: Repository) if org matches Organization and has_relation(repo, "parent_org", org) and has_role(actor, "admin", org);
Unlike the previous example, this rule has two required conditional rule statements:
org matches Organization
has_role(actor, "admin", org)
As a result, two supporting facts are needed: the familiar has_role
fact and has_relation
fact.
You'll write facts that:
- Use any actor type defined in your policy
- Use the role defined in the rule conditions (in this example: admin)
- Use the resource type defined in the rule conditions (in this case Organization)
- Specifies the relationship between two resources (in this case the parent_org relationship between a Repository and an Organization)
Example Facts (both are required)
oso-cloud tell has_role User:bob admin Organization:org_1
oso-cloud tell has_relation Repository:my_repo parent_org Organization:org_1
Facts that Inherit Roles from Relationships
...resource Organization { ...}resource Repository { ... relations = {parent_org: Organization}; "admin" if "admin" on "parent_org";}
This is a shorthand roles based access pattern that inherits roles based on a resource-resource relationship.
Equivalent Longhand Rule
has_role(actor: Actor, "admin", repo: Repository) if org matches Organization and has_relation(repo, "parent_org", org) and has_role(actor, "admin", org);
The two required conditional rule statements are:
has_relation(repo, "parent_org", org)
has_role(actor, "admin", org)
You'll write facts that:
-
Use any actor type defined in your policy
-
Use the role defined in the rule conditions (in this example: admin)
-
Use the resource type defined in the rule conditions (in this case Organization)
-
Specifies the relationship between two resources (in this case the parent_org relationship between a Repository and an Organization)
Example Facts (both are required)
oso-cloud tell has_role User:bob admin Organization:org_1
oso-cloud tell has_relation Repository:my_repo parent_org Organization:org_1
Facts that Inherit Roles from Groups
has_role(user: User, role: String, resource: Resource) if group matches Group and has_group(user, group) and has_role(group, role, resource);
This is a custom roles pattern that inherits roles based on an actor-actor relationship. This rule has two required conditional rule statements:
has_group(user, group)
has_role(group, role, resource)
You'll write facts that:
- Use only the actor type defined in the rule (in this case User)
- Assign custom roles (any string is valid)
- Use any resource type defined in your policy
- Establishes membership of a User to a Group
- Defines the role the group has on a particular resource
Example Facts (both are required)
oso-cloud tell has_role group:my_group admin Organization:org_1
oso-cloud tell has_group User:bob my_group
Additional Resources
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.