Skip to content

Commit 7a1ae15

Browse files
committed
Add RBAC tests
1 parent d3b9ab5 commit 7a1ae15

File tree

7 files changed

+27
-8
lines changed

7 files changed

+27
-8
lines changed

.vscode/settings.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@
8080
"weblinks",
8181
"webrtc",
8282
"workspaceagent",
83+
"workspaceapp",
8384
"workspaceapps",
8485
"wsconncache",
8586
"xerrors",

coderd/coderd.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -107,8 +107,8 @@ func New(options *Options) *API {
107107
// %40 is the encoded character of the @ symbol. VS Code Web does
108108
// not handle character encoding properly, so it's safe to assume
109109
// other applications might not as well.
110-
r.Route("/%40{user}/{workspaceagent}/apps/{application}", apps)
111-
r.Route("/@{user}/{workspaceagent}/apps/{application}", apps)
110+
r.Route("/%40{user}/{workspacename}/apps/{workspaceapp}", apps)
111+
r.Route("/@{user}/{workspacename}/apps/{workspaceapp}", apps)
112112

113113
r.Route("/api/v2", func(r chi.Router) {
114114
r.NotFound(func(rw http.ResponseWriter, r *http.Request) {

coderd/coderd_test.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,10 @@ func TestAuthorizeAllEndpoints(t *testing.T) {
8282
Agents: []*proto.Agent{{
8383
Id: "something",
8484
Auth: &proto.Agent_Token{},
85+
Apps: []*proto.App{{
86+
Name: "app",
87+
Url: "http://localhost:3000",
88+
}},
8589
}},
8690
}},
8791
},
@@ -128,6 +132,15 @@ func TestAuthorizeAllEndpoints(t *testing.T) {
128132
"GET:/api/v2/users/authmethods": {NoAuthorize: true},
129133
"POST:/api/v2/csp/reports": {NoAuthorize: true},
130134

135+
"GET:/%40{user}/{workspacename}/apps/{application}/*": {
136+
AssertAction: rbac.ActionRead,
137+
AssertObject: workspaceRBACObj,
138+
},
139+
"GET:/@{user}/{workspacename}/apps/{application}/*": {
140+
AssertAction: rbac.ActionRead,
141+
AssertObject: workspaceRBACObj,
142+
},
143+
131144
// Has it's own auth
132145
"GET:/api/v2/users/oauth2/github/callback": {NoAuthorize: true},
133146

@@ -374,6 +387,7 @@ func TestAuthorizeAllEndpoints(t *testing.T) {
374387
route = strings.ReplaceAll(route, "{template}", template.ID.String())
375388
route = strings.ReplaceAll(route, "{hash}", file.Hash)
376389
route = strings.ReplaceAll(route, "{workspaceresource}", workspaceResources[0].ID.String())
390+
route = strings.ReplaceAll(route, "{workspaceapp}", workspaceResources[0].Agents[0].Apps[0].Name)
377391
route = strings.ReplaceAll(route, "{templateversion}", version.ID.String())
378392
route = strings.ReplaceAll(route, "{templateversiondryrun}", templateVersionDryRun.ID.String())
379393
route = strings.ReplaceAll(route, "{templatename}", template.Name)

coderd/workspaceagents.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -403,7 +403,7 @@ func (api *API) workspaceAgentPTY(rw http.ResponseWriter, r *http.Request) {
403403
return
404404
}
405405
defer release()
406-
ptNetConn, err := agentConn.ReconnectingPTY(reconnect.String(), uint16(height), uint16(width), "")
406+
ptNetConn, err := agentConn.ReconnectingPTY(reconnect.String(), uint16(height), uint16(width), r.URL.Query().Get("command"))
407407
if err != nil {
408408
_ = conn.Close(websocket.StatusInternalError, httpapi.WebsocketCloseSprintf("dial: %s", err))
409409
return

coderd/workspaceagents_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -297,7 +297,7 @@ func TestWorkspaceAgentPTY(t *testing.T) {
297297
})
298298
resources := coderdtest.AwaitWorkspaceAgents(t, client, workspace.LatestBuild.ID)
299299

300-
conn, err := client.WorkspaceAgentReconnectingPTY(context.Background(), resources[0].Agents[0].ID, uuid.New(), 80, 80)
300+
conn, err := client.WorkspaceAgentReconnectingPTY(context.Background(), resources[0].Agents[0].ID, uuid.New(), 80, 80, "/bin/bash")
301301
require.NoError(t, err)
302302
defer conn.Close()
303303

coderd/workspaceapps.go

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import (
1515
"github.com/coder/coder/coderd/database"
1616
"github.com/coder/coder/coderd/httpapi"
1717
"github.com/coder/coder/coderd/httpmw"
18+
"github.com/coder/coder/coderd/rbac"
1819
"github.com/coder/coder/site"
1920
)
2021

@@ -23,7 +24,7 @@ import (
2324
func (api *API) workspaceAppsProxyPath(rw http.ResponseWriter, r *http.Request) {
2425
user := httpmw.UserParam(r)
2526
// This can be in the form of: "<workspace-name>.[workspace-agent]" or "<workspace-name>"
26-
workspaceWithAgent := chi.URLParam(r, "workspaceagent")
27+
workspaceWithAgent := chi.URLParam(r, "workspacename")
2728
workspaceParts := strings.Split(workspaceWithAgent, ".")
2829

2930
workspace, err := api.Database.GetWorkspaceByOwnerIDAndName(r.Context(), database.GetWorkspaceByOwnerIDAndNameParams{
@@ -42,6 +43,9 @@ func (api *API) workspaceAppsProxyPath(rw http.ResponseWriter, r *http.Request)
4243
})
4344
return
4445
}
46+
if !api.Authorize(rw, r, rbac.ActionRead, workspace) {
47+
return
48+
}
4549

4650
build, err := api.Database.GetLatestWorkspaceBuildByWorkspaceID(r.Context(), workspace.ID)
4751
if err != nil {
@@ -87,7 +91,7 @@ func (api *API) workspaceAppsProxyPath(rw http.ResponseWriter, r *http.Request)
8791

8892
app, err := api.Database.GetWorkspaceAppByAgentIDAndName(r.Context(), database.GetWorkspaceAppByAgentIDAndNameParams{
8993
AgentID: agent.ID,
90-
Name: chi.URLParam(r, "application"),
94+
Name: chi.URLParam(r, "workspaceapp"),
9195
})
9296
if errors.Is(err, sql.ErrNoRows) {
9397
httpapi.Write(rw, http.StatusNotFound, httpapi.Response{

codersdk/workspaceagents.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -341,8 +341,8 @@ func (c *Client) WorkspaceAgent(ctx context.Context, id uuid.UUID) (WorkspaceAge
341341
// WorkspaceAgentReconnectingPTY spawns a PTY that reconnects using the token provided.
342342
// It communicates using `agent.ReconnectingPTYRequest` marshaled as JSON.
343343
// Responses are PTY output that can be rendered.
344-
func (c *Client) WorkspaceAgentReconnectingPTY(ctx context.Context, agentID, reconnect uuid.UUID, height, width int) (net.Conn, error) {
345-
serverURL, err := c.URL.Parse(fmt.Sprintf("/api/v2/workspaceagents/%s/pty?reconnect=%s&height=%d&width=%d", agentID, reconnect, height, width))
344+
func (c *Client) WorkspaceAgentReconnectingPTY(ctx context.Context, agentID, reconnect uuid.UUID, height, width int, command string) (net.Conn, error) {
345+
serverURL, err := c.URL.Parse(fmt.Sprintf("/api/v2/workspaceagents/%s/pty?reconnect=%s&height=%d&width=%d&command=%s", agentID, reconnect, height, width, command))
346346
if err != nil {
347347
return nil, xerrors.Errorf("parse url: %w", err)
348348
}

0 commit comments

Comments
 (0)