Skip to content

Instantly share code, notes, and snippets.

@moea
Last active December 18, 2021 08:38
Show Gist options
  • Save moea/bdcb5b8c7948c4fef7176619793f9eac to your computer and use it in GitHub Desktop.
Save moea/bdcb5b8c7948c4fef7176619793f9eac to your computer and use it in GitHub Desktop.
Failing OSO Example
#!/usr/bin/env python3
from oso import Oso, Relation
from dataclasses import dataclass
from functools import partial
policy = """
actor User {}
resource Group {
relations = {network: Network};
permissions = ["read"];
roles = ["host", "member"];
"read" if "member";
"member" if "host";
}
resource Network {
relations = {members: NetworkMember};
permissions = ["read"];
roles = ["member"];
}
resource NetworkMember {
relations = {user: User};
}
resource Article {
relations = {group: Group};
permissions = ["read"];
}
allow(_, "read", _n: Network);
has_permission(u: User, "read", a: Article) if
has_permission(u, "read", a.group);
has_permission(u: User, "read", g: Group) if
has_role(u, "member", g.network);
allow(actor, action, resource) if has_permission(actor, action, resource);
has_role(u: User, role_name: String, n: Network) if
r in n.members and
r.role = role_name and
r.user_id = u.id;
"""
open('policy.polar', 'w').write(policy)
OSO = Oso()
args = {'exec_query': lambda q: q,
'combine_query': lambda a, b: (a, b)}
def build_query(table, filt):
if table == 'networks__users':
for f in filt:
if f.kind == 'Eq' and f.field == 'role':
assert f.value == 'member', "Network doesn't have role " + f.value
class Something:
def __getattr__(self, x):
return self
def __iter__(self):
return iter([self])
return Something()
@dataclass
class User:
id: str
OSO.register_class(
User,
fields={'id': str},
build_query=partial(build_query, 'users'),
**args)
class Network:
pass
OSO.register_class(
Network,
fields={'id': str,
'members': Relation(
kind='many',
my_field='id',
other_type='NetworkMember',
other_field='network_id')},
build_query=partial(build_query, 'networks'),
**args)
class NetworkMember:
pass
OSO.register_class(
NetworkMember,
fields={
'user': Relation(
other_type='User',
kind='one',
my_field='user_id',
other_field='id'),
'role': str,
'user_id': str},
build_query=partial(build_query, 'networks__users'),
**args)
class Group:
pass
OSO.register_class(
Group,
fields={'id': str,
'network': Relation(
kind='one',
my_field='network_id',
other_field='id',
other_type='Network')},
build_query=partial(build_query, 'networks'),
**args)
class Article:
pass
OSO.register_class(
Article,
fields={
'group': Relation(
other_type='Group',
kind='one',
my_field='group_id',
other_field='id'),
'group_id': str},
build_query=partial(build_query, 'articles'),
**args)
OSO.load_files(["policy.polar"])
print(OSO.authorized_query(User(id="xyz"), "read", Article))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment