What you will learn
- Indicate relationships between a group of users and an object. See Modeling User Groups for more details. Used here to indicate that all members of an organization are repository admins on the organization.
- Modeling concentric relationship to have a certain relation on an object imply another relation on the same object. See Modeling Concepts: Concentric Relationships for more. Used here to indicate that maintainers of a repository are also writers of that repository.
- Using the union operator condition to indicate that a user might have a certain relation with an object if they match any of the criteria indicated. Used here to indicate that a user can be a reader on a repository, or can have the reader relationship implied through triager.
- Model parent-child objects to indicate that a user having a relationship with a certain object implies having a relationship with another object in OpenFGA. Used here to indicate that a repository admin on a GitHub organization, is an admin on all repositories that organization owns.
Before you start
In order to understand this guide correctly you must be familiar with some OpenFGA concepts and know how to develop the things that we will list below. It would be helpful to have an understanding of some concepts of OpenFGA before you start.OpenFGA concepts
OpenFGA concepts
Modeling concentric relationships
You need to know how to update the authorization model to allow having nested relations such as all writers are readers. Learn more →Modeling object-to-object relationships
You need to know how to create relationships between objects and how that might affect a user’s relationships to those objects. Learn more →Used here to indicate that users who have repo admin access on an organization, have admin access to all repositories owned by that organization.Concepts & configuration language
What you will be modeling
GitHub is a system to develop and collaborate on code. In this tutorial, you will build a subset of the GitHub permission model (detailed below) in OpenFGA, using some scenarios to validate the model.Note: For brevity, this tutorial will not model all of GitHub’s permissions. Instead, it will focus on modeling for the scenarios outlined below
Requirements
GitHub’s permission model is represented in their documentation. In this tutorial, you will be focusing on a subset of these permissions. Requirements:- Users can be admins, maintainers, writers, triagers or readers of repositories (each level inherits all access of the level lower than it. e.g. admins inherit maintainer access and so forth)
- Teams can have members
- Organizations can have members
- Organizations can own repositories
- Users can have repository admin access on organizations, and thus have admin access to all repositories owned by that organization
Defined scenarios
There will be the following users:- Anne
- Beth
- Charles, a member of the contoso/engineering team
- Diane, a member of the contoso/protocols team
- Erik, a member of the contoso org
- members of the contoso/protocols team are members of the contoso/engineering team
- members of the contoso org are repo_admins on the org
- repo admins on the org are admins on all the repos the org owns
- contoso/tooling repository, owned by the contoso org and of which Beth is a writer and Anne is a reader and members of the contoso/engineering team are admins
Modeling GitHub’s permissions
01. Permissions For Individuals In An Org
GitHub has 5 different permission levels for repositories:Objects of type “repo” have users related to them as “reader” if those users belong to the userset of all users related to the repo as “reader”
anne is a reader of repository repo:contoso/tooling we create this relationship tuple:
We can now ask OpenFGA “is anne a reader of repository repo:contoso/tooling?”
We could also say that beth is a writer of the same repository:
And ask some questions to OpenFGA:
The first reply makes sense but the second one does not. Intuitively, if beth was writer, she was also be a reader. In fact, GitHub explains this in their documentation
The users with a reader relationship to a certain object of type “repo” are any of:
- the “readers”: the set of users who are directly related to the repo as a “reader”
- the “triagers”: the set of users who are related to the object as “triager”
02. Permissions for teams in an org
GitHub also supports creating teams in an organization, adding members to a team and granting teams permissions, rather than individuals. At the end of this section we want to end up with the following permissions represented:03. Permissions for child teams in an org
GitHub also supports team nesting, known as “child teams”. Child teams inherit the access permissions of the parent team. Let’s say we have a protocols team that is part of the engineering. The simplest way to achieve the aforementioned requirement is just adding this relationship tuple: which says that members of protocols are members of engineering.Note: this is enough and valid for our current requirements, and for other read cases allows determining members of the direct team vs sub teams as the latter come from team:contoso/protocols#member. If the #member relation should not be followed for use cases a different approach could be taken.We can now add a member to the protocols team and check that they are admins of the tooling repository. At the end of this section ended with the following permissions represented:
04. Base permissions for org members
In GitHub, “you can set base permissions that apply to all members of an organization when accessing any of the organization’s repositories”. For our purposes this means that if:- User
erikis a member of an organizationcontoso - and
contosohas a repositorytooling - and
contosohas configured base permission to be “write”
erik has write permissions to tooling.
Let us model that!
At the end of this section we want to end up with the following permissions represented:
Note the added “owner” relation, indicating that organizations can own repositories.
- [done] they have a repo admin relation (directly or through team membership)
- [pending] their organization is configured with repo_admin as the base permission
The users with an admin relationship to a certain object of type “repo” are any of:
- the “admins”: the set of users who are directly related to the repo as an “admin”
- the “repository admins of the org that owns the repo”: from the objects who are related to the doc as owner, return the sets of users who are related to those objects as “repo_admin”
- read all relationship tuples related to repo:contoso/tooling as owner which returns:
[{ "object": "repo:contoso/tooling", "relation": "owner", "user": "organization:contoso" }]- for each relationship tuple read, return all usersets that match the following, returning tuples of shape:
{ "object": "organization:contoso", "relation": "repo_admin", "user": ??? }- Well:
- If the base permission for org contoso is repo_admin then it should be organization:contoso#member.
- If the base permission for org contoso is NOT repo_admin, then it should be empty (no relationship tuple).
- Whenever the value of this dropdown changes:

- Delete the previous relationship tuple and create a new one: