Skip to content

Commit fa4810b

Browse files
committed
feat: add API key scope for workspace agents to support running without user data access
Change-Id: Ia5a7085afea6ad6ab7fdba2ab738357f4c519966 Signed-off-by: Thomas Kosiewski <tk@coder.com>
1 parent 5ffda26 commit fa4810b

File tree

19 files changed

+699
-400
lines changed

19 files changed

+699
-400
lines changed

coderd/coderd.go

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -800,6 +800,17 @@ func New(options *Options) *API {
800800
PostAuthAdditionalHeadersFunc: options.PostAuthAdditionalHeadersFunc,
801801
})
802802

803+
workspaceAgentInfo := httpmw.ExtractWorkspaceAgentAndLatestBuild(httpmw.ExtractWorkspaceAgentAndLatestBuildConfig{
804+
DB: options.Database,
805+
Optional: false,
806+
})
807+
// Same as above but optional
808+
workspaceAgentInfoOptional := httpmw.ExtractWorkspaceAgentAndLatestBuild(httpmw.ExtractWorkspaceAgentAndLatestBuildConfig{
809+
DB: options.Database,
810+
Optional: true,
811+
})
812+
workspaceAgentAPIKeyScopeCheck := httpmw.AgentAPIKeyScopeCheckMW()
813+
803814
// API rate limit middleware. The counter is local and not shared between
804815
// replicas or instances of this middleware.
805816
apiRateLimiter := httpmw.RateLimit(options.APIRateLimit, time.Minute)
@@ -1019,6 +1030,8 @@ func New(options *Options) *API {
10191030
r.Route("/external-auth", func(r chi.Router) {
10201031
r.Use(
10211032
apiKeyMiddleware,
1033+
workspaceAgentInfoOptional,
1034+
workspaceAgentAPIKeyScopeCheck,
10221035
)
10231036
// Get without a specific external auth ID will return all external auths.
10241037
r.Get("/", api.listUserExternalAuths)
@@ -1254,8 +1267,14 @@ func New(options *Options) *API {
12541267
r.Get("/", api.workspaceByOwnerAndName)
12551268
r.Get("/builds/{buildnumber}", api.workspaceBuildByBuildNumber)
12561269
})
1257-
r.Get("/gitsshkey", api.gitSSHKey)
1258-
r.Put("/gitsshkey", api.regenerateGitSSHKey)
1270+
r.With(
1271+
workspaceAgentInfoOptional,
1272+
workspaceAgentAPIKeyScopeCheck,
1273+
).Get("/gitsshkey", api.gitSSHKey)
1274+
r.With(
1275+
workspaceAgentInfoOptional,
1276+
workspaceAgentAPIKeyScopeCheck,
1277+
).Put("/gitsshkey", api.regenerateGitSSHKey)
12591278
r.Route("/notifications", func(r chi.Router) {
12601279
r.Route("/preferences", func(r chi.Router) {
12611280
r.Get("/", api.userNotificationPreferences)
@@ -1284,15 +1303,13 @@ func New(options *Options) *API {
12841303
httpmw.RequireAPIKeyOrWorkspaceProxyAuth(),
12851304
).Get("/connection", api.workspaceAgentConnectionGeneric)
12861305
r.Route("/me", func(r chi.Router) {
1287-
r.Use(httpmw.ExtractWorkspaceAgentAndLatestBuild(httpmw.ExtractWorkspaceAgentAndLatestBuildConfig{
1288-
DB: options.Database,
1289-
Optional: false,
1290-
}))
1306+
r.Use(workspaceAgentInfo)
12911307
r.Get("/rpc", api.workspaceAgentRPC)
12921308
r.Patch("/logs", api.patchWorkspaceAgentLogs)
12931309
r.Patch("/app-status", api.patchWorkspaceAgentAppStatus)
12941310
// Deprecated: Required to support legacy agents
1295-
r.Get("/gitauth", api.workspaceAgentsGitAuth)
1311+
r.With(workspaceAgentAPIKeyScopeCheck).
1312+
Get("/gitauth", api.workspaceAgentsGitAuth)
12961313
r.Get("/external-auth", api.workspaceAgentsExternalAuth)
12971314
r.Get("/gitsshkey", api.agentGitSSHKey)
12981315
r.Post("/log-source", api.workspaceAgentPostLogSource)

coderd/database/dbgen/dbgen.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,7 @@ func WorkspaceAgent(t testing.TB, db database.Store, orig database.WorkspaceAgen
210210
MOTDFile: takeFirst(orig.TroubleshootingURL, ""),
211211
DisplayApps: append([]database.DisplayApp{}, orig.DisplayApps...),
212212
DisplayOrder: takeFirst(orig.DisplayOrder, 1),
213+
APIKeyScope: takeFirst(orig.APIKeyScope, database.ApiKeyScopeEnumDefault),
213214
})
214215
require.NoError(t, err, "insert workspace agent")
215216
return agt

coderd/database/dbmem/dbmem.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9587,6 +9587,7 @@ func (q *FakeQuerier) InsertWorkspaceAgent(_ context.Context, arg database.Inser
95879587
LifecycleState: database.WorkspaceAgentLifecycleStateCreated,
95889588
DisplayApps: arg.DisplayApps,
95899589
DisplayOrder: arg.DisplayOrder,
9590+
APIKeyScope: arg.APIKeyScope,
95909591
}
95919592

95929593
q.workspaceAgents = append(q.workspaceAgents, agent)

coderd/database/dump.sql

Lines changed: 8 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
-- Remove the api_key_scope column from the workspace_agents table
2+
ALTER TABLE workspace_agents
3+
DROP COLUMN IF EXISTS api_key_scope;
4+
5+
-- Drop the enum type for API key scope
6+
DROP TYPE IF EXISTS api_key_scope_enum;
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
-- Create the enum type for API key scope
2+
CREATE TYPE api_key_scope_enum AS ENUM ('default', 'no_user_data');
3+
4+
-- Add the api_key_scope column to the workspace_agents table
5+
-- It defaults to 'default' to maintain existing behavior for current agents.
6+
ALTER TABLE workspace_agents
7+
ADD COLUMN api_key_scope api_key_scope_enum NOT NULL DEFAULT 'default';
8+
9+
-- Add a comment explaining the purpose of the column
10+
COMMENT ON COLUMN workspace_agents.api_key_scope IS 'Defines the scope of the API key associated with the agent. ''default'' allows access to everything, ''no_user_data'' restricts it to exclude user data.';

coderd/database/models.go

Lines changed: 60 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy