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

chore: Implement standard rbac.Subject to be reused everywhere#5881

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Merged
Emyrk merged 4 commits intomainfromstevenmasley/standard_rbac_subject
Jan 26, 2023
Merged
Show file tree
Hide file tree
Changes fromall commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 14 additions & 12 deletionscoderd/authorize.go
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -19,14 +19,15 @@ import (
// This is faster than calling Authorize() on each object.
funcAuthorizeFilter[O rbac.Objecter](h*HTTPAuthorizer,r*http.Request,action rbac.Action,objects []O) ([]O,error) {
roles:=httpmw.UserAuthorization(r)
objects,err:=rbac.Filter(r.Context(),h.Authorizer,roles.ID.String(),roles.Roles,roles.Scope.ToRBAC(),roles.Groups,action,objects)
objects,err:=rbac.Filter(r.Context(),h.Authorizer,roles.Actor,action,objects)
iferr!=nil {
// Log the error as Filter should not be erroring.
h.Logger.Error(r.Context(),"filter failed",
slog.Error(err),
slog.F("user_id",roles.ID),
slog.F("user_id",roles.Actor.ID),
slog.F("username",roles.Username),
slog.F("scope",roles.Scope),
slog.F("roles",roles.Actor.SafeRoleNames()),
slog.F("scope",roles.Actor.SafeScopeName()),
slog.F("route",r.URL.Path),
slog.F("action",action),
)
Expand DownExpand Up@@ -64,7 +65,7 @@ func (api *API) Authorize(r *http.Request, action rbac.Action, object rbac.Objec
//}
func (h*HTTPAuthorizer)Authorize(r*http.Request,action rbac.Action,object rbac.Objecter)bool {
roles:=httpmw.UserAuthorization(r)
err:=h.Authorizer.ByRoleName(r.Context(),roles.ID.String(),roles.Roles,roles.Scope.ToRBAC(),roles.Groups,action,object.RBACObject())
err:=h.Authorizer.Authorize(r.Context(),roles.Actor,action,object.RBACObject())
iferr!=nil {
// Log the errors for debugging
internalError:=new(rbac.UnauthorizedError)
Expand All@@ -75,10 +76,10 @@ func (h *HTTPAuthorizer) Authorize(r *http.Request, action rbac.Action, object r
// Log information for debugging. This will be very helpful
// in the early days
logger.Warn(r.Context(),"unauthorized",
slog.F("roles",roles.Roles),
slog.F("user_id",roles.ID),
slog.F("roles",roles.Actor.SafeRoleNames()),
slog.F("user_id",roles.Actor.ID),
slog.F("username",roles.Username),
slog.F("scope",roles.Scope),
slog.F("scope",roles.Actor.SafeScopeName()),
slog.F("route",r.URL.Path),
slog.F("action",action),
slog.F("object",object),
Expand All@@ -96,7 +97,7 @@ func (h *HTTPAuthorizer) Authorize(r *http.Request, action rbac.Action, object r
// Note the authorization is only for the given action and object type.
func (h*HTTPAuthorizer)AuthorizeSQLFilter(r*http.Request,action rbac.Action,objectTypestring) (rbac.PreparedAuthorized,error) {
roles:=httpmw.UserAuthorization(r)
prepared,err:=h.Authorizer.PrepareByRoleName(r.Context(),roles.ID.String(),roles.Roles,roles.Scope.ToRBAC(),roles.Groups,action,objectType)
prepared,err:=h.Authorizer.Prepare(r.Context(),roles.Actor,action,objectType)
iferr!=nil {
returnnil,xerrors.Errorf("prepare filter: %w",err)
}
Expand DownExpand Up@@ -127,9 +128,10 @@ func (api *API) checkAuthorization(rw http.ResponseWriter, r *http.Request) {

api.Logger.Debug(ctx,"check-auth",
slog.F("my_id",httpmw.APIKey(r).UserID),
slog.F("got_id",auth.ID),
slog.F("got_id",auth.Actor.ID),
slog.F("name",auth.Username),
slog.F("roles",auth.Roles),slog.F("scope",auth.Scope),
slog.F("roles",auth.Actor.SafeRoleNames()),
slog.F("scope",auth.Actor.SafeScopeName()),
)

response:=make(codersdk.AuthorizationResponse)
Expand DownExpand Up@@ -169,7 +171,7 @@ func (api *API) checkAuthorization(rw http.ResponseWriter, r *http.Request) {
Type:v.Object.ResourceType,
}
ifobj.Owner=="me" {
obj.Owner=auth.ID.String()
obj.Owner=auth.Actor.ID
}

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

err:=api.Authorizer.ByRoleName(ctx,auth.ID.String(),auth.Roles,auth.Scope.ToRBAC(),auth.Groups,rbac.Action(v.Action),obj)
err:=api.Authorizer.Authorize(ctx,auth.Actor,rbac.Action(v.Action),obj)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

This is so much nicer and more readable ❤️

response[k]=err==nil
}

Expand Down
40 changes: 14 additions & 26 deletionscoderd/coderdtest/authorize.go
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -533,12 +533,9 @@ func (a *AuthTester) Test(ctx context.Context, assertRoute map[string]RouteCheck
}

type authCall struct {
SubjectID string
Roles rbac.ExpandableRoles
Groups []string
Scope rbac.ScopeName
Action rbac.Action
Object rbac.Object
Subject rbac.Subject
Action rbac.Action
Object rbac.Object
}

type RecordingAuthorizer struct {
Expand All@@ -548,33 +545,27 @@ type RecordingAuthorizer struct {

var _ rbac.Authorizer = (*RecordingAuthorizer)(nil)

//ByRoleNameSQL does not record the call. This matches the postgres behavior
//AuthorizeSQL does not record the call. This matches the postgres behavior
// of not calling Authorize()
func (r *RecordingAuthorizer)ByRoleNameSQL(_ context.Context, _string, _rbac.ExpandableRoles, _ rbac.ScopeName, _ []string, _ rbac.Action, _ rbac.Object) error {
func (r *RecordingAuthorizer)AuthorizeSQL(_ context.Context, _ rbac.Subject, _ rbac.Action, _ rbac.Object) error {
return r.AlwaysReturn
}

func (r *RecordingAuthorizer)ByRoleName(_ context.Context,subjectID string, roleNamesrbac.ExpandableRoles, scope rbac.ScopeName, groups []string, action rbac.Action, object rbac.Object) error {
func (r *RecordingAuthorizer)Authorize(_ context.Context,subjectrbac.Subject, action rbac.Action, object rbac.Object) error {
r.Called = &authCall{
SubjectID: subjectID,
Roles: roleNames,
Groups: groups,
Scope: scope,
Action: action,
Object: object,
Subject: subject,
Action: action,
Object: object,
}
return r.AlwaysReturn
}

func (r *RecordingAuthorizer)PrepareByRoleName(_ context.Context,subjectID string, rolesrbac.ExpandableRoles, scope rbac.ScopeName, groups []string, action rbac.Action, _ string) (rbac.PreparedAuthorized, error) {
func (r *RecordingAuthorizer)Prepare(_ context.Context,subjectrbac.Subject, action rbac.Action, _ string) (rbac.PreparedAuthorized, error) {
return &fakePreparedAuthorizer{
Original: r,
SubjectID: subjectID,
Roles: roles,
Scope: scope,
Subject: subject,
Action: action,
HardCodedSQLString: "true",
Groups: groups,
}, nil
}

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

type fakePreparedAuthorizer struct {
Original *RecordingAuthorizer
SubjectID string
Roles rbac.ExpandableRoles
Scope rbac.ScopeName
Subject rbac.Subject
Action rbac.Action
Groups []string
HardCodedSQLString string
HardCodedRegoString string
}

func (f *fakePreparedAuthorizer) Authorize(ctx context.Context, object rbac.Object) error {
return f.Original.ByRoleName(ctx, f.SubjectID, f.Roles, f.Scope, f.Groups, f.Action, object)
return f.Original.Authorize(ctx, f.Subject, f.Action, object)
}

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

func (f *fakePreparedAuthorizer) Eval(object rbac.Object) bool {
return f.Original.ByRoleNameSQL(context.Background(), f.SubjectID, f.Roles, f.Scope, f.Groups, f.Action, object) == nil
return f.Original.AuthorizeSQL(context.Background(), f.Subject, f.Action, object) == nil
}

func (f fakePreparedAuthorizer) RegoString() string {
Expand Down
17 changes: 9 additions & 8 deletionscoderd/httpmw/apikey.go
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -52,11 +52,10 @@ func APIKey(r *http.Request) database.APIKey {
type userAuthKey struct{}

type Authorization struct {
ID uuid.UUID
Actor rbac.Subject
// Username is required for logging and human friendly related
// identification.
Username string
Roles rbac.RoleNames
Groups []string
Scope database.APIKeyScope
}

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

ctx = context.WithValue(ctx, apiKeyContextKey{}, key)
ctx = context.WithValue(ctx, userAuthKey{}, Authorization{
ID: key.UserID,
Username: roles.Username,
Roles: roles.Roles,
Scope: key.Scope,
Groups: roles.Groups,
Actor: rbac.Subject{
ID: key.UserID.String(),
Roles: rbac.RoleNames(roles.Roles),
Groups: roles.Groups,
Scope: rbac.ScopeName(key.Scope),
},
})

next.ServeHTTP(rw, r.WithContext(ctx))
Expand Down
4 changes: 2 additions & 2 deletionscoderd/httpmw/authorize_test.go
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -126,8 +126,8 @@ func TestExtractUserRoles(t *testing.T) {
)
rtr.Get("/", func(_ http.ResponseWriter, r *http.Request) {
roles := httpmw.UserAuthorization(r)
require.ElementsMatch(t, user.ID, roles.ID)
require.ElementsMatch(t, expRoles, roles.Roles)
require.Equal(t, user.ID.String(), roles.Actor.ID)
require.ElementsMatch(t, expRoles, roles.Actor.Roles.Names())
})

req := httptest.NewRequest("GET", "/", nil)
Expand Down
2 changes: 1 addition & 1 deletioncoderd/httpmw/ratelimit.go
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -47,7 +47,7 @@ func RateLimit(count int, window time.Duration) func(http.Handler) http.Handler

// We avoid using rbac.Authorizer since rego is CPU-intensive
// and undermines the DoS-prevention goal of the rate limiter.
for _, role := range auth.Roles {
for _, role := range auth.Actor.SafeRoleNames() {
if role == rbac.RoleOwner() {
// HACK: use a random key each time to
// de facto disable rate limiting. The
Expand Down
2 changes: 1 addition & 1 deletioncoderd/members.go
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -67,7 +67,7 @@ func (api *API) putMemberRoles(rw http.ResponseWriter, r *http.Request) {

// Just treat adding & removing as "assigning" for now.
for _, roleName := range append(added, removed...) {
if !rbac.CanAssignRole(actorRoles.Roles, roleName) {
if !rbac.CanAssignRole(actorRoles.Actor.Roles, roleName) {
httpapi.Forbidden(rw)
return
}
Expand Down
Loading

[8]ページ先頭

©2009-2025 Movatter.jp