Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
4 changes: 4 additions & 0 deletions cli/testdata/coder_server_--help.golden
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@ OPTIONS:
creating a token without specifying a duration, such as when
authenticating the CLI or an IDE plugin.

--disable-chat-sharing bool, $CODER_DISABLE_CHAT_SHARING
Disable chat sharing. Chat ACL checking is disabled and only owners
can access their chats.

--disable-owner-workspace-access bool, $CODER_DISABLE_OWNER_WORKSPACE_ACCESS
Remove the permission for the 'owner' role to have workspace execution
on all workspaces. This prevents the 'owner' from ssh, apps, and
Expand Down
4 changes: 4 additions & 0 deletions cli/testdata/server-config.yaml.golden
Original file line number Diff line number Diff line change
Expand Up @@ -530,6 +530,10 @@ disableOwnerWorkspaceAccess: false
# --disable-owner-workspace-access.
# (default: <unset>, type: bool)
disableWorkspaceSharing: false
# Disable chat sharing. Chat ACL checking is disabled and only owners can access
# their chats.
# (default: <unset>, type: bool)
disableChatSharing: false
# These options change the behavior of how clients interact with the Coder.
# Clients include the Coder CLI, Coder Desktop, IDE extensions, and the web UI.
client:
Expand Down
5 changes: 5 additions & 0 deletions coderd/apidoc/docs.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions coderd/apidoc/swagger.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 5 additions & 1 deletion coderd/coderd.go
Original file line number Diff line number Diff line change
Expand Up @@ -343,16 +343,20 @@ func New(options *Options) *API {
panic("developer error: options.PrometheusRegistry is nil and not running a unit test")
}

if options.DeploymentValues.DisableOwnerWorkspaceExec || options.DeploymentValues.DisableWorkspaceSharing {
if options.DeploymentValues.DisableOwnerWorkspaceExec || options.DeploymentValues.DisableWorkspaceSharing || options.DeploymentValues.DisableChatSharing {
rbac.ReloadBuiltinRoles(&rbac.RoleOptions{
NoOwnerWorkspaceExec: bool(options.DeploymentValues.DisableOwnerWorkspaceExec),
NoWorkspaceSharing: bool(options.DeploymentValues.DisableWorkspaceSharing),
NoChatSharing: bool(options.DeploymentValues.DisableChatSharing),
})
}

if options.DeploymentValues.DisableWorkspaceSharing {
rbac.SetWorkspaceACLDisabled(true)
}
if options.DeploymentValues.DisableChatSharing {
rbac.SetChatACLDisabled(true)
}

if options.PrometheusRegistry == nil {
options.PrometheusRegistry = prometheus.NewRegistry()
Expand Down
3 changes: 3 additions & 0 deletions coderd/database/check_constraint.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

74 changes: 71 additions & 3 deletions coderd/database/dbauthz/dbauthz.go
Original file line number Diff line number Diff line change
Expand Up @@ -2682,6 +2682,17 @@ func (q *querier) GetAuthorizationUserRoles(ctx context.Context, userID uuid.UUI
return q.db.GetAuthorizationUserRoles(ctx, userID)
}

func (q *querier) GetChatACLByID(ctx context.Context, id uuid.UUID) (database.GetChatACLByIDRow, error) {
chat, err := q.db.GetChatByID(ctx, id)
if err != nil {
return database.GetChatACLByIDRow{}, err
}
if err := q.authorizeContext(ctx, policy.ActionRead, chat); err != nil {
return database.GetChatACLByIDRow{}, err
}
return q.db.GetChatACLByID(ctx, id)
}

Comment thread
DanielleMaywood marked this conversation as resolved.
func (q *querier) GetChatAdvisorConfig(ctx context.Context) (string, error) {
// The advisor configuration is a deployment-wide setting read by any
// authenticated chat user and by chatd when deciding whether to attach
Expand Down Expand Up @@ -2884,25 +2895,56 @@ func (q *querier) GetChatFileByID(ctx context.Context, id uuid.UUID) (database.C
if err != nil {
return database.ChatFile{}, err
}
if err := q.authorizeContext(ctx, policy.ActionRead, file); err != nil {
fileAuthErr := q.authorizeContext(ctx, policy.ActionRead, file)
if fileAuthErr == nil {
return file, nil
}

prepared, err := prepareSQLFilter(ctx, q.auth, policy.ActionRead, rbac.ResourceChat.Type)
if err != nil {
return database.ChatFile{}, xerrors.Errorf("(dev error) prepare sql filter: %w", err)
}
chats, err := q.db.GetAuthorizedChatsByChatFileID(ctx, id, prepared)
if err != nil {
return database.ChatFile{}, err
}
if len(chats) == 0 {
return database.ChatFile{}, fileAuthErr
}
return file, nil
}

func (q *querier) GetChatFileMetadataByChatID(ctx context.Context, chatID uuid.UUID) ([]database.GetChatFileMetadataByChatIDRow, error) {
return fetchWithPostFilter(q.auth, policy.ActionRead, q.db.GetChatFileMetadataByChatID)(ctx, chatID)
if _, err := q.GetChatByID(ctx, chatID); err != nil {
return nil, err
}
return q.db.GetChatFileMetadataByChatID(ctx, chatID)
}

func (q *querier) GetChatFilesByIDs(ctx context.Context, ids []uuid.UUID) ([]database.ChatFile, error) {
Comment thread
DanielleMaywood marked this conversation as resolved.
files, err := q.db.GetChatFilesByIDs(ctx, ids)
if err != nil {
return nil, err
}
var prepared rbac.PreparedAuthorized
for _, f := range files {
Comment thread
DanielleMaywood marked this conversation as resolved.
if err := q.authorizeContext(ctx, policy.ActionRead, f); err != nil {
fileAuthErr := q.authorizeContext(ctx, policy.ActionRead, f)
if fileAuthErr == nil {
continue
}
if prepared == nil {
prepared, err = prepareSQLFilter(ctx, q.auth, policy.ActionRead, rbac.ResourceChat.Type)
if err != nil {
return nil, xerrors.Errorf("(dev error) prepare sql filter: %w", err)
}
}
chats, err := q.db.GetAuthorizedChatsByChatFileID(ctx, f.ID, prepared)
if err != nil {
return nil, err
}
if len(chats) == 0 {
return nil, fileAuthErr
}
}
return files, nil
}
Expand Down Expand Up @@ -3164,6 +3206,10 @@ func (q *querier) GetChats(ctx context.Context, arg database.GetChatsParams) ([]
return q.db.GetAuthorizedChats(ctx, arg, prep)
}

func (q *querier) GetChatsByChatFileID(ctx context.Context, fileID uuid.UUID) ([]database.Chat, error) {
return fetchWithPostFilter(q.auth, policy.ActionRead, q.db.GetChatsByChatFileID)(ctx, fileID)
}

func (q *querier) GetChatsByWorkspaceIDs(ctx context.Context, ids []uuid.UUID) ([]database.Chat, error) {
return fetchWithPostFilter(q.auth, policy.ActionRead, q.db.GetChatsByWorkspaceIDs)(ctx, ids)
}
Expand Down Expand Up @@ -6392,6 +6438,24 @@ func (q *querier) UpdateAPIKeyByID(ctx context.Context, arg database.UpdateAPIKe
return update(q.log, q.auth, fetch, q.db.UpdateAPIKeyByID)(ctx, arg)
Comment thread
DanielleMaywood marked this conversation as resolved.
}

func (q *querier) UpdateChatACLByID(ctx context.Context, arg database.UpdateChatACLByIDParams) error {
Comment thread
DanielleMaywood marked this conversation as resolved.
if rbac.ChatACLDisabled() {
return NotAuthorizedError{Err: xerrors.New("chat sharing is disabled")}
}
fetch := func(ctx context.Context, arg database.UpdateChatACLByIDParams) (database.Chat, error) {
chat, err := q.db.GetChatByID(ctx, arg.ID)
if err != nil {
return database.Chat{}, err
}
if chat.IsSubChat() {
return database.Chat{}, NotAuthorizedError{Err: xerrors.New("chat ACLs can only be updated on root chats")}
}
return chat, nil
}

return fetchAndExec(q.log, q.auth, policy.ActionShare, fetch, q.db.UpdateChatACLByID)(ctx, arg)
}

func (q *querier) UpdateChatBuildAgentBinding(ctx context.Context, arg database.UpdateChatBuildAgentBindingParams) (database.Chat, error) {
chat, err := q.db.GetChatByID(ctx, arg.ID)
if err != nil {
Expand Down Expand Up @@ -8323,3 +8387,7 @@ func (q *querier) ListAuthorizedAIBridgeSessionThreads(ctx context.Context, arg
func (q *querier) GetAuthorizedChats(ctx context.Context, arg database.GetChatsParams, _ rbac.PreparedAuthorized) ([]database.GetChatsRow, error) {
return q.GetChats(ctx, arg)
}

func (q *querier) GetAuthorizedChatsByChatFileID(ctx context.Context, fileID uuid.UUID, prepared rbac.PreparedAuthorized) ([]database.Chat, error) {
return q.db.GetAuthorizedChatsByChatFileID(ctx, fileID, prepared)
}
Loading
Loading