Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit45d6550

Browse files
committed
feat: add public API key scope endpoint
Add /auth/scopes endpoint returning curated list of public low-level API key scopes (resource:action format).This read-only endpoint requires no authentication and provides SDK constants for all public scopes.
1 parent4f84ffa commit45d6550

File tree

16 files changed

+623
-57
lines changed

16 files changed

+623
-57
lines changed

‎Makefile‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -651,6 +651,7 @@ GEN_FILES := \
651651
coderd/rbac/object_gen.go\
652652
codersdk/rbacresources_gen.go\
653653
coderd/rbac/scopes_constants_gen.go\
654+
codersdk/apikey_scopes_gen.go\
654655
docs/admin/integrations/prometheus.md\
655656
docs/reference/cli/index.md\
656657
docs/admin/security/audit-logs.md\
@@ -870,6 +871,12 @@ codersdk/rbacresources_gen.go: scripts/typegen/codersdk.gotmpl scripts/typegen/m
870871
mv /tmp/rbacresources_gen.go codersdk/rbacresources_gen.go
871872
touch "$@"
872873

874+
codersdk/apikey_scopes_gen.go: scripts/apikeyscopesgen/main.go coderd/rbac/scopes_catalog.go coderd/rbac/scopes.go
875+
# Generate SDK constants for public low-level API key scopes.
876+
go run ./scripts/apikeyscopesgen> /tmp/apikey_scopes_gen.go
877+
mv /tmp/apikey_scopes_gen.go codersdk/apikey_scopes_gen.go
878+
touch"$@"
879+
873880
site/src/api/rbacresourcesGenerated.ts: site/node_modules/.installed scripts/typegen/codersdk.gotmpl scripts/typegen/main.go coderd/rbac/object.go coderd/rbac/policy/policy.go
874881
go run scripts/typegen/main.go rbac typescript>"$@"
875882
(cd site/&& pnpmexec biome format --write src/api/rbacresourcesGenerated.ts)

‎coderd/apidoc/docs.go‎

Lines changed: 86 additions & 11 deletions
Some generated files are not rendered by default. Learn more aboutcustomizing how changed files appear on GitHub.

‎coderd/apidoc/swagger.json‎

Lines changed: 88 additions & 8 deletions
Some generated files are not rendered by default. Learn more aboutcustomizing how changed files appear on GitHub.

‎coderd/apikey.go‎

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -66,9 +66,19 @@ func (api *API) postToken(rw http.ResponseWriter, r *http.Request) {
6666
return
6767
}
6868

69-
scope:=database.APIKeyScopeAll
70-
ifscope!="" {
71-
scope=database.APIKeyScope(createToken.Scope)
69+
// Map and validate requested scope.
70+
// Accept special scopes (all, application_connect) and curated public low-level scopes.
71+
scopes:= database.APIKeyScopes{database.APIKeyScopeAll}
72+
ifcreateToken.Scope!="" {
73+
name:=string(createToken.Scope)
74+
if!rbac.IsExternalScope(rbac.ScopeName(name)) {
75+
httpapi.Write(ctx,rw,http.StatusBadRequest, codersdk.Response{
76+
Message:"Failed to create API key.",
77+
Detail:fmt.Sprintf("invalid API key scope: %q",name),
78+
})
79+
return
80+
}
81+
scopes= database.APIKeyScopes{database.APIKeyScope(name)}
7282
}
7383

7484
tokenName:=namesgenerator.GetRandomName(1)
@@ -81,7 +91,7 @@ func (api *API) postToken(rw http.ResponseWriter, r *http.Request) {
8191
UserID:user.ID,
8292
LoginType:database.LoginTypeToken,
8393
DefaultLifetime:api.DeploymentValues.Sessions.DefaultTokenDuration.Value(),
84-
Scope:scope,
94+
Scopes:scopes,
8595
TokenName:tokenName,
8696
}
8797

‎coderd/apikey/apikey.go‎

Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,16 @@ type CreateParams struct {
2525
// Optional.
2626
ExpiresAt time.Time
2727
LifetimeSecondsint64
28-
Scope database.APIKeyScope
29-
TokenNamestring
30-
RemoteAddrstring
28+
// Scope is legacy single-scope input kept for backward compatibility.
29+
//
30+
// Deprecated: Prefer Scopes for new code.
31+
Scope database.APIKeyScope
32+
// Scopes is the full list of scopes to attach to the key.
33+
// If empty and Scope is set, the generator will use [Scope].
34+
// If both are empty, the generator will default to [APIKeyScopeAll].
35+
Scopes database.APIKeyScopes
36+
TokenNamestring
37+
RemoteAddrstring
3138
}
3239

3340
// Generate generates an API key, returning the key as a string as well as the
@@ -62,14 +69,20 @@ func Generate(params CreateParams) (database.InsertAPIKeyParams, string, error)
6269

6370
bitlen:=len(ip)*8
6471

65-
scope:=database.APIKeyScopeAll
66-
ifparams.Scope!="" {
67-
scope=params.Scope
68-
}
69-
switchscope {
70-
casedatabase.APIKeyScopeAll,database.APIKeyScopeApplicationConnect:
72+
varscopes database.APIKeyScopes
73+
switch {
74+
caselen(params.Scopes)>0:
75+
scopes=params.Scopes
76+
caseparams.Scope!="":
77+
scopes= database.APIKeyScopes{params.Scope}
7178
default:
72-
return database.InsertAPIKeyParams{},"",xerrors.Errorf("invalid API key scope: %q",scope)
79+
scopes= database.APIKeyScopes{database.APIKeyScopeAll}
80+
}
81+
82+
for_,s:=rangescopes {
83+
if!s.Valid() {
84+
return database.InsertAPIKeyParams{},"",xerrors.Errorf("invalid API key scope: %q",s)
85+
}
7386
}
7487

7588
token:=fmt.Sprintf("%s-%s",keyID,keySecret)
@@ -92,7 +105,7 @@ func Generate(params CreateParams) (database.InsertAPIKeyParams, string, error)
92105
UpdatedAt:dbtime.Now(),
93106
HashedSecret:hashed[:],
94107
LoginType:params.LoginType,
95-
Scopes:database.APIKeyScopes{scope},
108+
Scopes:scopes,
96109
AllowList: database.AllowList{database.AllowListWildcard()},
97110
TokenName:params.TokenName,
98111
},token,nil
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
package coderd_test
2+
3+
import (
4+
"context"
5+
"testing"
6+
7+
"github.com/stretchr/testify/require"
8+
9+
"github.com/coder/coder/v2/coderd/coderdtest"
10+
"github.com/coder/coder/v2/codersdk"
11+
"github.com/coder/coder/v2/testutil"
12+
)
13+
14+
funcTestTokenCreation_ScopeValidation(t*testing.T) {
15+
t.Parallel()
16+
17+
cases:= []struct {
18+
namestring
19+
scope codersdk.APIKeyScope
20+
wantErrbool
21+
}{
22+
{name:"AllowsPublicLowLevelScope",scope:"workspace:read",wantErr:false},
23+
{name:"RejectsInternalOnlyScope",scope:"debug_info:read",wantErr:true},
24+
{name:"AllowsLegacyScopes",scope:"application_connect",wantErr:false},
25+
{name:"AllowsCanonicalSpecialScope",scope:"all",wantErr:false},
26+
}
27+
28+
for_,tc:=rangecases {
29+
t.Run(tc.name,func(t*testing.T) {
30+
t.Parallel()
31+
32+
client:=coderdtest.New(t,nil)
33+
_=coderdtest.CreateFirstUser(t,client)
34+
35+
ctx,cancel:=context.WithTimeout(t.Context(),testutil.WaitShort)
36+
defercancel()
37+
38+
resp,err:=client.CreateToken(ctx,codersdk.Me, codersdk.CreateTokenRequest{Scope:tc.scope})
39+
iftc.wantErr {
40+
require.Error(t,err)
41+
return
42+
}
43+
require.NoError(t,err)
44+
require.NotEmpty(t,resp.Key)
45+
})
46+
}
47+
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp