mirror of
https://github.com/coder/coder.git
synced 2026-09-24 15:04:27 +08:00
feat: Implement allow_list for scopes for resource specific permissions (#5769)
* feat: Implement allow_list for scopes for resource specific permissions Feature that adds an allow_list for scopes to specify particular resources. This enables workspace agent tokens to use the same RBAC system as users. - Add ID to compileSQL matchers * Plumb through WithID on rbac objects * Rename Scope -> ScopeName * Update input.json with scope allow_list Co-authored-by: Cian Johnston <cian@coder.com>
This commit is contained in:
co-authored by
Cian Johnston
parent
f0df0686f9
commit
08cce81ac8
+10
-10
@@ -18,8 +18,8 @@ import (
|
||||
)
|
||||
|
||||
type Authorizer interface {
|
||||
ByRoleName(ctx context.Context, subjectID string, roleNames []string, scope Scope, groups []string, action Action, object Object) error
|
||||
PrepareByRoleName(ctx context.Context, subjectID string, roleNames []string, scope Scope, groups []string, action Action, objectType string) (PreparedAuthorized, error)
|
||||
ByRoleName(ctx context.Context, subjectID string, roleNames []string, scope ScopeName, groups []string, action Action, object Object) error
|
||||
PrepareByRoleName(ctx context.Context, subjectID string, roleNames []string, scope ScopeName, groups []string, action Action, objectType string) (PreparedAuthorized, error)
|
||||
}
|
||||
|
||||
type PreparedAuthorized interface {
|
||||
@@ -33,7 +33,7 @@ type PreparedAuthorized interface {
|
||||
//
|
||||
// Ideally the 'CompileToSQL' is used instead for large sets. This cost scales
|
||||
// linearly with the number of objects passed in.
|
||||
func Filter[O Objecter](ctx context.Context, auth Authorizer, subjID string, subjRoles []string, scope Scope, groups []string, action Action, objects []O) ([]O, error) {
|
||||
func Filter[O Objecter](ctx context.Context, auth Authorizer, subjID string, subjRoles []string, scope ScopeName, groups []string, action Action, objects []O) ([]O, error) {
|
||||
if len(objects) == 0 {
|
||||
// Nothing to filter
|
||||
return objects, nil
|
||||
@@ -173,13 +173,13 @@ type authSubject struct {
|
||||
ID string `json:"id"`
|
||||
Roles []Role `json:"roles"`
|
||||
Groups []string `json:"groups"`
|
||||
Scope Role `json:"scope"`
|
||||
Scope Scope `json:"scope"`
|
||||
}
|
||||
|
||||
// ByRoleName will expand all roleNames into roles before calling Authorize().
|
||||
// This is the function intended to be used outside this package.
|
||||
// The role is fetched from the builtin map located in memory.
|
||||
func (a RegoAuthorizer) ByRoleName(ctx context.Context, subjectID string, roleNames []string, scope Scope, groups []string, action Action, object Object) error {
|
||||
func (a RegoAuthorizer) ByRoleName(ctx context.Context, subjectID string, roleNames []string, scope ScopeName, groups []string, action Action, object Object) error {
|
||||
start := time.Now()
|
||||
ctx, span := tracing.StartSpan(ctx,
|
||||
trace.WithTimestamp(start), // Reuse the time.Now for metric and trace
|
||||
@@ -197,7 +197,7 @@ func (a RegoAuthorizer) ByRoleName(ctx context.Context, subjectID string, roleNa
|
||||
return err
|
||||
}
|
||||
|
||||
scopeRole, err := ScopeRole(scope)
|
||||
scopeRole, err := ExpandScope(scope)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -216,7 +216,7 @@ func (a RegoAuthorizer) ByRoleName(ctx context.Context, subjectID string, roleNa
|
||||
|
||||
// Authorize allows passing in custom Roles.
|
||||
// This is really helpful for unit testing, as we can create custom roles to exercise edge cases.
|
||||
func (a RegoAuthorizer) Authorize(ctx context.Context, subjectID string, roles []Role, scope Role, groups []string, action Action, object Object) error {
|
||||
func (a RegoAuthorizer) Authorize(ctx context.Context, subjectID string, roles []Role, scope Scope, groups []string, action Action, object Object) error {
|
||||
input := map[string]interface{}{
|
||||
"subject": authSubject{
|
||||
ID: subjectID,
|
||||
@@ -239,7 +239,7 @@ func (a RegoAuthorizer) Authorize(ctx context.Context, subjectID string, roles [
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a RegoAuthorizer) PrepareByRoleName(ctx context.Context, subjectID string, roleNames []string, scope Scope, groups []string, action Action, objectType string) (PreparedAuthorized, error) {
|
||||
func (a RegoAuthorizer) PrepareByRoleName(ctx context.Context, subjectID string, roleNames []string, scope ScopeName, groups []string, action Action, objectType string) (PreparedAuthorized, error) {
|
||||
start := time.Now()
|
||||
ctx, span := tracing.StartSpan(ctx,
|
||||
trace.WithTimestamp(start),
|
||||
@@ -252,7 +252,7 @@ func (a RegoAuthorizer) PrepareByRoleName(ctx context.Context, subjectID string,
|
||||
return nil, err
|
||||
}
|
||||
|
||||
scopeRole, err := ScopeRole(scope)
|
||||
scopeRole, err := ExpandScope(scope)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -275,7 +275,7 @@ func (a RegoAuthorizer) PrepareByRoleName(ctx context.Context, subjectID string,
|
||||
|
||||
// Prepare will partially execute the rego policy leaving the object fields unknown (except for the type).
|
||||
// This will vastly speed up performance if batch authorization on the same type of objects is needed.
|
||||
func (RegoAuthorizer) Prepare(ctx context.Context, subjectID string, roles []Role, scope Role, groups []string, action Action, objectType string) (*PartialAuthorizer, error) {
|
||||
func (RegoAuthorizer) Prepare(ctx context.Context, subjectID string, roles []Role, scope Scope, groups []string, action Action, objectType string) (*PartialAuthorizer, error) {
|
||||
auth, err := newPartialAuthorizer(ctx, subjectID, roles, scope, groups, action, objectType)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("new partial authorizer: %w", err)
|
||||
|
||||
Reference in New Issue
Block a user