Polar Facts as Data
Polar, powered by Oso Cloud, can consider facts stored outside your policy when making authorization decisions. In Oso, this is often referred to as "data."
It's important to note that storing facts as data does not necessarily have semantic meaning when making authorization decisions; if you stored the facts as data or within your policy, the decisions Polar makes would be the same.
Instead, choosing to store facts as data impacts secondary features like the mutability of your environment, performance, and where authorization decisions ultimately occur. For more details about those considerations, see:
- Rules + Facts in the Polar reference docs, which primarily deals with storing rules in your policy.
- Facts: the Oso Cloud Data Model in the Oso conceptual docs, which deals with storing facts as data in Oso Cloud.
Construction
Facts stored as data have a construction similar to generic rules, but:
- They must be unconditionally true, i.e. they cannot have an
if
clause after defining their parameters. - All parameter values must be primitive
values (e.g.
3
) or object literals (e.g.User{"alice"}
).
For example, the following fact could be stored as data:
integer_string_eq(2, "two");
Storage
Where you store facts and how you manage them is a concern of Oso Cloud, moreso than of Polar. For more detail, see:
Type inference
Oso infers type information about facts based on how the facts are used in your policy. For example, with a policy like this:
has_permission(user: User, "pet", dog: Dog) if are_friends(user, dog);
Oso infers that it should only accept are_friends
facts with two arguments,
where the first argument is a User
and the second is a Dog
.
Oso uses these inferred fact types to prevent you from inserting invalid facts.
For example, with the above policy, if you attempted to tell
Oso the fact are_friends(User:alice, Rabbit:peter)
, Oso would reject the
fact, because your policy doesn't use facts with the type
are_friends(User, Rabbit)
. Additionally, Oso prevents you from accidentally
omitting an argument – Oso will reject are_friends(User:alice)
, because the
second Dog
argument is missing.
Oso also uses these inferred types to prevent you from inserting facts that it
doesn't know about. This makes it impossible to accidentally insert a fact with
a misspelled predicate, like ar_frens(User:alice, Dog:fido)
.
Overriding inferred types
What if you want Oso Cloud to store a fact that isn't used anywhere in your policy? For
instance, maybe you want to tag users by inserting has_tag
facts into Oso,
anticipating that you might use tags in your policy someday. Or maybe you
already tag users and use those in your policy, but you want to start tagging
organizations, too.
In these cases, you can use the declare
statement to force Oso to accept a certain fact type:
declare has_tag(User, Tag);
This will make Oso accept facts like has_tag(User:alice, Tag:is-cool)
, even
if your policy doesn't currently use facts like this.
You can have multiple declare
statements for a given fact predicate:
declare has_tag(User, Tag);declare has_tag(Dog, Tag);declare has_tag(Tag, Tag, Tag); # I heard you like tags.
These declare
statements form a union type-- as long as a fact matches
one of the declared or inferred types, Oso will accept it.
You never need to use a declare
statement for fact types that are used in
your policy. declare
statements are only for making Oso accept fact types
that your policy never uses. Most policies will not use declare
statements.
Up next
- Facts: the Oso Cloud Data Model to understand how to store facts
- Rules + facts to understand how facts are used to evaluate your policy.
Talk to an Oso engineer
If you want to learn more about Polar, schedule a 1x1 with an Oso engineer. We're happy to help.