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

feat: Add template-admin + user-admin role for managing templates + users#3490

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 11 commits intomainfromstevenmasley/2135/roles
Aug 12, 2022
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
2 changes: 1 addition & 1 deletioncoderd/coderd.go
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -340,7 +340,7 @@ func New(options *Options) *API {
r.Get("/", api.workspaceAgent)
r.Post("/peer", api.postWorkspaceAgentWireguardPeer)
r.Get("/dial", api.workspaceAgentDial)
r.Get("/turn", api.workspaceAgentTurn)
r.Get("/turn", api.userWorkspaceAgentTurn)
r.Get("/pty", api.workspaceAgentPTY)
r.Get("/iceservers", api.workspaceAgentICEServers)
r.Get("/derp", api.derpMap)
Expand Down
14 changes: 9 additions & 5 deletionscoderd/coderd_test.go
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -220,6 +220,7 @@ func TestAuthorizeAllEndpoints(t *testing.T) {

// Some quick reused objects
workspaceRBACObj := rbac.ResourceWorkspace.InOrg(organization.ID).WithOwner(workspace.OwnerID.String())
workspaceExecObj := rbac.ResourceWorkspaceExecution.InOrg(organization.ID).WithOwner(workspace.OwnerID.String())

// skipRoutes allows skipping routes from being checked.
skipRoutes := map[string]string{
Expand DownExpand Up@@ -268,7 +269,6 @@ func TestAuthorizeAllEndpoints(t *testing.T) {
"GET:/api/v2/workspaceagents/me/wireguardlisten": {NoAuthorize: true},
"POST:/api/v2/workspaceagents/me/keys": {NoAuthorize: true},
"GET:/api/v2/workspaceagents/{workspaceagent}/iceservers": {NoAuthorize: true},
"GET:/api/v2/workspaceagents/{workspaceagent}/turn": {NoAuthorize: true},
"GET:/api/v2/workspaceagents/{workspaceagent}/derp": {NoAuthorize: true},

// These endpoints have more assertions. This is good, add more endpoints to assert if you can!
Expand DownExpand Up@@ -331,12 +331,16 @@ func TestAuthorizeAllEndpoints(t *testing.T) {
AssertObject: workspaceRBACObj,
},
"GET:/api/v2/workspaceagents/{workspaceagent}/dial": {
AssertAction: rbac.ActionUpdate,
AssertObject: workspaceRBACObj,
AssertAction: rbac.ActionCreate,
AssertObject: workspaceExecObj,
},
"GET:/api/v2/workspaceagents/{workspaceagent}/turn": {
AssertAction: rbac.ActionCreate,
AssertObject: workspaceExecObj,
},
"GET:/api/v2/workspaceagents/{workspaceagent}/pty": {
AssertAction: rbac.ActionUpdate,
AssertObject:workspaceRBACObj,
AssertAction: rbac.ActionCreate,
AssertObject:workspaceExecObj,
},
"GET:/api/v2/workspaces/": {
StatusCode: http.StatusOK,
Expand Down
4 changes: 4 additions & 0 deletionscoderd/database/modelmethods.go
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -17,6 +17,10 @@ func (w Workspace) RBACObject() rbac.Object {
return rbac.ResourceWorkspace.InOrg(w.OrganizationID).WithOwner(w.OwnerID.String())
}

func (w Workspace) ExecutionRBAC() rbac.Object {
return rbac.ResourceWorkspaceExecution.InOrg(w.OrganizationID).WithOwner(w.OwnerID.String())
}

func (m OrganizationMember) RBACObject() rbac.Object {
return rbac.ResourceOrganizationMember.InOrg(m.OrganizationID)
}
Expand Down
53 changes: 45 additions & 8 deletionscoderd/rbac/builtin.go
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -9,9 +9,11 @@ import (
)

const (
admin string = "admin"
member string = "member"
auditor string = "auditor"
admin string = "admin"
member string = "member"
templateAdmin string = "template-admin"
userAdmin string = "user-admin"
auditor string = "auditor"

orgAdmin string = "organization-admin"
orgMember string = "organization-member"
Expand All@@ -26,6 +28,14 @@ func RoleAdmin() string {
return roleName(admin, "")
}

func RoleTemplateAdmin() string {
return roleName(templateAdmin, "")
}

func RoleUserAdmin() string {
return roleName(userAdmin, "")
}

func RoleMember() string {
return roleName(member, "")
}
Expand DownExpand Up@@ -93,6 +103,31 @@ var (
}
},

templateAdmin: func(_ string) Role {
return Role{
Name: templateAdmin,
DisplayName: "Template Admin",
Site: permissions(map[Object][]Action{
ResourceTemplate: {ActionCreate, ActionRead, ActionUpdate, ActionDelete},
// CRUD all files, even those they did not upload.
ResourceFile: {ActionCreate, ActionRead, ActionUpdate, ActionDelete},
ResourceWorkspace: {ActionCreate, ActionRead, ActionUpdate, ActionDelete},
// CRUD to provisioner daemons for now.
ResourceProvisionerDaemon: {ActionCreate, ActionRead, ActionUpdate, ActionDelete},
}),
}
},

userAdmin: func(_ string) Role {
return Role{
Name: userAdmin,
DisplayName: "User Admin",
Site: permissions(map[Object][]Action{
ResourceUser: {ActionCreate, ActionRead, ActionUpdate, ActionDelete},
}),
}
},

// orgAdmin returns a role with all actions allows in a given
// organization scope.
orgAdmin: func(organizationID string) Role {
Expand DownExpand Up@@ -153,11 +188,13 @@ var (
//map[actor_role][assign_role]<can_assign>
assignRoles = map[string]map[string]bool{
admin: {
admin: true,
auditor: true,
member: true,
orgAdmin: true,
orgMember: true,
admin: true,
auditor: true,
member: true,
orgAdmin: true,
orgMember: true,
templateAdmin: true,
userAdmin: true,
},
orgAdmin: {
orgAdmin: true,
Expand Down
2 changes: 2 additions & 0 deletionscoderd/rbac/builtin_internal_test.go
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -18,6 +18,8 @@ func TestRoleByName(t *testing.T) {
}{
{Role: builtInRoles[admin]("")},
{Role: builtInRoles[member]("")},
{Role: builtInRoles[templateAdmin]("")},
{Role: builtInRoles[userAdmin]("")},
{Role: builtInRoles[auditor]("")},

{Role: builtInRoles[orgAdmin](uuid.New().String())},
Expand Down
68 changes: 43 additions & 25 deletionscoderd/rbac/builtin_test.go
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -111,6 +111,7 @@ func TestRolePermissions(t *testing.T) {
// currentUser is anything that references "me", "mine", or "my".
currentUser := uuid.New()
adminID := uuid.New()
templateAdminID := uuid.New()
orgID := uuid.New()
otherOrg := uuid.New()

Expand All@@ -124,9 +125,12 @@ func TestRolePermissions(t *testing.T) {
otherOrgMember := authSubject{Name: "org_member_other", UserID: uuid.NewString(), Roles: []string{rbac.RoleMember(), rbac.RoleOrgMember(otherOrg)}}
otherOrgAdmin := authSubject{Name: "org_admin_other", UserID: uuid.NewString(), Roles: []string{rbac.RoleMember(), rbac.RoleOrgMember(otherOrg), rbac.RoleOrgAdmin(otherOrg)}}

templateAdmin := authSubject{Name: "template-admin", UserID: templateAdminID.String(), Roles: []string{rbac.RoleMember(), rbac.RoleTemplateAdmin()}}
userAdmin := authSubject{Name: "user-admin", UserID: templateAdminID.String(), Roles: []string{rbac.RoleMember(), rbac.RoleUserAdmin()}}

// requiredSubjects are required to be asserted in each test case. This is
// to make sure one is not forgotten.
requiredSubjects := []authSubject{memberMe, admin, orgMemberMe, orgAdmin, otherOrgAdmin, otherOrgMember}
requiredSubjects := []authSubject{memberMe, admin, orgMemberMe, orgAdmin, otherOrgAdmin, otherOrgMember, templateAdmin, userAdmin}

testCases := []struct {
// Name the test case to better locate the failing test case.
Expand All@@ -146,7 +150,7 @@ func TestRolePermissions(t *testing.T) {
Actions: []rbac.Action{rbac.ActionRead},
Resource: rbac.ResourceUser,
AuthorizeMap: map[bool][]authSubject{
true: {admin, memberMe, orgMemberMe, orgAdmin, otherOrgMember, otherOrgAdmin},
true: {admin, memberMe, orgMemberMe, orgAdmin, otherOrgMember, otherOrgAdmin, templateAdmin, userAdmin},
false: {},
},
},
Expand All@@ -155,8 +159,8 @@ func TestRolePermissions(t *testing.T) {
Actions: []rbac.Action{rbac.ActionCreate, rbac.ActionUpdate, rbac.ActionDelete},
Resource: rbac.ResourceUser,
AuthorizeMap: map[bool][]authSubject{
true: {admin},
false: {memberMe, orgMemberMe, orgAdmin, otherOrgMember, otherOrgAdmin},
true: {admin, userAdmin},
false: {memberMe, orgMemberMe, orgAdmin, otherOrgMember, otherOrgAdmin, templateAdmin},
},
},
{
Expand All@@ -165,44 +169,54 @@ func TestRolePermissions(t *testing.T) {
Actions: []rbac.Action{rbac.ActionCreate, rbac.ActionRead, rbac.ActionUpdate, rbac.ActionDelete},
Resource: rbac.ResourceWorkspace.InOrg(orgID).WithOwner(currentUser.String()),
AuthorizeMap: map[bool][]authSubject{
true: {admin, orgMemberMe, orgAdmin},
false: {memberMe, otherOrgAdmin, otherOrgMember},
true: {admin, orgMemberMe, orgAdmin, templateAdmin},
false: {memberMe, otherOrgAdmin, otherOrgMember, userAdmin},
},
},
{
Name: "MyWorkspaceInOrgExecution",
// When creating the WithID won't be set, but it does not change the result.
Actions: []rbac.Action{rbac.ActionCreate, rbac.ActionRead, rbac.ActionUpdate, rbac.ActionDelete},
Resource: rbac.ResourceWorkspaceExecution.InOrg(orgID).WithOwner(currentUser.String()),
AuthorizeMap: map[bool][]authSubject{
true: {admin, orgAdmin, orgMemberMe},
false: {memberMe, otherOrgAdmin, otherOrgMember, templateAdmin, userAdmin},
Comment on lines +177 to +183
Copy link
MemberAuthor

Choose a reason for hiding this comment

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

Workspace execution can only be done byadmin,orgadmin and the owner of the workspace.

},
},
{
Name: "Templates",
Actions: []rbac.Action{rbac.ActionCreate, rbac.ActionUpdate, rbac.ActionDelete},
Resource: rbac.ResourceTemplate.InOrg(orgID),
AuthorizeMap: map[bool][]authSubject{
true: {admin, orgAdmin},
false: {memberMe, orgMemberMe, otherOrgAdmin, otherOrgMember},
true: {admin, orgAdmin, templateAdmin},
false: {memberMe, orgMemberMe, otherOrgAdmin, otherOrgMember, userAdmin},
},
},
{
Name: "ReadTemplates",
Actions: []rbac.Action{rbac.ActionRead},
Resource: rbac.ResourceTemplate.InOrg(orgID),
AuthorizeMap: map[bool][]authSubject{
true: {admin, orgMemberMe, orgAdmin},
false: {memberMe, otherOrgAdmin, otherOrgMember},
true: {admin, orgMemberMe, orgAdmin, templateAdmin},
false: {memberMe, otherOrgAdmin, otherOrgMember, userAdmin},
},
},
{
Name: "Files",
Actions: []rbac.Action{rbac.ActionCreate},
Resource: rbac.ResourceFile,
AuthorizeMap: map[bool][]authSubject{
true: {admin},
false: {orgMemberMe, orgAdmin, memberMe, otherOrgAdmin, otherOrgMember},
true: {admin, templateAdmin},
false: {orgMemberMe, orgAdmin, memberMe, otherOrgAdmin, otherOrgMember, userAdmin},
},
},
{
Name: "MyFile",
Actions: []rbac.Action{rbac.ActionRead, rbac.ActionUpdate, rbac.ActionDelete},
Resource: rbac.ResourceFile.WithOwner(currentUser.String()),
AuthorizeMap: map[bool][]authSubject{
true: {admin, memberMe, orgMemberMe},
false: {orgAdmin, otherOrgAdmin, otherOrgMember},
true: {admin, memberMe, orgMemberMe, templateAdmin},
false: {orgAdmin, otherOrgAdmin, otherOrgMember, userAdmin},
},
},
{
Expand All@@ -211,7 +225,7 @@ func TestRolePermissions(t *testing.T) {
Resource: rbac.ResourceOrganization,
AuthorizeMap: map[bool][]authSubject{
true: {admin},
false: {orgAdmin, otherOrgAdmin, otherOrgMember, memberMe, orgMemberMe},
false: {orgAdmin, otherOrgAdmin, otherOrgMember, memberMe, orgMemberMe, templateAdmin, userAdmin},
},
},
{
Expand All@@ -220,7 +234,7 @@ func TestRolePermissions(t *testing.T) {
Resource: rbac.ResourceOrganization.InOrg(orgID),
AuthorizeMap: map[bool][]authSubject{
true: {admin, orgAdmin},
false: {otherOrgAdmin, otherOrgMember, memberMe, orgMemberMe},
false: {otherOrgAdmin, otherOrgMember, memberMe, orgMemberMe, templateAdmin, userAdmin},
},
},
{
Expand All@@ -229,7 +243,7 @@ func TestRolePermissions(t *testing.T) {
Resource: rbac.ResourceOrganization.InOrg(orgID),
AuthorizeMap: map[bool][]authSubject{
true: {admin, orgAdmin, orgMemberMe},
false: {otherOrgAdmin, otherOrgMember, memberMe},
false: {otherOrgAdmin, otherOrgMember, memberMe, templateAdmin, userAdmin},
},
},
{
Expand All@@ -238,15 +252,15 @@ func TestRolePermissions(t *testing.T) {
Resource: rbac.ResourceRoleAssignment,
AuthorizeMap: map[bool][]authSubject{
true: {admin},
false: {orgAdmin, orgMemberMe, otherOrgAdmin, otherOrgMember, memberMe},
false: {orgAdmin, orgMemberMe, otherOrgAdmin, otherOrgMember, memberMe, templateAdmin, userAdmin},
},
},
{
Name: "ReadRoleAssignment",
Actions: []rbac.Action{rbac.ActionRead},
Resource: rbac.ResourceRoleAssignment,
AuthorizeMap: map[bool][]authSubject{
true: {admin, orgAdmin, orgMemberMe, otherOrgAdmin, otherOrgMember, memberMe},
true: {admin, orgAdmin, orgMemberMe, otherOrgAdmin, otherOrgMember, memberMe, templateAdmin, userAdmin},
false: {},
},
},
Expand All@@ -256,7 +270,7 @@ func TestRolePermissions(t *testing.T) {
Resource: rbac.ResourceOrgRoleAssignment.InOrg(orgID),
AuthorizeMap: map[bool][]authSubject{
true: {admin, orgAdmin},
false: {orgMemberMe, otherOrgAdmin, otherOrgMember, memberMe},
false: {orgMemberMe, otherOrgAdmin, otherOrgMember, memberMe, templateAdmin, userAdmin},
},
},
{
Expand All@@ -265,7 +279,7 @@ func TestRolePermissions(t *testing.T) {
Resource: rbac.ResourceOrgRoleAssignment.InOrg(orgID),
AuthorizeMap: map[bool][]authSubject{
true: {admin, orgAdmin, orgMemberMe},
false: {otherOrgAdmin, otherOrgMember, memberMe},
false: {otherOrgAdmin, otherOrgMember, memberMe, templateAdmin, userAdmin},
},
},
{
Expand All@@ -274,7 +288,7 @@ func TestRolePermissions(t *testing.T) {
Resource: rbac.ResourceAPIKey.WithOwner(currentUser.String()),
AuthorizeMap: map[bool][]authSubject{
true: {admin, orgMemberMe, memberMe},
false: {orgAdmin, otherOrgAdmin, otherOrgMember},
false: {orgAdmin, otherOrgAdmin, otherOrgMember, templateAdmin, userAdmin},
},
},
{
Expand All@@ -283,7 +297,7 @@ func TestRolePermissions(t *testing.T) {
Resource: rbac.ResourceUserData.WithOwner(currentUser.String()),
AuthorizeMap: map[bool][]authSubject{
true: {admin, orgMemberMe, memberMe},
false: {orgAdmin, otherOrgAdmin, otherOrgMember},
false: {orgAdmin, otherOrgAdmin, otherOrgMember, templateAdmin, userAdmin},
},
},
{
Expand All@@ -292,7 +306,7 @@ func TestRolePermissions(t *testing.T) {
Resource: rbac.ResourceOrganizationMember.InOrg(orgID),
AuthorizeMap: map[bool][]authSubject{
true: {admin, orgAdmin},
false: {orgMemberMe, memberMe, otherOrgAdmin, otherOrgMember},
false: {orgMemberMe, memberMe, otherOrgAdmin, otherOrgMember, templateAdmin, userAdmin},
},
},
{
Expand All@@ -301,7 +315,7 @@ func TestRolePermissions(t *testing.T) {
Resource: rbac.ResourceOrganizationMember.InOrg(orgID),
AuthorizeMap: map[bool][]authSubject{
true: {admin, orgAdmin, orgMemberMe},
false: {memberMe, otherOrgAdmin, otherOrgMember},
false: {memberMe, otherOrgAdmin, otherOrgMember, templateAdmin, userAdmin},
},
},
}
Expand DownExpand Up@@ -396,10 +410,14 @@ func TestListRoles(t *testing.T) {

// If this test is ever failing, just update the list to the roles
// expected from the builtin set.
// Always use constant strings, as if the names change, we need to write
// a SQL migration to change the name on the backend.
require.ElementsMatch(t, []string{
"admin",
"member",
"auditor",
"template-admin",
"user-admin",
},
siteRoleNames)

Expand Down
9 changes: 9 additions & 0 deletionscoderd/rbac/object.go
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -22,6 +22,15 @@ var (
Type: "workspace",
}

// ResourceWorkspaceExecution CRUD. Org + User owner
//create = workspace remote execution
// read = ?
//update = ?
// delete = ?
ResourceWorkspaceExecution = Object{
Type: "workspace_execution",
}

// ResourceAuditLog
// read = access audit log
ResourceAuditLog = Object{
Expand Down
Loading

[8]ページ先頭

©2009-2025 Movatter.jp