@@ -17,9 +17,24 @@ import (
17
17
"github.com/coder/coder/coderd/tracing"
18
18
)
19
19
20
+ // ExpandableRoles is any type that can be expanded into a []Role. This is implemented
21
+ // as an interface so we can have RoleNames for user defined roles, and implement
22
+ // custom ExpandableRoles for system type users (eg autostart/autostop system role).
23
+ // We want a clear divide between the two types of roles so users have no codepath
24
+ // to interact or assign system roles.
25
+ //
26
+ // Note: We may also want to do the same thing with scopes to allow custom scope
27
+ // support unavailable to the user. Eg: Scope to a single resource.
28
+ type ExpandableRoles interface {
29
+ Expand () ([]Role , error )
30
+ // Names is for logging and tracing purposes, we want to know the human
31
+ // names of the expanded roles.
32
+ Names () []string
33
+ }
34
+
20
35
type Authorizer interface {
21
- ByRoleName (ctx context.Context , subjectID string , roleNames [] string , scope ScopeName , groups []string , action Action , object Object ) error
22
- PrepareByRoleName (ctx context.Context , subjectID string , roleNames [] string , scope ScopeName , groups []string , action Action , objectType string ) (PreparedAuthorized , error )
36
+ ByRoleName (ctx context.Context , subjectID string , roleNames ExpandableRoles , scope ScopeName , groups []string , action Action , object Object ) error
37
+ PrepareByRoleName (ctx context.Context , subjectID string , roleNames ExpandableRoles , scope ScopeName , groups []string , action Action , objectType string ) (PreparedAuthorized , error )
23
38
}
24
39
25
40
type PreparedAuthorized interface {
@@ -33,7 +48,7 @@ type PreparedAuthorized interface {
33
48
//
34
49
// Ideally the 'CompileToSQL' is used instead for large sets. This cost scales
35
50
// linearly with the number of objects passed in.
36
- func Filter [O Objecter ](ctx context.Context , auth Authorizer , subjID string , subjRoles [] string , scope ScopeName , groups []string , action Action , objects []O ) ([]O , error ) {
51
+ func Filter [O Objecter ](ctx context.Context , auth Authorizer , subjID string , subjRoles ExpandableRoles , scope ScopeName , groups []string , action Action , objects []O ) ([]O , error ) {
37
52
if len (objects ) == 0 {
38
53
// Nothing to filter
39
54
return objects , nil
@@ -45,7 +60,7 @@ func Filter[O Objecter](ctx context.Context, auth Authorizer, subjID string, sub
45
60
// objects, then the span is not interesting. It would just add excessive
46
61
// 0 time spans that provide no insight.
47
62
ctx , span := tracing .StartSpan (ctx ,
48
- rbacTraceAttributes (subjRoles , len (groups ), scope , action , objectType ,
63
+ rbacTraceAttributes (subjRoles . Names () , len (groups ), scope , action , objectType ,
49
64
// For filtering, we are only measuring the total time for the entire
50
65
// set of objects. This and the 'PrepareByRoleName' span time
51
66
// is all that is required to measure the performance of this
@@ -179,11 +194,11 @@ type authSubject struct {
179
194
// ByRoleName will expand all roleNames into roles before calling Authorize().
180
195
// This is the function intended to be used outside this package.
181
196
// The role is fetched from the builtin map located in memory.
182
- func (a RegoAuthorizer ) ByRoleName (ctx context.Context , subjectID string , roleNames [] string , scope ScopeName , groups []string , action Action , object Object ) error {
197
+ func (a RegoAuthorizer ) ByRoleName (ctx context.Context , subjectID string , roleNames ExpandableRoles , scope ScopeName , groups []string , action Action , object Object ) error {
183
198
start := time .Now ()
184
199
ctx , span := tracing .StartSpan (ctx ,
185
200
trace .WithTimestamp (start ), // Reuse the time.Now for metric and trace
186
- rbacTraceAttributes (roleNames , len (groups ), scope , action , object .Type ,
201
+ rbacTraceAttributes (roleNames . Names () , len (groups ), scope , action , object .Type ,
187
202
// For authorizing a single object, this data is useful to know how
188
203
// complex our objects are getting.
189
204
attribute .Int ("object_num_groups" , len (object .ACLGroupList )),
@@ -192,7 +207,7 @@ func (a RegoAuthorizer) ByRoleName(ctx context.Context, subjectID string, roleNa
192
207
)
193
208
defer span .End ()
194
209
195
- roles , err := RolesByNames ( roleNames )
210
+ roles , err := roleNames . Expand ( )
196
211
if err != nil {
197
212
return err
198
213
}
@@ -239,15 +254,15 @@ func (a RegoAuthorizer) Authorize(ctx context.Context, subjectID string, roles [
239
254
return nil
240
255
}
241
256
242
- func (a RegoAuthorizer ) PrepareByRoleName (ctx context.Context , subjectID string , roleNames [] string , scope ScopeName , groups []string , action Action , objectType string ) (PreparedAuthorized , error ) {
257
+ func (a RegoAuthorizer ) PrepareByRoleName (ctx context.Context , subjectID string , roleNames ExpandableRoles , scope ScopeName , groups []string , action Action , objectType string ) (PreparedAuthorized , error ) {
243
258
start := time .Now ()
244
259
ctx , span := tracing .StartSpan (ctx ,
245
260
trace .WithTimestamp (start ),
246
- rbacTraceAttributes (roleNames , len (groups ), scope , action , objectType ),
261
+ rbacTraceAttributes (roleNames . Names () , len (groups ), scope , action , objectType ),
247
262
)
248
263
defer span .End ()
249
264
250
- roles , err := RolesByNames ( roleNames )
265
+ roles , err := roleNames . Expand ( )
251
266
if err != nil {
252
267
return nil , err
253
268
}
0 commit comments