You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: ee/rbac/README.md
+83-99Lines changed: 83 additions & 99 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -75,6 +75,10 @@ erDiagram
75
75
}
76
76
```
77
77
78
+
The center of the RBAC system is the subject role bindings table, which assigns a role to a given subject (either a user or a group), and that role has a list of permissions attached to it.
79
+
80
+
There are two resources to which roles can be assigned: you can have a role within the organization, or you can have a role within the project. If you want to assign a role within the organization, that role has to be of the "organization scope", and if you want to assign a role within the project, then the role you are assigning must be of the "project scope".
81
+
78
82
### Subject System (Users & Groups)
79
83
80
84
```mermaid
@@ -110,6 +114,48 @@ erDiagram
110
114
}
111
115
```
112
116
117
+
### Additional Complexity
118
+
119
+
Role Inheritance
120
+
121
+
One role can inherit another role and all of its permissions. Every time we want to calculate the permissions you have, we have to check the roles you are assigned, but also all the roles they inherit. This is a redundant feature. We're not really using in our production setup (except some Insider roles). Even though this is tested and works, we've never really found a use for it. When you're trying to create a new role within the custom roles UI, there is no way for you to set up role inheritance.
122
+
123
+
Organization Role to Project Role Mappings
124
+
125
+
Another table is organization role to project role mappings, which also makes this a bit more complex. This is something we are using regularly. You can say that some organizational role, like "Owner", carries automatic "Admin" access to all of the projects within the organization. In this case, organization role "Owner" maps to project role "Admin", and this also has to be taken into consideration when we are checking if user has access to a project: Even though they might not have a role directly within the project, they maybe have an organization role which maps to project role.
126
+
127
+
Groups
128
+
129
+
The subject in subject role bindings can be a user, but it can also be a group. When we are actually trying to see which permissions a user has, we have to track all of the roles assigned directly. We also have to check if the user is part of a group, and then if they are, we also need to check all of the roles that the group has.
130
+
We have tested groups thoroughly, but I'm not sure if any customers are using them.
131
+
132
+
### Key-Value Stores & Audit
133
+
134
+
```mermaid
135
+
erDiagram
136
+
user_permissions_key_value_store {
137
+
string key
138
+
text value
139
+
}
140
+
141
+
project_access_key_value_store {
142
+
string key
143
+
text value
144
+
}
145
+
```
146
+
147
+
User Permission Key Value Store
148
+
149
+
All of this complexity makes actually figuring out which permissions a user has within an organization (or project) a bit more complex. It's not as simple as just tracking the subject role bindings table. It takes quite a few joins, and some recursive joins. Query which calculates all of the permisions for a given user/organization/project is written in the `Rbac.ComputePermissions` module of rhis service. Depending on the size of the organization, number of user and projects they have, it can take from >1s, to 6,7s to calculate these permission.
150
+
151
+
That's why we had a need for `user_permissions_key_value_store` and `project_access_key_value_store`. Instead of calculating all of the permissions for every "GET" query, there is one table which stores all of the permissions user has within the org and/or project, and another with list of projects user has access to within the organization.
152
+
153
+
These key value stores are recalculated anytime somebody is assigned a new role, anytime somebody's role is being removed, when you are joining a group, when you are being removed from a group, or when the role definition changes (which can happen with custom roles).
154
+
155
+
Performance Issues
156
+
157
+
As mentioned above, recalculation permissions usually takes around a second, but for some organizations that have a lot of projects, it can take five or six seconds. In some extreme cases, it can take around 10+ seconds, and this is where a problem occurs because we are hitting gRPC request timeout. You get bad UX experience when you want to change a role and you get a spinner for, let's say, 10 seconds, and it just times out. One major improvement we can do is to make role assignment and role retraction asynchronous, like many other operations in RBAC already are.
158
+
113
159
### Identity Provider Integration
114
160
115
161
```mermaid
@@ -170,8 +216,44 @@ erDiagram
170
216
}
171
217
```
172
218
219
+
### Background Job Tables
220
+
221
+
```mermaid
222
+
erDiagram
223
+
collaborator_refresh_requests {
224
+
uuid id
225
+
uuid org_id
226
+
string state
227
+
uuid requester_user_id
228
+
}
229
+
230
+
rbac_refresh_project_access_requests {
231
+
uuid id
232
+
string state
233
+
uuid org_id
234
+
int user_id
235
+
}
236
+
237
+
rbac_refresh_all_permissions_requests {
238
+
int id
239
+
string state
240
+
int organizations_updated
241
+
int retries
242
+
}
243
+
244
+
group_management_request {
245
+
int id
246
+
string state
247
+
uuid user_id
248
+
uuid group_id
249
+
string action
250
+
}
251
+
```
252
+
173
253
### Legacy Tables
174
254
255
+
These tables are leftover from the old auth system. We still use collaborators table when we want to sych GitHub repo access with the Semaphore project roles.
0 commit comments