|
2 | 2 | title: Role Based Access Control (RBAC)
|
3 | 3 | ---
|
4 | 4 |
|
5 |
| -This guide will explain how to implement RBAC using Ory Keto. It's still work in |
6 |
| -progress. If you happened to figure this out yourself, please open a PR to add |
7 |
| -your findings on this page. |
| 5 | +This guide will explain how to implement RBAC using Ory Keto. |
| 6 | + |
| 7 | +:::warning |
| 8 | + |
| 9 | +Implementing RBAC currently is possible, but requires some workarounds. This |
| 10 | +guide enables RBAC support with Keto but native support is still work in |
| 11 | +progress. Follow the progress in |
| 12 | +[this issue](https://github.com/ory/keto/issues/598) |
| 13 | +::: |
| 14 | + |
| 15 | +[Role Based Access Control (RBAC)](https://en.wikipedia.org/wiki/Role-based_access_control) |
| 16 | +maps subjects to roles and roles to permissions. The goal of (H)RBAC is to make |
| 17 | +permission management convenient by grouping subjects in roles and assigning |
| 18 | +permissions roles. This type of access control is common in web applications |
| 19 | +where one often encounters roles such as "administrator", "moderator", and so |
| 20 | +on. |
| 21 | + |
| 22 | +In **Hierarchical Role Based Access Control (HRBAC)** roles can inherit |
| 23 | +permissions from other roles. The "administrator" role, for example, could |
| 24 | +inherit all permissions from the "moderator" role. This reduces duplication and |
| 25 | +management complexity around defining privileges. |
| 26 | + |
| 27 | +Let's assume that we are building a reporting application and need to have three |
| 28 | +groups of users with different access levels. |
| 29 | +We have the following group of reports in our application. |
| 30 | + |
| 31 | +- Financial performance reports |
| 32 | +- Marketing performance reports |
| 33 | +- Community performance reports |
| 34 | + |
| 35 | +This time we model the access rights using (H)RBAC and the roles |
| 36 | +`community`, `marketing`, `finance` and `admin`: |
| 37 | + |
| 38 | +The role `admin` inherits all privileges from `finance`, `marketing` and `community` |
| 39 | + |
| 40 | +(H)RBAC is everywhere. If you ever installed a forum software such as |
| 41 | +[phpBB](https://www.phpbb.com/support/docs/en/3.1/ug/adminguide/permissions_roles/) |
| 42 | +or [Wordpress](https://codex.wordpress.org/Roles_and_Capabilities), you have |
| 43 | +definitely encountered ACL, (H)RBAC, or both. |
| 44 | + |
| 45 | +(H)RBAC reduces management complexity and overhead with large user bases. |
| 46 | +Sometimes however, even (H)RBAC is not enough. An example is when you need to |
| 47 | +express ownership (e.g. `Dilan` can only modify his own reports), have |
| 48 | +attributes (e.g. `Dilan` needs to have access only during work hours), |
| 49 | +or in multi-tenant environments. |
| 50 | + |
| 51 | +**Benefits:** |
| 52 | + |
| 53 | +- Reduces management complexity when many identities share similar permissions. |
| 54 | +- Role hierarchies can reduce redundancy even further. |
| 55 | +- Is well established and easily understood by many developers as it is a |
| 56 | + de-facto standard for web applications. |
| 57 | + |
| 58 | +**Shortcomings:** |
| 59 | + |
| 60 | +- Has no concept of context: |
| 61 | +- There is no concept of ownership: _Dan is the author of article "Hello |
| 62 | +World" and is thus allowed to update it_. |
| 63 | +- There is no concept of environment: _Dan is allowed to access accounting |
| 64 | +services when the request comes from IP 10.0.0.3_. |
| 65 | +- There is no concept of tenants: _Dan is allowed to access resources on the |
| 66 | +"dan's test" tenant_. |
| 67 | + |
| 68 | +## Using RBAC with Ory Keto |
| 69 | + |
| 70 | +We need to have three groups, `finance`, `marketing`, `community`. Also, we need |
| 71 | +to have two namespaces: `reports` to manage access control and `groups` to add |
| 72 | +users to this group |
| 73 | + |
| 74 | +Let's add namespaces to Keto config. |
| 75 | +[here](https://www.ory.sh/docs/keto/reference/configuration) |
| 76 | + |
| 77 | +```yaml |
| 78 | +# ... |
| 79 | +namespaces: |
| 80 | + - id: 0 |
| 81 | + name: groups |
| 82 | + - id: 1 |
| 83 | + name: reports |
| 84 | +#... |
| 85 | +``` |
| 86 | + |
| 87 | +We can have two types of permission to access reports for granularity. Let's |
| 88 | +assume that we need `edit` and `view` access to the reports. |
| 89 | + |
| 90 | +```keto-relation-tuples |
| 91 | +// View only access for finance department |
| 92 | +reports:finance#view@(groups:finance#member) |
| 93 | +// View only access for community department |
| 94 | +reports:community#view@(groups:community#member) |
| 95 | +// View only access for marketing department |
| 96 | +reports:marketing#view@(groups:marketing#member) |
| 97 | +// Edit access for admin group |
| 98 | +reports:finance#edit@(groups:admin#member) |
| 99 | +reports:community#edit@(groups:admin#member) |
| 100 | +reports:marketing#edit@(groups:admin#member) |
| 101 | +reports:finance#view@(groups:admin#member) |
| 102 | +reports:community#view@(groups:admin#member) |
| 103 | +reports:marketing#view@(groups:admin#member) |
| 104 | +``` |
| 105 | + |
| 106 | +Let's assume that we have four people in our organization. Lila is CFO and needs |
| 107 | +access to financial reports, Hadley works in marketing, and Dilan works as a |
| 108 | +community manager. Neel is an admin of a system and needs to have edit |
| 109 | +permissions for reports. |
| 110 | + |
| 111 | +```keto-relation-tuples |
| 112 | +groups:finance#member@Lila |
| 113 | +groups:community#member@Dilan |
| 114 | +groups:marketing#member@Hadley |
| 115 | +groups:admin#member@Neel |
| 116 | +``` |
| 117 | + |
| 118 | +## Creating Relation Tuples |
| 119 | + |
| 120 | +Let's copy all permissions we created to a `policies.rts` file with the |
| 121 | +following content. |
| 122 | + |
| 123 | +```keto-relation-tuples |
| 124 | +reports:finance#view@(groups:finance#member) |
| 125 | +reports:community#view@(groups:community#member) |
| 126 | +reports:marketing#view@(groups:marketing#member) |
| 127 | +reports:finance#edit@(groups:admin#member) |
| 128 | +reports:community#edit@(groups:admin#member) |
| 129 | +reports:marketing#edit@(groups:admin#member) |
| 130 | +reports:finance#view@(groups:admin#member) |
| 131 | +reports:community#view@(groups:admin#member) |
| 132 | +reports:marketing#view@(groups:admin#member) |
| 133 | +groups:finance#member@Lila |
| 134 | +groups:community#member@Dilan |
| 135 | +groups:marketing#member@Hadley |
| 136 | +groups:admin#member@Neel |
| 137 | +``` |
| 138 | + |
| 139 | + |
| 140 | +Then we can run |
| 141 | + |
| 142 | +```bash |
| 143 | +keto relation-tuple parse policies.rts --format json | \ |
| 144 | + keto relation-tuple create - >/dev/null \ |
| 145 | + && echo "Successfully created tuple" \ |
| 146 | + || echo "Encountered error" |
| 147 | +``` |
| 148 | + |
| 149 | + |
| 150 | +Since Dilan works as a community manager, the following check examples show that |
| 151 | +he has access only to community reports |
| 152 | + |
| 153 | +```bash |
| 154 | +keto check Dilan view reports finance |
| 155 | +Denied |
| 156 | +keto check Dilan view reports community |
| 157 | +Allowed |
| 158 | +keto check Dilan edit reports community |
| 159 | +Denied |
| 160 | +``` |
| 161 | + |
| 162 | +Now Dilan decided to also work with marketing. Therefore we need to update his |
| 163 | +permissions and add him to the marketing group. |
| 164 | + |
| 165 | +```keto-relation-tuples |
| 166 | +groups:marketing#member@Dilan |
| 167 | +``` |
| 168 | + |
| 169 | +Now he also has access to marketing reports: |
| 170 | + |
| 171 | +``` |
| 172 | +keto check Dilan view reports marketing |
| 173 | +Allowed |
| 174 | +``` |
| 175 | + |
| 176 | +## Display all objects a User has access to |
| 177 | + |
| 178 | +The example below shows you how to get a list of objects Dilan has access to |
| 179 | + |
| 180 | +```bash |
| 181 | +# Get all groups for Dilan |
| 182 | +curl -s http://localhost:4466/relation-tuples\?subject_id\=Dilan\&relation\=member | jq |
| 183 | +{ |
| 184 | + "relation_tuples": [ |
| 185 | + { |
| 186 | + "namespace": "groups", |
| 187 | + "object": "community", |
| 188 | + "relation": "member", |
| 189 | + "subject_id": "Dilan" |
| 190 | + }, |
| 191 | + { |
| 192 | + "namespace": "groups", |
| 193 | + "object": "marketing", |
| 194 | + "relation": "member", |
| 195 | + "subject_id": "Dilan" |
| 196 | + } |
| 197 | + ], |
| 198 | + "next_page_token": "" |
| 199 | +} |
| 200 | + |
| 201 | +# Get permissions to objects for marketing group |
| 202 | +curl -s http://localhost:4466/relation-tuples\?subject_set.namespace\=groups\&subject_set.relation\=member\&subject_set.object\=marketing | jq |
| 203 | +{ |
| 204 | + "relation_tuples": [ |
| 205 | + { |
| 206 | + "namespace": "reports", |
| 207 | + "object": "marketing", |
| 208 | + "relation": "view", |
| 209 | + "subject_set": { |
| 210 | + "namespace": "groups", |
| 211 | + "object": "marketing", |
| 212 | + "relation": "member" |
| 213 | + } |
| 214 | + } |
| 215 | + ], |
| 216 | + "next_page_token": "" |
| 217 | +} |
| 218 | +# Get permissions to objects for community group |
| 219 | +curl -s http://localhost:4466/relation-tuples\?subject_set.namespace\=groups\&subject_set.relation\=member\&subject_set.object\=marketing | jq |
| 220 | +{ |
| 221 | + "relation_tuples": [ |
| 222 | + { |
| 223 | + "namespace": "reports", |
| 224 | + "object": "marketing", |
| 225 | + "relation": "view", |
| 226 | + "subject_set": { |
| 227 | + "namespace": "groups", |
| 228 | + "object": "marketing", |
| 229 | + "relation": "member" |
| 230 | + } |
| 231 | + } |
| 232 | + ], |
| 233 | + "next_page_token": "" |
| 234 | +} |
| 235 | +``` |
0 commit comments