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 typed database for custom permissions (breaks existing custom roles)#13457

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/custom_roles_dbtype
Jun 4, 2024
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
6 changes: 3 additions & 3 deletionscli/organizationroles.go
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -36,7 +36,7 @@ func (r *RootCmd) organizationRoles() *serpent.Command {
func (r *RootCmd) showOrganizationRoles() *serpent.Command {
formatter := cliui.NewOutputFormatter(
cliui.ChangeFormatterData(
cliui.TableFormat([]roleTableRow{}, []string{"name", "display_name", "site_permissions", "org_permissions", "user_permissions"}),
cliui.TableFormat([]roleTableRow{}, []string{"name", "display_name", "site_permissions", "organization_permissions", "user_permissions"}),
func(data any) (any, error) {
inputs, ok := data.([]codersdk.AssignableRoles)
if !ok {
Expand DownExpand Up@@ -103,7 +103,7 @@ func (r *RootCmd) showOrganizationRoles() *serpent.Command {
func (r *RootCmd) editOrganizationRole() *serpent.Command {
formatter := cliui.NewOutputFormatter(
cliui.ChangeFormatterData(
cliui.TableFormat([]roleTableRow{}, []string{"name", "display_name", "site_permissions", "org_permissions", "user_permissions"}),
cliui.TableFormat([]roleTableRow{}, []string{"name", "display_name", "site_permissions", "organization_permissions", "user_permissions"}),
func(data any) (any, error) {
typed, _ := data.(codersdk.Role)
return []roleTableRow{roleToTableView(typed)}, nil
Expand DownExpand Up@@ -391,6 +391,6 @@ type roleTableRow struct {
OrganizationID string `table:"organization_id"`
SitePermissions string ` table:"site_permissions"`
// map[<org_id>] -> Permissions
OrganizationPermissions string `table:"org_permissions"`
OrganizationPermissions string `table:"organization_permissions"`
UserPermissions string `table:"user_permissions"`
}
62 changes: 29 additions & 33 deletionscoderd/database/db2sdk/db2sdk.go
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -18,7 +18,6 @@ import (
"github.com/coder/coder/v2/coderd/database"
"github.com/coder/coder/v2/coderd/parameter"
"github.com/coder/coder/v2/coderd/rbac"
"github.com/coder/coder/v2/coderd/rbac/policy"
"github.com/coder/coder/v2/coderd/workspaceapps/appurl"
"github.com/coder/coder/v2/codersdk"
"github.com/coder/coder/v2/provisionersdk/proto"
Expand DownExpand Up@@ -526,54 +525,51 @@ func ProvisionerDaemon(dbDaemon database.ProvisionerDaemon) codersdk.Provisioner
return result
}

funcRole(role rbac.Role) codersdk.Role {
funcRBACRole(role rbac.Role) codersdk.Role {
roleName, orgIDStr, err := rbac.RoleSplit(role.Name)
if err != nil {
roleName = role.Name
}
orgPerms := role.Org[orgIDStr]

return codersdk.Role{
Name: roleName,
OrganizationID: orgIDStr,
DisplayName: role.DisplayName,
SitePermissions: List(role.Site, Permission),
// This is not perfect. If there are organization permissions in another
// organization, they will be omitted. This should not be allowed, so
// should never happen.
OrganizationPermissions: List(role.Org[orgIDStr], Permission),
UserPermissions: List(role.User, Permission),
Name: roleName,
OrganizationID: orgIDStr,
DisplayName: role.DisplayName,
SitePermissions: List(role.Site, RBACPermission),
OrganizationPermissions: List(orgPerms, RBACPermission),
UserPermissions: List(role.User, RBACPermission),
}
}

func Permission(permission rbac.Permission) codersdk.Permission {
return codersdk.Permission{
Negate: permission.Negate,
ResourceType: codersdk.RBACResource(permission.ResourceType),
Action: codersdk.RBACAction(permission.Action),
func Role(role database.CustomRole) codersdk.Role {
orgID := ""
if role.OrganizationID.UUID != uuid.Nil {
orgID = role.OrganizationID.UUID.String()
}
}

func RoleToRBAC(role codersdk.Role) rbac.Role {
orgPerms := map[string][]rbac.Permission{}
if role.OrganizationID != "" {
orgPerms = map[string][]rbac.Permission{
role.OrganizationID: List(role.OrganizationPermissions, PermissionToRBAC),
}
return codersdk.Role{
Name: role.Name,
OrganizationID: orgID,
DisplayName: role.DisplayName,
SitePermissions: List(role.SitePermissions, Permission),
OrganizationPermissions: List(role.OrgPermissions, Permission),
UserPermissions: List(role.UserPermissions, Permission),
}
}

return rbac.Role{
Name: rbac.RoleName(role.Name, role.OrganizationID),
DisplayName: role.DisplayName,
Site: List(role.SitePermissions, PermissionToRBAC),
Org: orgPerms,
User: List(role.UserPermissions, PermissionToRBAC),
func Permission(permission database.CustomRolePermission) codersdk.Permission {
return codersdk.Permission{
Negate: permission.Negate,
ResourceType: codersdk.RBACResource(permission.ResourceType),
Action: codersdk.RBACAction(permission.Action),
}
}

funcPermissionToRBAC(permissioncodersdk.Permission)rbac.Permission {
returnrbac.Permission{
funcRBACPermission(permissionrbac.Permission)codersdk.Permission {
returncodersdk.Permission{
Negate: permission.Negate,
ResourceType:string(permission.ResourceType),
Action:policy.Action(permission.Action),
ResourceType:codersdk.RBACResource(permission.ResourceType),
Action:codersdk.RBACAction(permission.Action),
}
}
145 changes: 72 additions & 73 deletionscoderd/database/dbauthz/customroles_test.go
View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
package dbauthz_test

import (
"encoding/json"
"testing"

"github.com/google/uuid"
Expand All@@ -11,10 +10,12 @@ import (
"cdr.dev/slog"
"github.com/coder/coder/v2/coderd/coderdtest"
"github.com/coder/coder/v2/coderd/database"
"github.com/coder/coder/v2/coderd/database/db2sdk"
"github.com/coder/coder/v2/coderd/database/dbauthz"
"github.com/coder/coder/v2/coderd/database/dbmem"
"github.com/coder/coder/v2/coderd/rbac"
"github.com/coder/coder/v2/coderd/rbac/policy"
"github.com/coder/coder/v2/codersdk"
"github.com/coder/coder/v2/testutil"
)

Expand DownExpand Up@@ -60,17 +61,21 @@ func TestUpsertCustomRoles(t *testing.T) {
return all
}

orgID := uuid.New()
orgID := uuid.NullUUID{
UUID: uuid.New(),
Valid: true,
}
testCases := []struct {
name string

subject rbac.ExpandableRoles

// Perms to create on new custom role
site []rbac.Permission
org map[string][]rbac.Permission
user []rbac.Permission
errorContains string
organizationID uuid.NullUUID
site []codersdk.Permission
org []codersdk.Permission
user []codersdk.Permission
errorContains string
}{
{
// No roles, so no assign role
Expand All@@ -84,144 +89,129 @@ func TestUpsertCustomRoles(t *testing.T) {
subject: merge(canAssignRole),
},
{
name: "mixed-scopes",
subject: merge(canAssignRole, rbac.RoleOwner()),
site: rbac.Permissions(map[string][]policy.Action{
rbac.ResourceWorkspace.Type: {policy.ActionRead},
name: "mixed-scopes",
subject: merge(canAssignRole, rbac.RoleOwner()),
organizationID: orgID,
site: codersdk.CreatePermissions(map[codersdk.RBACResource][]codersdk.RBACAction{
codersdk.ResourceWorkspace: {codersdk.ActionRead},
}),
org: codersdk.CreatePermissions(map[codersdk.RBACResource][]codersdk.RBACAction{
codersdk.ResourceWorkspace: {codersdk.ActionRead},
}),
org: map[string][]rbac.Permission{
uuid.New().String(): rbac.Permissions(map[string][]policy.Action{
rbac.ResourceWorkspace.Type: {policy.ActionRead},
}),
},
errorContains: "cannot assign both org and site permissions",
},
{
name: "multiple-org",
subject: merge(canAssignRole, rbac.RoleOwner()),
org: map[string][]rbac.Permission{
uuid.New().String(): rbac.Permissions(map[string][]policy.Action{
rbac.ResourceWorkspace.Type: {policy.ActionRead},
}),
uuid.New().String(): rbac.Permissions(map[string][]policy.Action{
rbac.ResourceWorkspace.Type: {policy.ActionRead},
}),
},
errorContains: "cannot assign permissions to more than 1",
},
{
name: "invalid-action",
subject: merge(canAssignRole, rbac.RoleOwner()),
site:rbac.Permissions(map[string][]policy.Action{
site:codersdk.CreatePermissions(map[codersdk.RBACResource][]codersdk.RBACAction{
// Action does not go with resource
rbac.ResourceWorkspace.Type: {policy.ActionViewInsights},
codersdk.ResourceWorkspace: {codersdk.ActionViewInsights},
}),
errorContains: "invalid action",
},
{
name: "invalid-resource",
subject: merge(canAssignRole, rbac.RoleOwner()),
site:rbac.Permissions(map[string][]policy.Action{
"foobar": {policy.ActionViewInsights},
site:codersdk.CreatePermissions(map[codersdk.RBACResource][]codersdk.RBACAction{
"foobar": {codersdk.ActionViewInsights},
}),
errorContains: "invalid resource",
},
{
// Not allowing these at this time.
name: "negative-permission",
subject: merge(canAssignRole, rbac.RoleOwner()),
site: []rbac.Permission{
site: []codersdk.Permission{
{
Negate: true,
ResourceType:rbac.ResourceWorkspace.Type,
Action:policy.ActionRead,
ResourceType:codersdk.ResourceWorkspace,
Action:codersdk.ActionRead,
},
},
errorContains: "no negative permissions",
},
{
name: "wildcard", // not allowed
subject: merge(canAssignRole, rbac.RoleOwner()),
site:rbac.Permissions(map[string][]policy.Action{
rbac.ResourceWorkspace.Type: {policy.WildcardSymbol},
site:codersdk.CreatePermissions(map[codersdk.RBACResource][]codersdk.RBACAction{
codersdk.ResourceWorkspace: {"*"},
}),
errorContains: "no wildcard symbols",
},
// escalation checks
{
name: "read-workspace-escalation",
subject: merge(canAssignRole),
site:rbac.Permissions(map[string][]policy.Action{
rbac.ResourceWorkspace.Type: {policy.ActionRead},
site:codersdk.CreatePermissions(map[codersdk.RBACResource][]codersdk.RBACAction{
codersdk.ResourceWorkspace: {codersdk.ActionRead},
}),
errorContains: "not allowed to grant this permission",
},
{
name: "read-workspace-outside-org",
subject: merge(canAssignRole, rbac.RoleOrgAdmin(orgID)),
org: map[string][]rbac.Permission{
// The org admin is for a different org
uuid.NewString(): rbac.Permissions(map[string][]policy.Action{
rbac.ResourceWorkspace.Type: {policy.ActionRead},
}),
name: "read-workspace-outside-org",
organizationID: uuid.NullUUID{
UUID: uuid.New(),
Valid: true,
},
subject: merge(canAssignRole, rbac.RoleOrgAdmin(orgID.UUID)),
org: codersdk.CreatePermissions(map[codersdk.RBACResource][]codersdk.RBACAction{
codersdk.ResourceWorkspace: {codersdk.ActionRead},
}),
errorContains: "not allowed to grant this permission",
},
{
name: "user-escalation",
// These roles do not grant user perms
subject: merge(canAssignRole, rbac.RoleOrgAdmin(orgID)),
user:rbac.Permissions(map[string][]policy.Action{
rbac.ResourceWorkspace.Type: {policy.ActionRead},
subject: merge(canAssignRole, rbac.RoleOrgAdmin(orgID.UUID)),
user:codersdk.CreatePermissions(map[codersdk.RBACResource][]codersdk.RBACAction{
codersdk.ResourceWorkspace: {codersdk.ActionRead},
}),
errorContains: "not allowed to grant this permission",
},
{
name: "template-admin-escalation",
subject: merge(canAssignRole, rbac.RoleTemplateAdmin()),
site:rbac.Permissions(map[string][]policy.Action{
rbac.ResourceWorkspace.Type: {policy.ActionRead}, // ok!
rbac.ResourceDeploymentConfig.Type: {policy.ActionUpdate}, // not ok!
site:codersdk.CreatePermissions(map[codersdk.RBACResource][]codersdk.RBACAction{
codersdk.ResourceWorkspace: {codersdk.ActionRead}, // ok!
codersdk.ResourceDeploymentConfig: {codersdk.ActionUpdate}, // not ok!
}),
user:rbac.Permissions(map[string][]policy.Action{
rbac.ResourceWorkspace.Type: {policy.ActionRead}, // ok!
user:codersdk.CreatePermissions(map[codersdk.RBACResource][]codersdk.RBACAction{
codersdk.ResourceWorkspace: {codersdk.ActionRead}, // ok!
}),
errorContains: "deployment_config",
},
// ok!
{
name: "read-workspace-template-admin",
subject: merge(canAssignRole, rbac.RoleTemplateAdmin()),
site:rbac.Permissions(map[string][]policy.Action{
rbac.ResourceWorkspace.Type: {policy.ActionRead},
site:codersdk.CreatePermissions(map[codersdk.RBACResource][]codersdk.RBACAction{
codersdk.ResourceWorkspace: {codersdk.ActionRead},
}),
},
{
name: "read-workspace-in-org",
subject: merge(canAssignRole, rbac.RoleOrgAdmin(orgID)),
org: map[string][]rbac.Permission{
// Org admin of this org, this is ok!
orgID.String(): rbac.Permissions(map[string][]policy.Action{
rbac.ResourceWorkspace.Type: {policy.ActionRead},
}),
},
name: "read-workspace-in-org",
subject: merge(canAssignRole, rbac.RoleOrgAdmin(orgID.UUID)),
organizationID: orgID,
org: codersdk.CreatePermissions(map[codersdk.RBACResource][]codersdk.RBACAction{
codersdk.ResourceWorkspace: {codersdk.ActionRead},
}),
},
{
name: "user-perms",
// This is weird, but is ok
subject: merge(canAssignRole, rbac.RoleMember()),
user:rbac.Permissions(map[string][]policy.Action{
rbac.ResourceWorkspace.Type: {policy.ActionRead},
user:codersdk.CreatePermissions(map[codersdk.RBACResource][]codersdk.RBACAction{
codersdk.ResourceWorkspace: {codersdk.ActionRead},
}),
},
{
name: "site+user-perms",
subject: merge(canAssignRole, rbac.RoleMember(), rbac.RoleTemplateAdmin()),
site:rbac.Permissions(map[string][]policy.Action{
rbac.ResourceWorkspace.Type: {policy.ActionRead},
site:codersdk.CreatePermissions(map[codersdk.RBACResource][]codersdk.RBACAction{
codersdk.ResourceWorkspace: {codersdk.ActionRead},
}),
user:rbac.Permissions(map[string][]policy.Action{
rbac.ResourceWorkspace.Type: {policy.ActionRead},
user:codersdk.CreatePermissions(map[codersdk.RBACResource][]codersdk.RBACAction{
codersdk.ResourceWorkspace: {codersdk.ActionRead},
}),
},
}
Expand All@@ -244,9 +234,10 @@ func TestUpsertCustomRoles(t *testing.T) {
_, err := az.UpsertCustomRole(ctx, database.UpsertCustomRoleParams{
Name: "test-role",
DisplayName: "",
SitePermissions: must(json.Marshal(tc.site)),
OrgPermissions: must(json.Marshal(tc.org)),
UserPermissions: must(json.Marshal(tc.user)),
OrganizationID: tc.organizationID,
SitePermissions: db2sdk.List(tc.site, convertSDKPerm),
OrgPermissions: db2sdk.List(tc.org, convertSDKPerm),
UserPermissions: db2sdk.List(tc.user, convertSDKPerm),
})
if tc.errorContains != "" {
require.ErrorContains(t, err, tc.errorContains)
Expand All@@ -256,3 +247,11 @@ func TestUpsertCustomRoles(t *testing.T) {
})
}
}

func convertSDKPerm(perm codersdk.Permission) database.CustomRolePermission {
return database.CustomRolePermission{
Negate: perm.Negate,
ResourceType: string(perm.ResourceType),
Action: policy.Action(perm.Action),
}
}
Loading
Loading

[8]ページ先頭

©2009-2025 Movatter.jp