Skip to content

chore: Move scope into the same auth call #4162

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 our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Sep 23, 2022
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
Prev Previous commit
Next Next commit
pass scope in partial executations
  • Loading branch information
Emyrk committed Sep 22, 2022
commit 2247a72661c29b439c1fc02dbbfca65c85df7db0
12 changes: 9 additions & 3 deletions coderd/rbac/authz.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ func NewAuthorizer() (*RegoAuthorizer, error) {
type authSubject struct {
ID string `json:"id"`
Roles []Role `json:"roles"`
Scope Role `json:"scope"`
}

// ByRoleName will expand all roleNames into roles before calling Authorize().
Expand Down Expand Up @@ -122,8 +123,8 @@ func (a RegoAuthorizer) Authorize(ctx context.Context, subjectID string, roles [
"subject": authSubject{
ID: subjectID,
Roles: roles,
Scope: scope,
},
"scope": scope,
"object": object,
"action": action,
}
Expand All @@ -147,7 +148,7 @@ func (a RegoAuthorizer) Authorize(ctx context.Context, subjectID string, roles [

// 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 Scope, action Action, objectType string) (*PartialAuthorizer, error) {
func (RegoAuthorizer) Prepare(ctx context.Context, subjectID string, roles []Role, scope Role, action Action, objectType string) (*PartialAuthorizer, error) {
ctx, span := tracing.StartSpan(ctx)
defer span.End()

Expand All @@ -168,5 +169,10 @@ func (a RegoAuthorizer) PrepareByRoleName(ctx context.Context, subjectID string,
return nil, err
}

return a.Prepare(ctx, subjectID, roles, scope, action, objectType)
scopeRole, err := ScopeRole(scope)
if err != nil {
return nil, err
}

return a.Prepare(ctx, subjectID, roles, scopeRole, action, objectType)
}
2 changes: 1 addition & 1 deletion coderd/rbac/authz_internal_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -741,7 +741,7 @@ func testAuthorize(t *testing.T, name string, subject subject, sets ...[]authTes
assert.Error(t, authError, "expected unauthorized")
}

partialAuthz, err := authorizer.Prepare(ctx, subject.UserID, subject.Roles, ScopeAll, a, c.resource.Type)
partialAuthz, err := authorizer.Prepare(ctx, subject.UserID, subject.Roles, must(ScopeRole(ScopeAll)), a, c.resource.Type)
require.NoError(t, err, "make prepared authorizer")

// Also check the rego policy can form a valid partial query result.
Expand Down
5 changes: 3 additions & 2 deletions coderd/rbac/partial.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,14 +94,15 @@ EachQueryLoop:
return ForbiddenWithInternal(xerrors.Errorf("policy disallows request"), pa.input, nil)
}

func newPartialAuthorizer(ctx context.Context, subjectID string, roles []Role, scope Scope, action Action, objectType string) (*PartialAuthorizer, error) {
func newPartialAuthorizer(ctx context.Context, subjectID string, roles []Role, scope Role, action Action, objectType string) (*PartialAuthorizer, error) {
ctx, span := tracing.StartSpan(ctx)
defer span.End()

input := map[string]interface{}{
"subject": authSubject{
ID: subjectID,
Roles: roles,
Scope: scope,
},
"object": map[string]string{
"type": objectType,
Expand All @@ -112,7 +113,7 @@ func newPartialAuthorizer(ctx context.Context, subjectID string, roles []Role, s
// Run the rego policy with a few unknown fields. This should simplify our
// policy to a set of queries.
partialQueries, err := rego.New(
rego.Query("data.authz.scope_allow = true"),
rego.Query("data.authz.role_allow = true data.authz.scope_allow = true"),
rego.Module("policy.rego", policy),
rego.Unknowns([]string{
"input.object.owner",
Expand Down
2 changes: 1 addition & 1 deletion coderd/rbac/policy.rego
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ number(set) = c {
default site = 0
site := site_allow(input.subject.roles)
default scope_site := 0
scope_site := site_allow([input.scope])
scope_site := site_allow([input.subject.scope])

site_allow(roles) := num {
# allow is a set of boolean values without duplicates.
Expand Down