Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitb0a1615

Browse files
authored
chore: Implement standard rbac.Subject to be reused everywhere (#5881)
* chore: Implement standard rbac.Subject to be reused everywhereAn rbac subject is created in multiple spots because of the way weexpand roles, scopes, etc. This difference in use creates a listof arguments which is unwieldy.Use of the expander interface lets us conform to a single subjectin every case
1 parent5c54d8b commitb0a1615

18 files changed

+449
-355
lines changed

‎coderd/authorize.go

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,15 @@ import (
1919
// This is faster than calling Authorize() on each object.
2020
funcAuthorizeFilter[O rbac.Objecter](h*HTTPAuthorizer,r*http.Request,action rbac.Action,objects []O) ([]O,error) {
2121
roles:=httpmw.UserAuthorization(r)
22-
objects,err:=rbac.Filter(r.Context(),h.Authorizer,roles.ID.String(),roles.Roles,roles.Scope.ToRBAC(),roles.Groups,action,objects)
22+
objects,err:=rbac.Filter(r.Context(),h.Authorizer,roles.Actor,action,objects)
2323
iferr!=nil {
2424
// Log the error as Filter should not be erroring.
2525
h.Logger.Error(r.Context(),"filter failed",
2626
slog.Error(err),
27-
slog.F("user_id",roles.ID),
27+
slog.F("user_id",roles.Actor.ID),
2828
slog.F("username",roles.Username),
29-
slog.F("scope",roles.Scope),
29+
slog.F("roles",roles.Actor.SafeRoleNames()),
30+
slog.F("scope",roles.Actor.SafeScopeName()),
3031
slog.F("route",r.URL.Path),
3132
slog.F("action",action),
3233
)
@@ -64,7 +65,7 @@ func (api *API) Authorize(r *http.Request, action rbac.Action, object rbac.Objec
6465
//}
6566
func (h*HTTPAuthorizer)Authorize(r*http.Request,action rbac.Action,object rbac.Objecter)bool {
6667
roles:=httpmw.UserAuthorization(r)
67-
err:=h.Authorizer.ByRoleName(r.Context(),roles.ID.String(),roles.Roles,roles.Scope.ToRBAC(),roles.Groups,action,object.RBACObject())
68+
err:=h.Authorizer.Authorize(r.Context(),roles.Actor,action,object.RBACObject())
6869
iferr!=nil {
6970
// Log the errors for debugging
7071
internalError:=new(rbac.UnauthorizedError)
@@ -75,10 +76,10 @@ func (h *HTTPAuthorizer) Authorize(r *http.Request, action rbac.Action, object r
7576
// Log information for debugging. This will be very helpful
7677
// in the early days
7778
logger.Warn(r.Context(),"unauthorized",
78-
slog.F("roles",roles.Roles),
79-
slog.F("user_id",roles.ID),
79+
slog.F("roles",roles.Actor.SafeRoleNames()),
80+
slog.F("user_id",roles.Actor.ID),
8081
slog.F("username",roles.Username),
81-
slog.F("scope",roles.Scope),
82+
slog.F("scope",roles.Actor.SafeScopeName()),
8283
slog.F("route",r.URL.Path),
8384
slog.F("action",action),
8485
slog.F("object",object),
@@ -96,7 +97,7 @@ func (h *HTTPAuthorizer) Authorize(r *http.Request, action rbac.Action, object r
9697
// Note the authorization is only for the given action and object type.
9798
func (h*HTTPAuthorizer)AuthorizeSQLFilter(r*http.Request,action rbac.Action,objectTypestring) (rbac.PreparedAuthorized,error) {
9899
roles:=httpmw.UserAuthorization(r)
99-
prepared,err:=h.Authorizer.PrepareByRoleName(r.Context(),roles.ID.String(),roles.Roles,roles.Scope.ToRBAC(),roles.Groups,action,objectType)
100+
prepared,err:=h.Authorizer.Prepare(r.Context(),roles.Actor,action,objectType)
100101
iferr!=nil {
101102
returnnil,xerrors.Errorf("prepare filter: %w",err)
102103
}
@@ -127,9 +128,10 @@ func (api *API) checkAuthorization(rw http.ResponseWriter, r *http.Request) {
127128

128129
api.Logger.Debug(ctx,"check-auth",
129130
slog.F("my_id",httpmw.APIKey(r).UserID),
130-
slog.F("got_id",auth.ID),
131+
slog.F("got_id",auth.Actor.ID),
131132
slog.F("name",auth.Username),
132-
slog.F("roles",auth.Roles),slog.F("scope",auth.Scope),
133+
slog.F("roles",auth.Actor.SafeRoleNames()),
134+
slog.F("scope",auth.Actor.SafeScopeName()),
133135
)
134136

135137
response:=make(codersdk.AuthorizationResponse)
@@ -169,7 +171,7 @@ func (api *API) checkAuthorization(rw http.ResponseWriter, r *http.Request) {
169171
Type:v.Object.ResourceType,
170172
}
171173
ifobj.Owner=="me" {
172-
obj.Owner=auth.ID.String()
174+
obj.Owner=auth.Actor.ID
173175
}
174176

175177
// If a resource ID is specified, fetch that specific resource.
@@ -217,7 +219,7 @@ func (api *API) checkAuthorization(rw http.ResponseWriter, r *http.Request) {
217219
obj=dbObj.RBACObject()
218220
}
219221

220-
err:=api.Authorizer.ByRoleName(ctx,auth.ID.String(),auth.Roles,auth.Scope.ToRBAC(),auth.Groups,rbac.Action(v.Action),obj)
222+
err:=api.Authorizer.Authorize(ctx,auth.Actor,rbac.Action(v.Action),obj)
221223
response[k]=err==nil
222224
}
223225

‎coderd/coderdtest/authorize.go

Lines changed: 14 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -533,12 +533,9 @@ func (a *AuthTester) Test(ctx context.Context, assertRoute map[string]RouteCheck
533533
}
534534

535535
typeauthCallstruct {
536-
SubjectIDstring
537-
Roles rbac.ExpandableRoles
538-
Groups []string
539-
Scope rbac.ScopeName
540-
Action rbac.Action
541-
Object rbac.Object
536+
Subject rbac.Subject
537+
Action rbac.Action
538+
Object rbac.Object
542539
}
543540

544541
typeRecordingAuthorizerstruct {
@@ -548,33 +545,27 @@ type RecordingAuthorizer struct {
548545

549546
var_ rbac.Authorizer= (*RecordingAuthorizer)(nil)
550547

551-
//ByRoleNameSQL does not record the call. This matches the postgres behavior
548+
//AuthorizeSQL does not record the call. This matches the postgres behavior
552549
// of not calling Authorize()
553-
func (r*RecordingAuthorizer)ByRoleNameSQL(_ context.Context,_string,_rbac.ExpandableRoles,_ rbac.ScopeName,_ []string,_ rbac.Action,_ rbac.Object)error {
550+
func (r*RecordingAuthorizer)AuthorizeSQL(_ context.Context,_ rbac.Subject,_ rbac.Action,_ rbac.Object)error {
554551
returnr.AlwaysReturn
555552
}
556553

557-
func (r*RecordingAuthorizer)ByRoleName(_ context.Context,subjectIDstring,roleNamesrbac.ExpandableRoles,scope rbac.ScopeName,groups []string,action rbac.Action,object rbac.Object)error {
554+
func (r*RecordingAuthorizer)Authorize(_ context.Context,subjectrbac.Subject,action rbac.Action,object rbac.Object)error {
558555
r.Called=&authCall{
559-
SubjectID:subjectID,
560-
Roles:roleNames,
561-
Groups:groups,
562-
Scope:scope,
563-
Action:action,
564-
Object:object,
556+
Subject:subject,
557+
Action:action,
558+
Object:object,
565559
}
566560
returnr.AlwaysReturn
567561
}
568562

569-
func (r*RecordingAuthorizer)PrepareByRoleName(_ context.Context,subjectIDstring,rolesrbac.ExpandableRoles,scope rbac.ScopeName,groups []string,action rbac.Action,_string) (rbac.PreparedAuthorized,error) {
563+
func (r*RecordingAuthorizer)Prepare(_ context.Context,subjectrbac.Subject,action rbac.Action,_string) (rbac.PreparedAuthorized,error) {
570564
return&fakePreparedAuthorizer{
571565
Original:r,
572-
SubjectID:subjectID,
573-
Roles:roles,
574-
Scope:scope,
566+
Subject:subject,
575567
Action:action,
576568
HardCodedSQLString:"true",
577-
Groups:groups,
578569
},nil
579570
}
580571

@@ -584,17 +575,14 @@ func (r *RecordingAuthorizer) reset() {
584575

585576
typefakePreparedAuthorizerstruct {
586577
Original*RecordingAuthorizer
587-
SubjectIDstring
588-
Roles rbac.ExpandableRoles
589-
Scope rbac.ScopeName
578+
Subject rbac.Subject
590579
Action rbac.Action
591-
Groups []string
592580
HardCodedSQLStringstring
593581
HardCodedRegoStringstring
594582
}
595583

596584
func (f*fakePreparedAuthorizer)Authorize(ctx context.Context,object rbac.Object)error {
597-
returnf.Original.ByRoleName(ctx,f.SubjectID,f.Roles,f.Scope,f.Groups,f.Action,object)
585+
returnf.Original.Authorize(ctx,f.Subject,f.Action,object)
598586
}
599587

600588
// CompileToSQL returns a compiled version of the authorizer that will work for
@@ -604,7 +592,7 @@ func (fakePreparedAuthorizer) CompileToSQL(_ context.Context, _ regosql.ConvertC
604592
}
605593

606594
func (f*fakePreparedAuthorizer)Eval(object rbac.Object)bool {
607-
returnf.Original.ByRoleNameSQL(context.Background(),f.SubjectID,f.Roles,f.Scope,f.Groups,f.Action,object)==nil
595+
returnf.Original.AuthorizeSQL(context.Background(),f.Subject,f.Action,object)==nil
608596
}
609597

610598
func (ffakePreparedAuthorizer)RegoString()string {

‎coderd/httpmw/apikey.go

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -52,11 +52,10 @@ func APIKey(r *http.Request) database.APIKey {
5252
typeuserAuthKeystruct{}
5353

5454
typeAuthorizationstruct {
55-
ID uuid.UUID
55+
Actor rbac.Subject
56+
// Username is required for logging and human friendly related
57+
// identification.
5658
Usernamestring
57-
Roles rbac.RoleNames
58-
Groups []string
59-
Scope database.APIKeyScope
6059
}
6160

6261
// UserAuthorizationOptional may return the roles and scope used for
@@ -343,11 +342,13 @@ func ExtractAPIKey(cfg ExtractAPIKeyConfig) func(http.Handler) http.Handler {
343342

344343
ctx=context.WithValue(ctx,apiKeyContextKey{},key)
345344
ctx=context.WithValue(ctx,userAuthKey{},Authorization{
346-
ID:key.UserID,
347345
Username:roles.Username,
348-
Roles:roles.Roles,
349-
Scope:key.Scope,
350-
Groups:roles.Groups,
346+
Actor: rbac.Subject{
347+
ID:key.UserID.String(),
348+
Roles:rbac.RoleNames(roles.Roles),
349+
Groups:roles.Groups,
350+
Scope:rbac.ScopeName(key.Scope),
351+
},
351352
})
352353

353354
next.ServeHTTP(rw,r.WithContext(ctx))

‎coderd/httpmw/authorize_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -126,8 +126,8 @@ func TestExtractUserRoles(t *testing.T) {
126126
)
127127
rtr.Get("/",func(_ http.ResponseWriter,r*http.Request) {
128128
roles:=httpmw.UserAuthorization(r)
129-
require.ElementsMatch(t,user.ID,roles.ID)
130-
require.ElementsMatch(t,expRoles,roles.Roles)
129+
require.Equal(t,user.ID.String(),roles.Actor.ID)
130+
require.ElementsMatch(t,expRoles,roles.Actor.Roles.Names())
131131
})
132132

133133
req:=httptest.NewRequest("GET","/",nil)

‎coderd/httpmw/ratelimit.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ func RateLimit(count int, window time.Duration) func(http.Handler) http.Handler
4747

4848
// We avoid using rbac.Authorizer since rego is CPU-intensive
4949
// and undermines the DoS-prevention goal of the rate limiter.
50-
for_,role:=rangeauth.Roles {
50+
for_,role:=rangeauth.Actor.SafeRoleNames() {
5151
ifrole==rbac.RoleOwner() {
5252
// HACK: use a random key each time to
5353
// de facto disable rate limiting. The

‎coderd/members.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ func (api *API) putMemberRoles(rw http.ResponseWriter, r *http.Request) {
6767

6868
// Just treat adding & removing as "assigning" for now.
6969
for_,roleName:=rangeappend(added,removed...) {
70-
if!rbac.CanAssignRole(actorRoles.Roles,roleName) {
70+
if!rbac.CanAssignRole(actorRoles.Actor.Roles,roleName) {
7171
httpapi.Forbidden(rw)
7272
return
7373
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp