Python Authorization Library

oso is available as a package for use in Python applications.

Code-level documentation is here.

To install, see installation instructions.

Framework integrations

oso provides integrations for popular frameworks:

Working with Python Objects

oso’s Python authorization library allows you to write policy rules over Python objects directly. This document explains how different types of Python objects can be used in oso policies.

Note

More detailed examples of working with application classes can be found in Policy Examples.

Class Instances

You can pass an instance of any Python class into oso and access its methods and fields from your policy (see Application Types).

Python instances can be constructed from inside an oso policy using the New operator if the Python class has been registered using either the register_class() method or the polar_class() decorator. An example of this can be found here.

Numbers and Booleans

Polar supports both integer and floating point numbers, as well as booleans (see Primitive Types)

Strings

Python strings are mapped to Polar Strings. Python’s string methods may be accessed from policies:

policy.polar
allow(actor, action, resource) if actor.username.endswith("example.com");
app.py
user = User()
user.username = "alice@example.com"
assert(oso.is_allowed(user, "foo", "bar))

Warning

Polar does not support methods that mutate strings in place. E.g. capitalize() will have no effect on a string in Polar.

Lists

Python lists are mapped to Polar Lists. Python’s list methods may be accessed from policies:

policy.polar
allow(actor, action, resource) if actor.groups.index("HR") == 0;
app.py
user = User()
user.groups = ["HR", "payroll"]
assert(oso.is_allowed(user, "foo", "bar"))

Warning

Polar does not support methods that mutate lists in place. E.g. reverse() will have no effect on a list in Polar.

Likewise, lists constructed in Polar may be passed into Python methods:

policy.polar
allow(actor, action, resource) if actor.has_groups(["HR", "payroll"]);
app.py
class User:
   def has_groups(self, groups):
      """ Check if a user has all of the provided groups. """
         for g in groups:
            if not g in self.groups:
               return False
         return True

user = User()
user.groups = ["HR", "payroll"]
assert(oso.is_allowed(user, "foo", "bar))

Dictionaries

Python dictionaries are mapped to Polar Dictionaries:

policy.polar
allow(actor, action, resource) if actor.roles.project1 = "admin";
app.py
user = User()
user.roles = {"project1": "admin"}
assert(oso.is_allowed(user, "foo", "bar))

Likewise, dictionaries constructed in Polar may be passed into Python methods.

Iterables

Oso handles non-list/dictionary iterable Python objects by evaluating each of the object’s elements one at a time. Generator methods are a common use case for passing iterables into oso:

policy.polar
allow(actor, action, resource) if actor.get_group() = "payroll";
app.py
class User:
   def get_group(self):
      """ Generator method to yield user groups. """
      yield from ["HR", "payroll", "]

user = User()
assert(oso.is_allowed(user, "foo", "bar))

In the policy above, the right hand side of the allow rule will first evaluate "HR" = "payroll", then "payroll" = "payroll". Because the latter evaluation succeeds, the call to is_allowed() will succeed. Note that if get_group() returned a list, the rule would fail, as the evaluation would be ["HR", "payroll"] = "payroll".

Summary

Python -> Polar Types Summary

Python type

Polar type

int

Number (Integer)

float

Number (Float)

bool

Boolean

list

List

dict

Dictionary