diff --git a/README.md b/README.md index dd3855a..a4fbdfb 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ Developers create a schema that models their permissions requirements and use a Examples in this repository include: - How to set up SpiceDB with tracing: see [tracing](./tracing) -- How to invoke SpiceDB as a library: see [library](./library) +- How to invoke SpiceDB as a library: see [library](./spicedb-as-library) - How to run SpiceDB in a Kubernetes cluster: see [kubernetes](./kubernetes) - CI/CD Workflows diff --git a/schemas/basic-rbac/README.md b/schemas/basic-rbac/README.md deleted file mode 100644 index 29e29a0..0000000 --- a/schemas/basic-rbac/README.md +++ /dev/null @@ -1,99 +0,0 @@ -# Simple Role Based Access Control - -Models Role Based Access Control (RBAC), where access is granted to users based on the role(s) in which they are a member. - ---- - -## Schema - -``` -/** - * user represents a user that can be granted role(s) - */ -definition user {} - -/** - * document represents a document protected by Authzed. - */ -definition document { - /** - * writer indicates that the user is a writer on the document. - */ - relation writer: user - - /** - * reader indicates that the user is a reader on the document. - */ - relation reader: user - - /** - * edit indicates that the user has permission to edit the document. - */ - permission edit = writer - - /** - * view indicates that the user has permission to view the document, if they - * are a `reader` *or* have `edit` permission. - */ - permission view = reader + edit -} -``` - -The RBAC example defines two kinds of objects: `user` to be used as references to users and `document`, representing a resource being protected (in this case, a document). - -### user - -`user` is an example of a "user" definition, which is used to represent users. The definition itself is empty, as it is only used for referencing purposes. - -```zed -definition user {} -``` - -### document - -`document` is an example of a "resource" definition, which is used to define the relations and permissions for a specific kind of resource. Here, that resource is a document. - -```zed -definition document { - /** - * writer indicates that the user is a writer on the document. - */ - relation writer: user - - /** - * reader indicates that the user is a reader on the document. - */ - relation reader: user - - /** - * edit indicates that the user has permission to edit the document. - */ - permission edit = writer - - /** - * view indicates that the user has permission to view the document, if they - * are a `reader` *or* have `edit` permission. - */ - permission view = reader + edit -} -``` - -Within the `document` definition, there are defined two relations `reader` and `writer`, which are used to represent roles for users, and two permissions `edit` and `view`, which represent the permissions that can be checked on a document. - -#### writer - -The `writer` relation defines a role of "writer" for users. - -#### reader - -The `reader` relation defines a role of "reader" for users. - -#### edit - -The `edit` permission defines an edit permission on the document. - -#### view - -The `view` permission defines a view permission on the document. - -Note that `view` includes the `edit` permission. This means that if a user is granted the role of `writer` and thus, has `edit` permission, they will _also_ be implicitly granted the permission of `view`. diff --git a/schemas/basic-rebac/README.md b/schemas/basic-rebac/README.md new file mode 100644 index 0000000..978153a --- /dev/null +++ b/schemas/basic-rebac/README.md @@ -0,0 +1,3 @@ +# Simple Relationship Based Access Control (ReBAC) + +Access is granted to users based on the relation(s) that they have to a given document. diff --git a/schemas/basic-rbac/schema-and-data.yaml b/schemas/basic-rebac/schema-and-data.yaml similarity index 64% rename from schemas/basic-rbac/schema-and-data.yaml rename to schemas/basic-rebac/schema-and-data.yaml index 8947c5f..3a99dd2 100644 --- a/schemas/basic-rbac/schema-and-data.yaml +++ b/schemas/basic-rebac/schema-and-data.yaml @@ -1,32 +1,31 @@ --- schema: |- /** - * user represents a user that can be granted role(s) + * an entity that can be granted permissions */ definition user {} /** - * document represents a document protected by Authzed. + * a resource that we are trying to protect */ definition document { /** - * writer indicates that the user is a writer on the document. + * users can be made writers of specific documents */ relation writer: user /** - * reader indicates that the user is a reader on the document. + * users can be made readers of specific documents */ relation reader: user /** - * edit indicates that the user has permission to edit the document. + * if a user has the writer relationship to a specific document, they automatically get permission to edit it */ permission edit = writer /** - * view indicates that the user has permission to view the document, if they - * are a `reader` *or* have `edit` permission. + * if a user has the reader relation to a document OR the permission to edit a document (or both), they automatically get permission to view it */ permission view = reader + edit } diff --git a/schemas/caveats/README.md b/schemas/caveats/README.md index e612957..6a838a2 100644 --- a/schemas/caveats/README.md +++ b/schemas/caveats/README.md @@ -1,29 +1,4 @@ -# Caveats for conditional access +# Simple Attribute Based Access Control (ABAC) -Models the use of caveats, which allows for conditional access based on information provided at _runtime_ to permission checks. +Access can be granted to users based on information provided at runtime to permission checks. ---- - -## Schema - -``` -definition user {} - -/** - * only allowed on tuesdays. `day_of_week` can be provided either at the time - * the relationship is written, or in the CheckPermission API call. - */ -caveat only_on_tuesday(day_of_week string) { - day_of_week == 'tuesday' -} - -definition document { - /** - * reader indicates that the user is a reader on the document, either - * directly or only on tuesday. - */ - relation reader: user | user with only_on_tuesday - - permission view = reader -} -``` diff --git a/schemas/caveats/schema-and-data.yaml b/schemas/caveats/schema-and-data.yaml index 6d7dc05..1c4c0a4 100644 --- a/schemas/caveats/schema-and-data.yaml +++ b/schemas/caveats/schema-and-data.yaml @@ -1,42 +1,57 @@ --- schema: |- + /** + * an entity that can be granted permissions + */ definition user {} /** - * only allowed on tuesdays. `day_of_week` can be provided either at the time - * the relationship is written, or in the CheckPermission API call. + * a resource that we are trying to protect */ - caveat only_on_tuesday(day_of_week string) { - day_of_week == 'tuesday' - } - - caveat ip_allowlist(user_ip ipaddress, cidr string) { - user_ip.in_cidr(cidr) - } - definition document { /** - * reader indicates that the user is a reader on the document, either directly, - * only on tuesday, or from allowed IPs. + * users can be made readers of specific documents, + * either directly, or only if they have a valid IP, or only if they aren't rate limited. */ - relation reader: user | user with only_on_tuesday | user with ip_allowlist + relation reader: user | user with has_valid_ip | user with not_rate_limited + /** + * if a user has the reder relationship to a specific document, they automatically get permission to view it + */ permission view = reader } + + /** + * only allowed if the IP address is allowed. + * we can provide cidr at the time we write the relation, and + * we can provide user_ip at the time the CheckPermission is made. + */ + caveat has_valid_ip(user_ip ipaddress, cidr string) { + user_ip.in_cidr(cidr) + } + + /** + * only allowed if rate limits haven't been exceeded. + * we can provide allowed_max at the time we write the relation, and + * we can provide current at the time the CheckPermission is made. + */ + caveat not_rate_limited(allowed_max int, current int) { + current < allowed_max + } relationships: |- document:firstdoc#reader@user:fred - document:firstdoc#reader@user:tom[only_on_tuesday] - document:firstdoc#reader@user:alice[ip_allowlist:{"cidr":"1.2.3.0/24"}] + document:firstdoc#reader@user:tom[not_rate_limited:{"allowed_max":100}] + document:firstdoc#reader@user:alice[has_valid_ip:{"cidr":"1.2.3.0/24"}] assertions: assertTrue: - - 'document:firstdoc#view@user:tom with {"day_of_week": "tuesday"}' + - 'document:firstdoc#view@user:tom with {"current": 1}' - "document:firstdoc#view@user:fred" - 'document:firstdoc#view@user:alice with {"user_ip": "1.2.3.4"}' assertCaveated: - "document:firstdoc#view@user:tom" - "document:firstdoc#view@user:alice" assertFalse: - - 'document:firstdoc#view@user:tom with {"day_of_week": "wednesday"}' + - 'document:firstdoc#view@user:tom with {"current": 500}' - 'document:firstdoc#view@user:alice with {"user_ip": "8.8.8.8"}' validation: document:firstdoc#view: diff --git a/schemas/docs-style-sharing/README.md b/schemas/docs-style-sharing/README.md index 4f2b1f8..63ae0f8 100644 --- a/schemas/docs-style-sharing/README.md +++ b/schemas/docs-style-sharing/README.md @@ -1,101 +1,3 @@ -# Google Docs-style Sharing +# Group membership and parent-of/child-of relations -Models a Google Docs-style sharing permission system where users can be granted direct access to a resource, or access via organizations and nested groups. - ---- - -## Schema - -``` -definition user {} - -definition resource { - relation manager: user | usergroup#member | usergroup#manager - relation viewer: user | usergroup#member | usergroup#manager - - permission manage = manager - permission view = viewer + manager -} - -definition usergroup { - relation manager: user | usergroup#member | usergroup#manager - relation direct_member: user | usergroup#member | usergroup#manager - - permission member = direct_member + manager -} - -definition organization { - relation group: usergroup - relation administrator: user | usergroup#member | usergroup#manager - relation direct_member: user - - relation resource: resource - - permission admin = administrator - permission member = direct_member + administrator + group->member -} -``` - -### user - -`user` is an example of a "user" type, which is used to represent users. The definition itself is empty, as it is only used for referencing purposes. - -```zed -definition user {} -``` - -### resource - -`resource` is the definition used to represent the resource being shared - -```zed -definition resource { - relation manager: user | usergroup#member | usergroup#manager - relation viewer: user | usergroup#member | usergroup#manager - - permission manage = manager - permission view = viewer + manager -} -``` - -Within the definition, there are defined two relations: `viewer` and `manager`, which are used to represent roles for users _or members/managers of groups_ for the resource, as well as the `view` and `manage` permissions for viewing and managing the resource, respectively. - -### usergroup - -`usergroup` is the definition used to represent groups, which can contain either users or other groups. Groups support a distinction between member and manager. - -```zed -definition usergroup { - relation manager: user | usergroup#member | usergroup#manager - relation direct_member: user | usergroup#member | usergroup#manager - - permission member = direct_member + manager -} -``` - -### organization - -`organization` is the definition used to represent the overall organization. - -```zed -definition organization { - relation group: usergroup - relation administrator: user | usergroup#member | usergroup#manager - relation direct_member: user - - relation resource: resource - - permission admin = administrator - permission member = direct_member + administrator + group->member -} -``` - -Organizations contain four relations (`group`, `resource`, `member`, `administrator`) which are used to reference the groups, resources, direct members and administrator users for the organization. - -#### member permission - -The `member` permission under organization computes the transitive closure of _all_ member users/groups of an organization by combining data from three sources: - -1. `direct_member`: users directly added to the organization as a member -2. `administrator` is used to add any users found as an `administrator` of the organization -3. `group->member` is used to walk from the organization to any of its groups, and then from the `group` to any of its members. This ensure that if a user is available under `member` under any group in the organization, they are treated as a member of the organization as well. +Access can be granted via direct access, or by being member of a group (that can be a child of another group) that has access to the resource. \ No newline at end of file diff --git a/schemas/docs-style-sharing/schema-and-data.yaml b/schemas/docs-style-sharing/schema-and-data.yaml index 66970a9..905746c 100644 --- a/schemas/docs-style-sharing/schema-and-data.yaml +++ b/schemas/docs-style-sharing/schema-and-data.yaml @@ -1,112 +1,89 @@ --- schema: |- + /** + * an entity that can be granted permissions. + * users can be part of groups. + */ definition user {} - definition resource { - relation manager: user | usergroup#member | usergroup#manager - relation viewer: user | usergroup#member | usergroup#manager + /** + * we can model groups as having a parent group... + */ + definition group_with_parent { + relation parent: group_with_parent + relation member: user - permission manage = manager - permission view = viewer + manager + permission view = member + parent->member } - definition usergroup { - relation manager: user | usergroup#member | usergroup#manager - relation direct_member: user | usergroup#member | usergroup#manager + /** + * ...or we can model a group as having children. + * in this example, we'll do both. + */ + definition group_with_child { + relation child: user | group_with_child#child - permission member = direct_member + manager + permission view = child } - definition organization { - relation group: usergroup - relation administrator: user | usergroup#member | usergroup#manager - relation direct_member: user + /** + * a resource that we are trying to protect + */ + definition document { + /** + * we can give viewer relation to a specific user, + * or to a group that has parents, + * or to a group that has children. + */ + relation viewer: user | group_with_parent#view | group_with_child#view - relation resource: resource - - permission admin = administrator - permission member = direct_member + administrator + group->member + permission view = viewer } relationships: |- - // Add users to various groups - usergroup:productname#manager@user:an_eng_manager - usergroup:productname#direct_member@user:an_engineer - usergroup:applications#manager@user:an_eng_director - usergroup:engineering#manager@user:cto - usergroup:csuite#manager@user:ceo - usergroup:csuite#direct_member@user:cto - - // Add groups to some other groups. - usergroup:engineering#direct_member@usergroup:applications#member - usergroup:applications#direct_member@usergroup:productname#member - usergroup:engineering#direct_member@usergroup:csuite#member - - // Add the groups under the organization. - organization:org1#group@usergroup:csuite - organization:org1#group@usergroup:productname - organization:org1#group@usergroup:applications - organization:org1#group@usergroup:engineering - - // Add some resources under the organization. - organization:org1#resource@resource:promserver - organization:org1#resource@resource:jira - - // Set a group's members and a user as the administrators of the organization. - organization:org1#administrator@usergroup:csuite#member - organization:org1#administrator@user:it_admin - - // Set the permissions on some resources. - resource:promserver#manager@usergroup:productname#member - resource:promserver#viewer@usergroup:engineering#member - resource:jira#viewer@usergroup:engineering#member - resource:jira#manager@usergroup:engineering#manager - resource:promserver#viewer@user:an_external_user + // Add an engineer to group of engineers + group_with_parent:engineering#member@user:engineer + group_with_child:engineering#child@user:engineer + // Add an analyst to group of analysts + group_with_parent:analysis#member@user:analyst + group_with_child:analysis#child@user:analyst - usergroup:blackhats#manager@user:a_villain + // Company is the parent of engineering and analysis + // Engineering and analysis are children of company + group_with_parent:engineering#parent@group_with_parent:company + group_with_child:company#child@group_with_child:engineering#child + group_with_parent:analysis#parent@group_with_parent:company + group_with_child:company#child@group_with_child:analysis#child + // Set the permissions on some documents + document:shared_with_company#viewer@group_with_child:company#view + document:shared_with_company#viewer@group_with_parent:company#view + document:shared_with_engineering#viewer@group_with_parent:engineering#view + document:shared_with_engineering#viewer@group_with_child:engineering#view + document:shared_with_analysis#viewer@group_with_parent:analysis#view + document:shared_with_analysis#viewer@group_with_child:analysis#view +assertions: + assertTrue: + - "document:shared_with_company#view@user:engineer" + - "document:shared_with_company#view@user:analyst" + - "document:shared_with_engineering#view@user:engineer" + - "document:shared_with_analysis#view@user:analyst" + assertFalse: + - "document:shared_with_engineering#view@user:analyst" + - "document:shared_with_analysis#view@user:engineer" validation: - organization:org1#admin: - - "[user:ceo] is " - - "[user:cto] is " - - "[user:it_admin] is " - - "[usergroup:csuite#member] is " - organization:org1#member: - - "[user:an_eng_director] is " - - "[user:an_eng_manager] is " - - "[user:an_engineer] is " - - "[user:ceo] is " - - "[user:cto] is /" - - "[user:it_admin] is " - - "[usergroup:applications#member] is " - - "[usergroup:csuite#member] is /" - - "[usergroup:productname#member] is " - resource:jira#manage: - - "[user:cto] is " - - "[usergroup:engineering#manager] is " - resource:jira#view: - - "[user:an_eng_director] is " - - "[user:an_eng_manager] is " - - "[user:an_engineer] is " - - "[user:ceo] is " - - "[user:cto] is /" - - "[usergroup:applications#member] is " - - "[usergroup:csuite#member] is " - - "[usergroup:engineering#manager] is " - - "[usergroup:engineering#member] is " - - "[usergroup:productname#member] is " - resource:promserver#manage: - - "[user:an_eng_manager] is " - - "[user:an_engineer] is " - - "[usergroup:productname#member] is " - resource:promserver#view: - - "[user:an_eng_director] is " - - "[user:an_eng_manager] is " - - "[user:an_engineer] is " - - "[user:an_external_user] is " - - "[user:ceo] is " - - "[user:cto] is /" - - "[usergroup:applications#member] is " - - "[usergroup:csuite#member] is " - - "[usergroup:engineering#member] is " - - "[usergroup:productname#member] is /" + document:shared_with_analysis#view: + - "[group_with_child:analysis#view] is " + - "[group_with_parent:analysis#view] is " + - "[user:analyst] is /" + document:shared_with_company#view: + - "[group_with_child:analysis#child] is " + - "[group_with_child:company#view] is " + - "[group_with_child:engineering#child] is " + - "[group_with_parent:company#view] is " + - "[user:analyst] is " + - "[user:engineer] is " + document:shared_with_engineering#view: + - "[group_with_child:engineering#view] is " + - "[group_with_parent:engineering#view] is " + - "[user:engineer] is /" diff --git a/schemas/entitlements/README.md b/schemas/entitlements/README.md new file mode 100644 index 0000000..671a208 --- /dev/null +++ b/schemas/entitlements/README.md @@ -0,0 +1,3 @@ +# Entitlements / features + +Models a SaaS application where there are various tiers of service; free tiers have less features than paid tiers. \ No newline at end of file diff --git a/schemas/entitlements/schema-and-data.yaml b/schemas/entitlements/schema-and-data.yaml new file mode 100644 index 0000000..cae9621 --- /dev/null +++ b/schemas/entitlements/schema-and-data.yaml @@ -0,0 +1,56 @@ +--- +schema: |- + /** + * an entity that can be granted permissions + */ + definition user {} + + /** + * organizations contain users + */ + definition organization { + relation member: user + } + + /** + * an entitlement is a grant given to an organization + */ + definition entitlement { + relation org: organization + permission subscribed_member = org->member + } + + /** + * features are given to entitlements + */ + definition feature { + relation associated_entitlement: entitlement + permission access = associated_entitlement->subscribed_member + } + +relationships: |- + // Add two users to organizations + organization:github#member@user:maria + organization:acme#member@user:frank + + // Assign entitlements to the organizations + entitlement:pro_plan#org@organization:github + entitlement:free_plan#org@organization:acme + + // Assign features to the entitlements + feature:download_analytics#associated_entitlement@entitlement:pro_plan + feature:view_analytics#associated_entitlement@entitlement:free_plan + feature:view_analytics#associated_entitlement@entitlement:pro_plan +assertions: + assertTrue: + - "feature:download_analytics#access@user:maria" + - "feature:view_analytics#access@user:maria" + - "feature:view_analytics#access@user:frank" + assertFalse: + - "feature:download_analytics#access@user:frank" +validation: + feature:download_analytics#access: + - "[user:maria] is " + feature:view_analytics#access: + - "[user:frank] is " + - "[user:maria] is " diff --git a/schemas/github/README.md b/schemas/github/README.md new file mode 100644 index 0000000..dd89cda --- /dev/null +++ b/schemas/github/README.md @@ -0,0 +1,3 @@ +# GitHub + +Models an app with repositories, teams and organizations. \ No newline at end of file diff --git a/schemas/github/schema-and-data.yaml b/schemas/github/schema-and-data.yaml new file mode 100644 index 0000000..b23fb18 --- /dev/null +++ b/schemas/github/schema-and-data.yaml @@ -0,0 +1,126 @@ +--- +schema: |- + definition user {} + + definition team { + relation parent: organization | team + relation maintainer: user + relation direct_member: user + + permission member = maintainer + direct_member + permission change_team_name = maintainer + parent->change_team_name + } + + definition organization { + relation own: user + relation member: user + relation billing_manager: user + relation team_maintainer: user + + // Repository actions + permission create_repository = owner + member + + // Organization settings + permission manage_billing = owner + billing_manager + permission user_seat = owner + member + team_maintainer + permission owner = own + + // Team permissions + permission change_team_name = team_maintainer + owner + } + + definition repository { + relation organization: organization + + // Repository roles + relation reader: user | team#member + relation triager: user | team#member + relation writer: user | team#member + relation maintainer: user | team#member + relation admin: user | team#member + + // Git Actions + permission clone = reader + triager + push + permission push = writer + maintainer + admin + organization->owner + + // Web actions + permission read = reader + triager + writer + maintainer + admin + organization->owner + permission delete = admin + organization->owner + + // Issues + permission create_issue = read + permission close_issue = triager + writer + maintainer + admin + organization->owner + + // Pull requests + permission create_pull_request = read + permission merge_pull_request = maintainer + organization->owner + permission close_pull_request = triager + writer + maintainer + admin + organization->owner + + // Coarse grained + permission manage_setting = maintainer + admin + organization->owner + permission manage_sensitive_setting = admin + organization->owner + } +relationships: |- + repository:authzed_go#organization@organization:authzed#... + + repository:authzed_go#reader@user:jake#... + repository:authzed_go#admin@user:jimmy#... + repository:authzed_go#triager@user:jessica#... + + repository:authzed_go#maintainer@team:support_engineers#member + + organization:authzed#own@user:jake#... + organization:authzed#own@user:jimmy#... + + team:support_engineers#maintainer@user:ivan#... + team:support_engineers#direct_member@user:ian#... + team:support_engineers#parent@organization:authzed#... + + team:emea_support_engineers#direct_member@user:iona#... + team:emea_support_engineers#parent@team:support_engineers#... +assertions: + assertTrue: + - "repository:authzed_go#clone@user:jake#..." + - "repository:authzed_go#clone@user:jimmy#..." +validation: + organization:authzed#manage_billing: + - "[user:jake] is " + - "[user:jimmy] is " + organization:authzed#user_seat: + - "[user:jake] is " + - "[user:jimmy] is " + repository:authzed_go#clone: + - "[team:support_engineers#member] is " + - "[user:ian] is " + - "[user:ivan] is " + - "[user:jake] is /" + - "[user:jessica] is " + - "[user:jimmy] is /" + repository:authzed_go#close_pull_request: + - "[team:support_engineers#member] is " + - "[user:ian] is " + - "[user:ivan] is " + - "[user:jake] is " + - "[user:jessica] is " + - "[user:jimmy] is /" + repository:authzed_go#create_issue: + - "[team:support_engineers#member] is " + - "[user:ian] is " + - "[user:ivan] is " + - "[user:jake] is /" + - "[user:jessica] is " + - "[user:jimmy] is /" + repository:authzed_go#push: + - "[team:support_engineers#member] is " + - "[user:ian] is " + - "[user:ivan] is " + - "[user:jake] is " + - "[user:jimmy] is /" + team:emea_support_engineers#change_team_name: + - "[user:ivan] is " + - "[user:jake] is " + - "[user:jimmy] is " + team:support_engineers#change_team_name: + - "[user:ivan] is " + - "[user:jake] is " + - "[user:jimmy] is " diff --git a/schemas/google-iam/README.md b/schemas/google-iam/README.md index 602cfb3..aedf795 100644 --- a/schemas/google-iam/README.md +++ b/schemas/google-iam/README.md @@ -1,4 +1,4 @@ -# Google IAM in SpiceDB +# Google IAM Models the permissions of Google's Cloud IAM in SpiceDB. Blog post: https://authzed.com/blog/google-cloud-iam-modeling/ diff --git a/schemas/superuser/README.md b/schemas/superuser/README.md index 90b904d..6be3285 100644 --- a/schemas/superuser/README.md +++ b/schemas/superuser/README.md @@ -1,29 +1,3 @@ # Super-admin / site-wide permissions -Models providing site-wide (or superuser) permissions for all resources of a specific type - ---- - -## Schema - -``` -definition platform { - relation administrator: user - permission super_admin = administrator -} - -definition organization { - // The platform is generally a singleton pointing to the same - // platform object, on which the superuser is in turn granted - // access. - relation platform: platform - permission admin = platform->super_admin -} - -definition resource { - relation owner: user | organization - permission admin = owner + owner->admin -} - -definition user {} -``` +Access is granted to all resources of a specific type to a super-admin user. \ No newline at end of file diff --git a/schemas/superuser/schema-and-data.yaml b/schemas/superuser/schema-and-data.yaml index 4f4bffa..14df8b4 100644 --- a/schemas/superuser/schema-and-data.yaml +++ b/schemas/superuser/schema-and-data.yaml @@ -1,30 +1,43 @@ --- schema: |- - definition platform { - relation administrator: user - permission super_admin = administrator + /** an entity that can be granted permissions */ + definition user {} + + /** a resource that we are trying to protect */ + definition document { + /** + * a specific user or a specific organization can be made owner of a document + */ + relation owner: user | organization + + /** + * if a user has the (direct) owner relation OR if they are admin of the owner organization, they get the admin permission on the document + */ + permission admin = owner + owner->admin } + /** organizations can own documents */ definition organization { - // The platform is generally a singleton pointing to the same - // platform object, on which the superuser is in turn granted - // access. - relation platform: platform - permission admin = platform->super_admin - } + /** the organization can be linked to one platform */ + relation platform: platform - definition resource { - relation owner: user | organization - permission admin = owner + owner->admin + /** + * if a user has the super_admin permission on the platform, they get the admin permission on the organization + */ + permission admin = platform->super_admin } - definition user {} + /** a root object with administrators */ + definition platform { + relation administrator: user + permission super_admin = administrator + } relationships: |- platform:evilempire#administrator@user:drevil organization:virtucon#platform@platform:evilempire - resource:lasers#owner@organization:virtucon + document:lasers#owner@organization:virtucon assertions: assertTrue: - - "resource:lasers#admin@user:drevil" + - "document:lasers#admin@user:drevil" assertFalse: null validation: null diff --git a/schemas/user-defined-roles/README.md b/schemas/user-defined-roles/README.md index 5d92431..4a0ee5e 100644 --- a/schemas/user-defined-roles/README.md +++ b/schemas/user-defined-roles/README.md @@ -1,52 +1,3 @@ -# User Defined Roles +# Custom Roles created at runtime -Models user defined custom roles. Blog post: https://authzed.com/blog/user-defined-roles/ - ---- - -## Schema - -``` -definition user {} - -definition project { - relation issue_creator: role#member - relation issue_assigner: role#member - relation any_issue_resolver: role#member - relation assigned_issue_resolver: role#member - relation comment_creator: role#member - relation comment_deleter: role#member - relation role_manager: role#member - - permission create_issue = issue_creator - permission create_role = role_manager -} - -definition role { - relation project: project - relation member: user - relation built_in_role: project - - permission delete = project->role_manager - built_in_role->role_manager - permission add_user = project->role_manager - permission add_permission = project->role_manager - built_in_role->role_manager - permission remove_permission = project->role_manager - built_in_role->role_manager -} - -definition issue { - relation project: project - relation assigned: user - - permission assign = project->issue_assigner - permission resolve = (project->assigned_issue_resolver & assigned) + project->any_issue_resolver - permission create_comment = project->comment_creator - - // synthetic relation - permission project_comment_deleter = project->comment_deleter -} - -definition comment { - relation issue: issue - permission delete = issue->project_comment_deleter -} -``` +Models roles created at runtime, e.g. in a JIRA project. Blog post: https://authzed.com/blog/user-defined-roles/ \ No newline at end of file