@@ -2,6 +2,7 @@ package coderdtest
2
2
3
3
import (
4
4
"context"
5
+ "fmt"
5
6
"io"
6
7
"net/http"
7
8
"strconv"
@@ -43,6 +44,7 @@ type AuthTester struct {
43
44
File codersdk.UploadResponse
44
45
TemplateVersionDryRun codersdk.ProvisionerJob
45
46
TemplateParam codersdk.Parameter
47
+ URLParams map [string ]string
46
48
}
47
49
48
50
func NewAuthTester (ctx context.Context , t * testing.T , options * Options ) * AuthTester {
@@ -86,7 +88,7 @@ func NewAuthTester(ctx context.Context, t *testing.T, options *Options) *AuthTes
86
88
Id : "something" ,
87
89
Auth : & proto.Agent_Token {},
88
90
Apps : []* proto.App {{
89
- Name : "app " ,
91
+ Name : "testapp " ,
90
92
Url : "http://localhost:3000" ,
91
93
}},
92
94
}},
@@ -116,6 +118,28 @@ func NewAuthTester(ctx context.Context, t *testing.T, options *Options) *AuthTes
116
118
})
117
119
require .NoError (t , err , "create template param" )
118
120
121
+ urlParameters := map [string ]string {
122
+ "{organization}" : admin .OrganizationID .String (),
123
+ "{user}" : admin .UserID .String (),
124
+ "{organizationname}" : organization .Name ,
125
+ "{workspace}" : workspace .ID .String (),
126
+ "{workspacebuild}" : workspace .LatestBuild .ID .String (),
127
+ "{workspacename}" : workspace .Name ,
128
+ "{workspacebuildname}" : workspace .LatestBuild .Name ,
129
+ "{workspaceagent}" : workspaceResources [0 ].Agents [0 ].ID .String (),
130
+ "{buildnumber}" : strconv .FormatInt (int64 (workspace .LatestBuild .BuildNumber ), 10 ),
131
+ "{template}" : template .ID .String (),
132
+ "{hash}" : file .Hash ,
133
+ "{workspaceresource}" : workspaceResources [0 ].ID .String (),
134
+ "{workspaceapp}" : workspaceResources [0 ].Agents [0 ].Apps [0 ].Name ,
135
+ "{templateversion}" : version .ID .String (),
136
+ "{jobID}" : templateVersionDryRun .ID .String (),
137
+ "{templatename}" : template .Name ,
138
+ // Only checking template scoped params here
139
+ "parameters/{scope}/{id}" : fmt .Sprintf ("parameters/%s/%s" ,
140
+ string (templateParam .Scope ), templateParam .ScopeID .String ()),
141
+ }
142
+
119
143
return & AuthTester {
120
144
t : t ,
121
145
api : api ,
@@ -130,6 +154,7 @@ func NewAuthTester(ctx context.Context, t *testing.T, options *Options) *AuthTes
130
154
File : file ,
131
155
TemplateVersionDryRun : templateVersionDryRun ,
132
156
TemplateParam : templateParam ,
157
+ URLParams : urlParameters ,
133
158
}
134
159
}
135
160
@@ -153,13 +178,13 @@ func AGPLRoutes(a *AuthTester) (map[string]string, map[string]RouteCheck) {
153
178
"POST:/api/v2/csp/reports" : {NoAuthorize : true },
154
179
"GET:/api/v2/entitlements" : {NoAuthorize : true },
155
180
156
- "GET:/%40{user}/{workspacename}/apps/{application }/*" : {
157
- AssertAction : rbac .ActionRead ,
158
- AssertObject : workspaceRBACObj ,
181
+ "GET:/%40{user}/{workspacename}/apps/{workspaceapp }/*" : {
182
+ AssertAction : rbac .ActionCreate ,
183
+ AssertObject : workspaceExecObj ,
159
184
},
160
- "GET:/@{user}/{workspacename}/apps/{application }/*" : {
161
- AssertAction : rbac .ActionRead ,
162
- AssertObject : workspaceRBACObj ,
185
+ "GET:/@{user}/{workspacename}/apps/{workspaceapp }/*" : {
186
+ AssertAction : rbac .ActionCreate ,
187
+ AssertObject : workspaceExecObj ,
163
188
},
164
189
165
190
// Has it's own auth
@@ -188,7 +213,7 @@ func AGPLRoutes(a *AuthTester) (map[string]string, map[string]RouteCheck) {
188
213
AssertObject : rbac .ResourceWorkspace ,
189
214
AssertAction : rbac .ActionRead ,
190
215
},
191
- "GET:/api/v2/users/me /workspace/{workspacename}/builds/{buildnumber}" : {
216
+ "GET:/api/v2/users/{user} /workspace/{workspacename}/builds/{buildnumber}" : {
192
217
AssertObject : rbac .ResourceWorkspace ,
193
218
AssertAction : rbac .ActionRead ,
194
219
},
@@ -216,7 +241,7 @@ func AGPLRoutes(a *AuthTester) (map[string]string, map[string]RouteCheck) {
216
241
AssertAction : rbac .ActionUpdate ,
217
242
AssertObject : workspaceRBACObj ,
218
243
},
219
- "PUT:/api/v2/workspaces/{workspace}/autostop " : {
244
+ "PUT:/api/v2/workspaces/{workspace}/ttl " : {
220
245
AssertAction : rbac .ActionUpdate ,
221
246
AssertObject : workspaceRBACObj ,
222
247
},
@@ -275,7 +300,7 @@ func AGPLRoutes(a *AuthTester) (map[string]string, map[string]RouteCheck) {
275
300
AssertObject : rbac .ResourceTemplate .InOrg (a .Template .OrganizationID ),
276
301
},
277
302
"POST:/api/v2/files" : {AssertAction : rbac .ActionCreate , AssertObject : rbac .ResourceFile },
278
- "GET:/api/v2/files/{fileHash }" : {
303
+ "GET:/api/v2/files/{hash }" : {
279
304
AssertAction : rbac .ActionRead ,
280
305
AssertObject : rbac .ResourceFile .WithOwner (a .Admin .UserID .String ()),
281
306
},
@@ -320,19 +345,19 @@ func AGPLRoutes(a *AuthTester) (map[string]string, map[string]RouteCheck) {
320
345
AssertAction : rbac .ActionRead ,
321
346
AssertObject : rbac .ResourceTemplate .InOrg (a .Version .OrganizationID ),
322
347
},
323
- "GET:/api/v2/templateversions/{templateversion}/dry-run/{templateversiondryrun }" : {
348
+ "GET:/api/v2/templateversions/{templateversion}/dry-run/{jobID }" : {
324
349
AssertAction : rbac .ActionRead ,
325
350
AssertObject : rbac .ResourceTemplate .InOrg (a .Version .OrganizationID ),
326
351
},
327
- "GET:/api/v2/templateversions/{templateversion}/dry-run/{templateversiondryrun }/resources" : {
352
+ "GET:/api/v2/templateversions/{templateversion}/dry-run/{jobID }/resources" : {
328
353
AssertAction : rbac .ActionRead ,
329
354
AssertObject : rbac .ResourceTemplate .InOrg (a .Version .OrganizationID ),
330
355
},
331
- "GET:/api/v2/templateversions/{templateversion}/dry-run/{templateversiondryrun }/logs" : {
356
+ "GET:/api/v2/templateversions/{templateversion}/dry-run/{jobID }/logs" : {
332
357
AssertAction : rbac .ActionRead ,
333
358
AssertObject : rbac .ResourceTemplate .InOrg (a .Version .OrganizationID ),
334
359
},
335
- "PATCH:/api/v2/templateversions/{templateversion}/dry-run/{templateversiondryrun }/cancel" : {
360
+ "PATCH:/api/v2/templateversions/{templateversion}/dry-run/{jobID }/cancel" : {
336
361
AssertAction : rbac .ActionRead ,
337
362
AssertObject : rbac .ResourceTemplate .InOrg (a .Version .OrganizationID ),
338
363
},
@@ -366,10 +391,6 @@ func AGPLRoutes(a *AuthTester) (map[string]string, map[string]RouteCheck) {
366
391
AssertAction : rbac .ActionRead ,
367
392
AssertObject : workspaceRBACObj ,
368
393
},
369
- "POST:/api/v2/users/{user}/organizations" : {
370
- AssertAction : rbac .ActionCreate ,
371
- AssertObject : rbac .ResourceOrganization ,
372
- },
373
394
"GET:/api/v2/users" : {StatusCode : http .StatusOK , AssertObject : rbac .ResourceUser },
374
395
375
396
// These endpoints need payloads to get to the auth part. Payloads will be required
@@ -385,13 +406,15 @@ func (a *AuthTester) Test(ctx context.Context, assertRoute map[string]RouteCheck
385
406
// Always fail auth from this point forward
386
407
a .authorizer .AlwaysReturn = rbac .ForbiddenWithInternal (xerrors .New ("fake implementation" ), nil , nil )
387
408
409
+ routeMissing := make (map [string ]bool )
388
410
for k , v := range assertRoute {
389
411
noTrailSlash := strings .TrimRight (k , "/" )
390
412
if _ , ok := assertRoute [noTrailSlash ]; ok && noTrailSlash != k {
391
413
a .t .Errorf ("route %q & %q is declared twice" , noTrailSlash , k )
392
414
a .t .FailNow ()
393
415
}
394
416
assertRoute [noTrailSlash ] = v
417
+ routeMissing [noTrailSlash ] = true
395
418
}
396
419
397
420
for k , v := range skipRoutes {
@@ -422,32 +445,18 @@ func (a *AuthTester) Test(ctx context.Context, assertRoute map[string]RouteCheck
422
445
}
423
446
a .t .Run (name , func (t * testing.T ) {
424
447
a .authorizer .reset ()
425
- routeAssertions , ok := assertRoute [strings .TrimRight (name , "/" )]
448
+ routeKey := strings .TrimRight (name , "/" )
449
+ routeAssertions , ok := assertRoute [routeKey ]
426
450
if ! ok {
427
451
// By default, all omitted routes check for just "authorize" called
428
452
routeAssertions = RouteCheck {}
429
453
}
454
+ delete (routeMissing , routeKey )
430
455
431
456
// Replace all url params with known values
432
- route = strings .ReplaceAll (route , "{organization}" , a .Admin .OrganizationID .String ())
433
- route = strings .ReplaceAll (route , "{user}" , a .Admin .UserID .String ())
434
- route = strings .ReplaceAll (route , "{organizationname}" , a .Organization .Name )
435
- route = strings .ReplaceAll (route , "{workspace}" , a .Workspace .ID .String ())
436
- route = strings .ReplaceAll (route , "{workspacebuild}" , a .Workspace .LatestBuild .ID .String ())
437
- route = strings .ReplaceAll (route , "{workspacename}" , a .Workspace .Name )
438
- route = strings .ReplaceAll (route , "{workspacebuildname}" , a .Workspace .LatestBuild .Name )
439
- route = strings .ReplaceAll (route , "{workspaceagent}" , a .WorkspaceResource .Agents [0 ].ID .String ())
440
- route = strings .ReplaceAll (route , "{buildnumber}" , strconv .FormatInt (int64 (a .Workspace .LatestBuild .BuildNumber ), 10 ))
441
- route = strings .ReplaceAll (route , "{template}" , a .Template .ID .String ())
442
- route = strings .ReplaceAll (route , "{hash}" , a .File .Hash )
443
- route = strings .ReplaceAll (route , "{workspaceresource}" , a .WorkspaceResource .ID .String ())
444
- route = strings .ReplaceAll (route , "{workspaceapp}" , a .WorkspaceResource .Agents [0 ].Apps [0 ].Name )
445
- route = strings .ReplaceAll (route , "{templateversion}" , a .Version .ID .String ())
446
- route = strings .ReplaceAll (route , "{templateversiondryrun}" , a .TemplateVersionDryRun .ID .String ())
447
- route = strings .ReplaceAll (route , "{templatename}" , a .Template .Name )
448
- // Only checking template scoped params here
449
- route = strings .ReplaceAll (route , "{scope}" , string (a .TemplateParam .Scope ))
450
- route = strings .ReplaceAll (route , "{id}" , a .TemplateParam .ScopeID .String ())
457
+ for k , v := range a .URLParams {
458
+ route = strings .ReplaceAll (route , k , v )
459
+ }
451
460
452
461
resp , err := a .Client .Request (ctx , method , route , nil )
453
462
require .NoError (t , err , "do req" )
@@ -486,6 +495,7 @@ func (a *AuthTester) Test(ctx context.Context, assertRoute map[string]RouteCheck
486
495
return nil
487
496
})
488
497
require .NoError (a .t , err )
498
+ require .Len (a .t , routeMissing , 0 , "didn't walk some asserted routes: %v" , routeMissing )
489
499
}
490
500
491
501
type authCall struct {
0 commit comments