Skip to content

Commit f3ff52e

Browse files
committed
Add comments, implement workpace agent scope
1 parent a166d57 commit f3ff52e

File tree

6 files changed

+34
-3
lines changed

6 files changed

+34
-3
lines changed

coderd/gitsshkey.go

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import (
44
"net/http"
55

66
"github.com/coder/coder/coderd/audit"
7-
"github.com/coder/coder/coderd/authzquery"
87
"github.com/coder/coder/coderd/database"
98
"github.com/coder/coder/coderd/gitsshkey"
109
"github.com/coder/coder/coderd/httpapi"
@@ -127,7 +126,6 @@ func (api *API) gitSSHKey(rw http.ResponseWriter, r *http.Request) {
127126
func (api *API) agentGitSSHKey(rw http.ResponseWriter, r *http.Request) {
128127
ctx := r.Context()
129128
agent := httpmw.WorkspaceAgent(r)
130-
agentCtx := authzquery.WithWorkspaceAgentTokenContext(ctx, agent.ResourceID, agent.ID, rbac.RoleNames([]string{}), []string{})
131129
resource, err := api.Database.GetWorkspaceResourceByID(agentCtx, agent.ResourceID)
132130
if err != nil {
133131
httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{

coderd/httpmw/workspaceagent.go

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,11 +92,16 @@ func ExtractWorkspaceAgent(db database.Store) func(http.Handler) http.Handler {
9292
return
9393
}
9494

95+
// A user that creates a workspace can use this agent auth token and
96+
// impersonate the workspace. So to prevent privledge escalation, the
97+
// subject inherits the roles of the user that owns the workspace.
98+
// We then add a workspace-agent scope to limit the permissions
99+
// to only what the workspace agent needs.
95100
subject := rbac.Subject{
96101
ID: user.ID.String(),
97102
Roles: rbac.RoleNames(roles.Roles),
98103
Groups: roles.Groups,
99-
Scope: rbac.ScopeAll, // TODO: ScopeWorkspaceAgent
104+
Scope: rbac.WorkspaceAgentScope(workspace.ID),
100105
}
101106

102107
ctx = context.WithValue(ctx, workspaceAgentContextKey{}, agent)

coderd/rbac/scopes.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ package rbac
33
import (
44
"fmt"
55

6+
"github.com/google/uuid"
7+
68
"golang.org/x/xerrors"
79
)
810

@@ -41,6 +43,24 @@ func (s Scope) Name() string {
4143
return s.Role.Name
4244
}
4345

46+
func WorkspaceAgentScope(workspaceID uuid.UUID) Scope {
47+
allScope, err := ScopeAll.Expand()
48+
if err != nil {
49+
panic("failed to expand scope all, this should never happen")
50+
}
51+
return Scope{
52+
// TODO: We want to limit the role too to be extra safe.
53+
// Even though the allowlist blocks anything else, it is still good
54+
// incase we change the behavior of the allowlist. The allowlist is new
55+
// and evolving.
56+
Role: allScope.Role,
57+
// This prevents the agent from being able to access any other resource.
58+
AllowIDList: []string{
59+
workspaceID.String(),
60+
},
61+
}
62+
}
63+
4464
const (
4565
ScopeAll ScopeName = "all"
4666
ScopeApplicationConnect ScopeName = "application_connect"

coderd/templates.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,10 @@ func (api *API) deleteTemplate(rw http.ResponseWriter, r *http.Request) {
9999
return
100100
}
101101

102+
// TODO: This just returns the workspaces a user can view. We should use
103+
// a system function to get all workspaces that use this template.
104+
// This data should never be exposed to the user aside from a non-zero count.
105+
// Or we move this into a postgres constraint.
102106
workspaces, err := api.Database.GetWorkspaces(ctx, database.GetWorkspacesParams{
103107
TemplateIds: []uuid.UUID{template.ID},
104108
})

coderd/users.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ func (api *API) firstUser(rw http.ResponseWriter, r *http.Request) {
7272
// @Success 201 {object} codersdk.CreateFirstUserResponse
7373
// @Router /users/first [post]
7474
func (api *API) postFirstUser(rw http.ResponseWriter, r *http.Request) {
75+
// TODO: Should this admin system context be in a middleware?
7576
ctx := authzquery.WithAuthorizeSystemContext(r.Context(), rbac.RolesAdminSystem())
7677
var createUser codersdk.CreateFirstUserRequest
7778
if !httpapi.Read(ctx, rw, r, &createUser) {

coderd/workspaces.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -359,6 +359,9 @@ func (api *API) postWorkspacesByOrganization(rw http.ResponseWriter, r *http.Req
359359
return
360360
}
361361

362+
// TODO: This should be a system call as the actor might not be able to
363+
// read other workspaces. Ideally we check the error on create and look for
364+
// a postgres conflict error.
362365
workspace, err := api.Database.GetWorkspaceByOwnerIDAndName(ctx, database.GetWorkspaceByOwnerIDAndNameParams{
363366
OwnerID: user.ID,
364367
Name: createWorkspace.Name,

0 commit comments

Comments
 (0)