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

Skip to content
Closed
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
39 changes: 32 additions & 7 deletions coderd/apidoc/docs.go

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

35 changes: 28 additions & 7 deletions coderd/apidoc/swagger.json

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

1 change: 1 addition & 0 deletions coderd/coderd.go
Original file line number Diff line number Diff line change
Expand Up @@ -1575,6 +1575,7 @@ func New(options *Options) *API {
).Get("/connection", api.workspaceAgentConnectionGeneric)
r.Route("/me", func(r chi.Router) {
r.Use(workspaceAgentInfo)
r.Get("/", api.workspaceAgentMe)
r.Group(func(r chi.Router) {
r.Use(
// Override the request_type for agent rpc traffic.
Expand Down
36 changes: 35 additions & 1 deletion coderd/workspaceagents.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,9 +60,43 @@ import (
// @Success 200 {object} codersdk.WorkspaceAgent
// @Router /workspaceagents/{workspaceagent} [get]
func (api *API) workspaceAgent(rw http.ResponseWriter, r *http.Request) {
waws := httpmw.WorkspaceAgentAndWorkspaceParam(r)
api.writeWorkspaceAgentResponse(rw, r, waws)
}

// @Summary Get authenticated workspace agent
// @ID get-authenticated-workspace-agent
// @Security CoderSessionToken
// @Produce json
// @Tags Agents
// @Success 200 {object} codersdk.WorkspaceAgent
// @Router /workspaceagents/me [get]
func (api *API) workspaceAgentMe(rw http.ResponseWriter, r *http.Request) {
ctx := r.Context()
agent := httpmw.WorkspaceAgent(r)

// The /me middleware only provides the agent and build, but the
// response also needs the workspace and owner username. Fetch them
// using the authenticated agent's ID.
//nolint:gocritic // The agent RBAC scope may not cover this cross-table query.
waws, err := api.Database.GetWorkspaceAgentAndWorkspaceByID(dbauthz.AsSystemRestricted(ctx), agent.ID)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

We should not escalate permissions. If the agent cannot fetch this metadata, then the api should fail.

Suggested change
waws, err := api.Database.GetWorkspaceAgentAndWorkspaceByID(dbauthz.AsSystemRestricted(ctx), agent.ID)
waws, err := api.Database.GetWorkspaceAgentAndWorkspaceByID(ctx, agent.ID)

Under normal conditions, the agent can fetch this data.

if err != nil {
httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error fetching workspace agent.",
Detail: err.Error(),
})
return
}

api.writeWorkspaceAgentResponse(rw, r, waws)
}

// writeWorkspaceAgentResponse fetches apps, scripts, log sources, and
// statuses for the given agent and writes a codersdk.WorkspaceAgent
// JSON response.
func (api *API) writeWorkspaceAgentResponse(rw http.ResponseWriter, r *http.Request, waws database.GetWorkspaceAgentAndWorkspaceByIDRow) {
var (
ctx = r.Context()
waws = httpmw.WorkspaceAgentAndWorkspaceParam(r)
dbApps []database.WorkspaceApp
scripts []database.WorkspaceAgentScript
logSources []database.WorkspaceAgentLogSource
Expand Down
23 changes: 23 additions & 0 deletions coderd/workspaceagents_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,29 @@ func TestWorkspaceAgent(t *testing.T) {
require.NoError(t, err)
require.True(t, workspace.LatestBuild.Resources[0].Agents[0].Health.Healthy)
})
t.Run("Me", func(t *testing.T) {
t.Parallel()
client, db := coderdtest.NewWithDatabase(t, nil)
user := coderdtest.CreateFirstUser(t, client)
tmpDir := t.TempDir()

r := dbfake.WorkspaceBuild(t, db, database.WorkspaceTable{
OrganizationID: user.OrganizationID,
OwnerID: user.UserID,
}).WithAgent(func(agents []*proto.Agent) []*proto.Agent {
agents[0].Directory = tmpDir
return agents
}).Do()

ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong)
defer cancel()

agentClient := agentsdk.New(client.URL, agentsdk.WithFixedToken(r.AgentToken))
me, err := agentClient.Me(ctx)
require.NoError(t, err)
require.Equal(t, r.Agents[0].ID, me.ID)
require.Equal(t, tmpDir, me.Directory)
})
t.Run("HasFallbackTroubleshootingURL", func(t *testing.T) {
t.Parallel()
client, db := coderdtest.NewWithDatabase(t, nil)
Expand Down
17 changes: 17 additions & 0 deletions codersdk/agentsdk/agentsdk.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,23 @@ type Client struct {
SDK *codersdk.Client
}

// Me returns the workspace agent metadata for the agent authenticated
// by the session token.
func (c *Client) Me(ctx context.Context) (codersdk.WorkspaceAgent, error) {
res, err := c.SDK.Request(ctx, http.MethodGet, "/api/v2/workspaceagents/me", nil)
if err != nil {
return codersdk.WorkspaceAgent{}, xerrors.Errorf("execute request: %w", err)
}
defer res.Body.Close()

if res.StatusCode != http.StatusOK {
return codersdk.WorkspaceAgent{}, codersdk.ReadBodyAsError(res)
}

var agent codersdk.WorkspaceAgent
return agent, json.NewDecoder(res.Body).Decode(&agent)
}

type GitSSHKey struct {
PublicKey string `json:"public_key"`
PrivateKey string `json:"private_key"`
Expand Down
Loading
Loading