@@ -36,8 +36,8 @@ func TestOwnerExec(t *testing.T) {
36
36
37
37
auth := rbac .NewCachingAuthorizer (prometheus .NewRegistry ())
38
38
// Exec a random workspace
39
- err := auth .Authorize (context .Background (), owner , policy .ActionCreate ,
40
- rbac .ResourceWorkspaceExecution .WithID (uuid .New ()).InOrg (uuid .New ()).WithOwner (uuid .NewString ()))
39
+ err := auth .Authorize (context .Background (), owner , policy .ActionSSH ,
40
+ rbac .ResourceWorkspace .WithID (uuid .New ()).InOrg (uuid .New ()).WithOwner (uuid .NewString ()))
41
41
require .ErrorAsf (t , err , & rbac.UnauthorizedError {}, "expected unauthorized error" )
42
42
})
43
43
@@ -50,8 +50,8 @@ func TestOwnerExec(t *testing.T) {
50
50
auth := rbac .NewCachingAuthorizer (prometheus .NewRegistry ())
51
51
52
52
// Exec a random workspace
53
- err := auth .Authorize (context .Background (), owner , policy .ActionCreate ,
54
- rbac .ResourceWorkspaceExecution .WithID (uuid .New ()).InOrg (uuid .New ()).WithOwner (uuid .NewString ()))
53
+ err := auth .Authorize (context .Background (), owner , policy .ActionSSH ,
54
+ rbac .ResourceWorkspace .WithID (uuid .New ()).InOrg (uuid .New ()).WithOwner (uuid .NewString ()))
55
55
require .NoError (t , err , "expected owner can" )
56
56
})
57
57
}
@@ -60,6 +60,8 @@ func TestOwnerExec(t *testing.T) {
60
60
func TestRolePermissions (t * testing.T ) {
61
61
t .Parallel ()
62
62
63
+ crud := []policy.Action {policy .ActionCreate , policy .ActionRead , policy .ActionUpdate , policy .ActionDelete }
64
+
63
65
auth := rbac .NewCachingAuthorizer (prometheus .NewRegistry ())
64
66
65
67
// currentUser is anything that references "me", "mine", or "my".
@@ -145,8 +147,8 @@ func TestRolePermissions(t *testing.T) {
145
147
{
146
148
Name : "MyWorkspaceInOrgExecution" ,
147
149
// When creating the WithID won't be set, but it does not change the result.
148
- Actions : []policy.Action {policy .ActionCreate , policy . ActionRead , policy . ActionUpdate , policy . ActionDelete },
149
- Resource : rbac .ResourceWorkspaceExecution .WithID (workspaceID ).InOrg (orgID ).WithOwner (currentUser .String ()),
150
+ Actions : []policy.Action {policy .ActionSSH },
151
+ Resource : rbac .ResourceWorkspace .WithID (workspaceID ).InOrg (orgID ).WithOwner (currentUser .String ()),
150
152
AuthorizeMap : map [bool ][]authSubject {
151
153
true : {owner , orgMemberMe },
152
154
false : {orgAdmin , memberMe , otherOrgAdmin , otherOrgMember , templateAdmin , userAdmin },
@@ -155,16 +157,16 @@ func TestRolePermissions(t *testing.T) {
155
157
{
156
158
Name : "MyWorkspaceInOrgAppConnect" ,
157
159
// When creating the WithID won't be set, but it does not change the result.
158
- Actions : []policy.Action {policy .ActionCreate , policy . ActionRead , policy . ActionUpdate , policy . ActionDelete },
159
- Resource : rbac .ResourceWorkspaceApplicationConnect .WithID (workspaceID ).InOrg (orgID ).WithOwner (currentUser .String ()),
160
+ Actions : []policy.Action {policy .ActionApplicationConnect },
161
+ Resource : rbac .ResourceWorkspace .WithID (workspaceID ).InOrg (orgID ).WithOwner (currentUser .String ()),
160
162
AuthorizeMap : map [bool ][]authSubject {
161
- true : {owner , orgAdmin , orgMemberMe },
162
- false : {memberMe , otherOrgAdmin , otherOrgMember , templateAdmin , userAdmin },
163
+ true : {owner , orgMemberMe },
164
+ false : {memberMe , otherOrgAdmin , otherOrgMember , templateAdmin , userAdmin , orgAdmin },
163
165
},
164
166
},
165
167
{
166
168
Name : "Templates" ,
167
- Actions : []policy.Action {policy .ActionCreate , policy .ActionUpdate , policy .ActionDelete },
169
+ Actions : []policy.Action {policy .ActionCreate , policy .ActionUpdate , policy .ActionDelete , policy . ActionViewInsights },
168
170
Resource : rbac .ResourceTemplate .WithID (templateID ).InOrg (orgID ),
169
171
AuthorizeMap : map [bool ][]authSubject {
170
172
true : {owner , orgAdmin , templateAdmin },
@@ -191,7 +193,7 @@ func TestRolePermissions(t *testing.T) {
191
193
},
192
194
{
193
195
Name : "MyFile" ,
194
- Actions : []policy.Action {policy .ActionCreate , policy .ActionRead , policy . ActionUpdate , policy . ActionDelete },
196
+ Actions : []policy.Action {policy .ActionCreate , policy .ActionRead },
195
197
Resource : rbac .ResourceFile .WithID (fileID ).WithOwner (currentUser .String ()),
196
198
AuthorizeMap : map [bool ][]authSubject {
197
199
true : {owner , memberMe , orgMemberMe , templateAdmin },
@@ -227,8 +229,8 @@ func TestRolePermissions(t *testing.T) {
227
229
},
228
230
{
229
231
Name : "RoleAssignment" ,
230
- Actions : []policy.Action {policy .ActionCreate , policy . ActionUpdate , policy .ActionDelete },
231
- Resource : rbac .ResourceRoleAssignment ,
232
+ Actions : []policy.Action {policy .ActionAssign , policy .ActionDelete },
233
+ Resource : rbac .ResourceAssignRole ,
232
234
AuthorizeMap : map [bool ][]authSubject {
233
235
true : {owner , userAdmin },
234
236
false : {orgAdmin , orgMemberMe , otherOrgAdmin , otherOrgMember , memberMe , templateAdmin },
@@ -237,16 +239,16 @@ func TestRolePermissions(t *testing.T) {
237
239
{
238
240
Name : "ReadRoleAssignment" ,
239
241
Actions : []policy.Action {policy .ActionRead },
240
- Resource : rbac .ResourceRoleAssignment ,
242
+ Resource : rbac .ResourceAssignRole ,
241
243
AuthorizeMap : map [bool ][]authSubject {
242
244
true : {owner , orgAdmin , orgMemberMe , otherOrgAdmin , otherOrgMember , memberMe , templateAdmin , userAdmin },
243
245
false : {},
244
246
},
245
247
},
246
248
{
247
249
Name : "OrgRoleAssignment" ,
248
- Actions : []policy.Action {policy .ActionCreate , policy . ActionUpdate , policy .ActionDelete },
249
- Resource : rbac .ResourceOrgRoleAssignment .InOrg (orgID ),
250
+ Actions : []policy.Action {policy .ActionAssign , policy .ActionDelete },
251
+ Resource : rbac .ResourceAssignOrgRole .InOrg (orgID ),
250
252
AuthorizeMap : map [bool ][]authSubject {
251
253
true : {owner , orgAdmin },
252
254
false : {orgMemberMe , otherOrgAdmin , otherOrgMember , memberMe , templateAdmin , userAdmin },
@@ -255,7 +257,7 @@ func TestRolePermissions(t *testing.T) {
255
257
{
256
258
Name : "ReadOrgRoleAssignment" ,
257
259
Actions : []policy.Action {policy .ActionRead },
258
- Resource : rbac .ResourceOrgRoleAssignment .InOrg (orgID ),
260
+ Resource : rbac .ResourceAssignOrgRole .InOrg (orgID ),
259
261
AuthorizeMap : map [bool ][]authSubject {
260
262
true : {owner , orgAdmin , orgMemberMe },
261
263
false : {otherOrgAdmin , otherOrgMember , memberMe , templateAdmin , userAdmin },
@@ -264,16 +266,16 @@ func TestRolePermissions(t *testing.T) {
264
266
{
265
267
Name : "APIKey" ,
266
268
Actions : []policy.Action {policy .ActionCreate , policy .ActionRead , policy .ActionUpdate , policy .ActionDelete },
267
- Resource : rbac .ResourceAPIKey .WithID (apiKeyID ).WithOwner (currentUser .String ()),
269
+ Resource : rbac .ResourceApiKey .WithID (apiKeyID ).WithOwner (currentUser .String ()),
268
270
AuthorizeMap : map [bool ][]authSubject {
269
271
true : {owner , orgMemberMe , memberMe },
270
272
false : {orgAdmin , otherOrgAdmin , otherOrgMember , templateAdmin , userAdmin },
271
273
},
272
274
},
273
275
{
274
276
Name : "UserData" ,
275
- Actions : []policy.Action {policy .ActionCreate , policy .ActionRead , policy . ActionUpdate , policy . ActionDelete },
276
- Resource : rbac .ResourceUserData . WithID (currentUser ). WithOwner ( currentUser . String () ),
277
+ Actions : []policy.Action {policy .ActionReadPersonal , policy .ActionUpdatePersonal },
278
+ Resource : rbac .ResourceUserObject (currentUser ),
277
279
AuthorizeMap : map [bool ][]authSubject {
278
280
true : {owner , orgMemberMe , memberMe , userAdmin },
279
281
false : {orgAdmin , otherOrgAdmin , otherOrgMember , templateAdmin },
@@ -312,6 +314,15 @@ func TestRolePermissions(t *testing.T) {
312
314
},
313
315
{
314
316
Name : "Groups" ,
317
+ Actions : []policy.Action {policy .ActionCreate , policy .ActionDelete , policy .ActionUpdate },
318
+ Resource : rbac .ResourceGroup .WithID (groupID ).InOrg (orgID ),
319
+ AuthorizeMap : map [bool ][]authSubject {
320
+ true : {owner , orgAdmin , userAdmin },
321
+ false : {memberMe , otherOrgAdmin , orgMemberMe , otherOrgMember , templateAdmin },
322
+ },
323
+ },
324
+ {
325
+ Name : "GroupsRead" ,
315
326
Actions : []policy.Action {policy .ActionRead },
316
327
Resource : rbac .ResourceGroup .WithID (groupID ).InOrg (orgID ),
317
328
AuthorizeMap : map [bool ][]authSubject {
@@ -330,19 +341,183 @@ func TestRolePermissions(t *testing.T) {
330
341
},
331
342
{
332
343
Name : "WorkspaceBuild" ,
333
- Actions : rbac . AllActions () ,
334
- Resource : rbac .ResourceWorkspaceBuild .WithID (uuid .New ()).InOrg (orgID ).WithOwner (memberMe .Actor .ID ),
344
+ Actions : []policy. Action { policy . ActionWorkspaceBuild } ,
345
+ Resource : rbac .ResourceWorkspace .WithID (uuid .New ()).InOrg (orgID ).WithOwner (memberMe .Actor .ID ),
335
346
AuthorizeMap : map [bool ][]authSubject {
336
347
true : {owner , orgAdmin , orgMemberMe },
337
348
false : {userAdmin , otherOrgAdmin , otherOrgMember , templateAdmin , memberMe },
338
349
},
339
350
},
351
+ // Some admin style resources
352
+ {
353
+ Name : "Licences" ,
354
+ Actions : []policy.Action {policy .ActionCreate , policy .ActionRead , policy .ActionDelete },
355
+ Resource : rbac .ResourceLicense ,
356
+ AuthorizeMap : map [bool ][]authSubject {
357
+ true : {owner },
358
+ false : {orgAdmin , otherOrgAdmin , otherOrgMember , memberMe , orgMemberMe , templateAdmin , userAdmin },
359
+ },
360
+ },
361
+ {
362
+ Name : "DeploymentStats" ,
363
+ Actions : []policy.Action {policy .ActionRead },
364
+ Resource : rbac .ResourceDeploymentStats ,
365
+ AuthorizeMap : map [bool ][]authSubject {
366
+ true : {owner },
367
+ false : {orgAdmin , otherOrgAdmin , otherOrgMember , memberMe , orgMemberMe , templateAdmin , userAdmin },
368
+ },
369
+ },
370
+ {
371
+ Name : "DeploymentConfig" ,
372
+ Actions : []policy.Action {policy .ActionRead },
373
+ Resource : rbac .ResourceDeploymentConfig ,
374
+ AuthorizeMap : map [bool ][]authSubject {
375
+ true : {owner },
376
+ false : {orgAdmin , otherOrgAdmin , otherOrgMember , memberMe , orgMemberMe , templateAdmin , userAdmin },
377
+ },
378
+ },
379
+ {
380
+ Name : "DebugInfo" ,
381
+ Actions : []policy.Action {policy .ActionUse },
382
+ Resource : rbac .ResourceDebugInfo ,
383
+ AuthorizeMap : map [bool ][]authSubject {
384
+ true : {owner },
385
+ false : {orgAdmin , otherOrgAdmin , otherOrgMember , memberMe , orgMemberMe , templateAdmin , userAdmin },
386
+ },
387
+ },
388
+ {
389
+ Name : "Replicas" ,
390
+ Actions : []policy.Action {policy .ActionRead },
391
+ Resource : rbac .ResourceReplicas ,
392
+ AuthorizeMap : map [bool ][]authSubject {
393
+ true : {owner },
394
+ false : {orgAdmin , otherOrgAdmin , otherOrgMember , memberMe , orgMemberMe , templateAdmin , userAdmin },
395
+ },
396
+ },
397
+ {
398
+ Name : "TailnetCoordinator" ,
399
+ Actions : crud ,
400
+ Resource : rbac .ResourceTailnetCoordinator ,
401
+ AuthorizeMap : map [bool ][]authSubject {
402
+ true : {owner },
403
+ false : {orgAdmin , otherOrgAdmin , otherOrgMember , memberMe , orgMemberMe , templateAdmin , userAdmin },
404
+ },
405
+ },
406
+ {
407
+ Name : "AuditLogs" ,
408
+ Actions : []policy.Action {policy .ActionRead },
409
+ Resource : rbac .ResourceAuditLog ,
410
+ AuthorizeMap : map [bool ][]authSubject {
411
+ true : {owner },
412
+ false : {orgAdmin , otherOrgAdmin , otherOrgMember , memberMe , orgMemberMe , templateAdmin , userAdmin },
413
+ },
414
+ },
415
+ {
416
+ Name : "ProvisionerDaemons" ,
417
+ Actions : []policy.Action {policy .ActionCreate , policy .ActionUpdate , policy .ActionDelete },
418
+ Resource : rbac .ResourceProvisionerDaemon .InOrg (orgID ),
419
+ AuthorizeMap : map [bool ][]authSubject {
420
+ true : {owner , templateAdmin , orgAdmin },
421
+ false : {otherOrgAdmin , otherOrgMember , memberMe , orgMemberMe , userAdmin },
422
+ },
423
+ },
424
+ {
425
+ Name : "ProvisionerDaemonsRead" ,
426
+ Actions : []policy.Action {policy .ActionRead },
427
+ Resource : rbac .ResourceProvisionerDaemon .InOrg (orgID ),
428
+ AuthorizeMap : map [bool ][]authSubject {
429
+ // This should be fixed when multi-org goes live
430
+ true : {owner , templateAdmin , orgAdmin , otherOrgAdmin , otherOrgMember , memberMe , orgMemberMe , userAdmin },
431
+ false : {},
432
+ },
433
+ },
434
+ {
435
+ Name : "UserProvisionerDaemons" ,
436
+ Actions : []policy.Action {policy .ActionCreate , policy .ActionUpdate , policy .ActionDelete },
437
+ Resource : rbac .ResourceProvisionerDaemon .WithOwner (currentUser .String ()).InOrg (orgID ),
438
+ AuthorizeMap : map [bool ][]authSubject {
439
+ true : {owner , templateAdmin , orgMemberMe , orgAdmin },
440
+ false : {memberMe , otherOrgAdmin , otherOrgMember , userAdmin },
441
+ },
442
+ },
443
+ {
444
+ Name : "System" ,
445
+ Actions : crud ,
446
+ Resource : rbac .ResourceSystem ,
447
+ AuthorizeMap : map [bool ][]authSubject {
448
+ true : {owner },
449
+ false : {orgAdmin , otherOrgAdmin , otherOrgMember , memberMe , orgMemberMe , templateAdmin , userAdmin },
450
+ },
451
+ },
452
+ {
453
+ Name : "Oauth2App" ,
454
+ Actions : []policy.Action {policy .ActionCreate , policy .ActionUpdate , policy .ActionDelete },
455
+ Resource : rbac .ResourceOauth2App ,
456
+ AuthorizeMap : map [bool ][]authSubject {
457
+ true : {owner },
458
+ false : {orgAdmin , otherOrgAdmin , otherOrgMember , memberMe , orgMemberMe , templateAdmin , userAdmin },
459
+ },
460
+ },
461
+ {
462
+ Name : "Oauth2AppRead" ,
463
+ Actions : []policy.Action {policy .ActionRead },
464
+ Resource : rbac .ResourceOauth2App ,
465
+ AuthorizeMap : map [bool ][]authSubject {
466
+ true : {owner , orgAdmin , otherOrgAdmin , otherOrgMember , memberMe , orgMemberMe , templateAdmin , userAdmin },
467
+ false : {},
468
+ },
469
+ },
470
+ {
471
+ Name : "Oauth2AppSecret" ,
472
+ Actions : crud ,
473
+ Resource : rbac .ResourceOauth2AppSecret ,
474
+ AuthorizeMap : map [bool ][]authSubject {
475
+ true : {owner },
476
+ false : {orgAdmin , otherOrgAdmin , otherOrgMember , memberMe , orgMemberMe , templateAdmin , userAdmin },
477
+ },
478
+ },
479
+ {
480
+ Name : "Oauth2Token" ,
481
+ Actions : crud ,
482
+ Resource : rbac .ResourceOauth2AppCodeToken ,
483
+ AuthorizeMap : map [bool ][]authSubject {
484
+ true : {owner },
485
+ false : {orgAdmin , otherOrgAdmin , otherOrgMember , memberMe , orgMemberMe , templateAdmin , userAdmin },
486
+ },
487
+ },
488
+ {
489
+ Name : "WorkspaceProxy" ,
490
+ Actions : []policy.Action {policy .ActionCreate , policy .ActionUpdate , policy .ActionDelete },
491
+ Resource : rbac .ResourceWorkspaceProxy ,
492
+ AuthorizeMap : map [bool ][]authSubject {
493
+ true : {owner },
494
+ false : {orgAdmin , otherOrgAdmin , otherOrgMember , memberMe , orgMemberMe , templateAdmin , userAdmin },
495
+ },
496
+ },
497
+ {
498
+ Name : "WorkspaceProxyRead" ,
499
+ Actions : []policy.Action {policy .ActionRead },
500
+ Resource : rbac .ResourceWorkspaceProxy ,
501
+ AuthorizeMap : map [bool ][]authSubject {
502
+ true : {owner , orgAdmin , otherOrgAdmin , otherOrgMember , memberMe , orgMemberMe , templateAdmin , userAdmin },
503
+ false : {},
504
+ },
505
+ },
506
+ }
507
+
508
+ // We expect every permission to be tested above.
509
+ remainingPermissions := make (map [string ]map [policy.Action ]bool )
510
+ for rtype , perms := range policy .RBACPermissions {
511
+ remainingPermissions [rtype ] = make (map [policy.Action ]bool )
512
+ for action := range perms .Actions {
513
+ remainingPermissions [rtype ][action ] = true
514
+ }
340
515
}
341
516
342
517
for _ , c := range testCases {
343
518
c := c
519
+ // nolint:tparallel -- These share the same remainingPermissions map
344
520
t .Run (c .Name , func (t * testing.T ) {
345
- t .Parallel ()
346
521
remainingSubjs := make (map [string ]struct {})
347
522
for _ , subj := range requiredSubjects {
348
523
remainingSubjs [subj .Name ] = struct {}{}
@@ -359,6 +534,8 @@ func TestRolePermissions(t *testing.T) {
359
534
if actor .Scope == nil {
360
535
actor .Scope = rbac .ScopeAll
361
536
}
537
+
538
+ delete (remainingPermissions [c .Resource .Type ], action )
362
539
err := auth .Authorize (context .Background (), actor , action , c .Resource )
363
540
if result {
364
541
assert .NoError (t , err , fmt .Sprintf ("Should pass: %s" , msg ))
@@ -371,6 +548,15 @@ func TestRolePermissions(t *testing.T) {
371
548
require .Empty (t , remainingSubjs , "test should cover all subjects" )
372
549
})
373
550
}
551
+
552
+ for rtype , v := range remainingPermissions {
553
+ // nolint:tparallel -- Making a subtest for easier diagnosing failures.
554
+ t .Run (fmt .Sprintf ("%s-AllActions" , rtype ), func (t * testing.T ) {
555
+ if len (v ) > 0 {
556
+ assert .Equal (t , map [policy.Action ]bool {}, v , "remaining permissions should be empty for type %q" , rtype )
557
+ }
558
+ })
559
+ }
374
560
}
375
561
376
562
func TestIsOrgRole (t * testing.T ) {
0 commit comments