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

Commit2bf3c3c

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 parentbbd9174 commit2bf3c3c

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
@@ -647,6 +647,7 @@ GEN_FILES := \
647647
coderd/rbac/object_gen.go\
648648
codersdk/rbacresources_gen.go\
649649
coderd/rbac/scopes_constants_gen.go\
650+
codersdk/apikey_scopes_gen.go\
650651
docs/admin/integrations/prometheus.md\
651652
docs/reference/cli/index.md\
652653
docs/admin/security/audit-logs.md\
@@ -860,6 +861,12 @@ codersdk/rbacresources_gen.go: scripts/typegen/codersdk.gotmpl scripts/typegen/m
860861
mv /tmp/rbacresources_gen.go codersdk/rbacresources_gen.go
861862
touch "$@"
862863

864+
codersdk/apikey_scopes_gen.go: scripts/apikeyscopesgen/main.go coderd/rbac/scopes_catalog.go coderd/rbac/scopes.go
865+
# Generate SDK constants for public low-level API key scopes.
866+
go run ./scripts/apikeyscopesgen> /tmp/apikey_scopes_gen.go
867+
mv /tmp/apikey_scopes_gen.go codersdk/apikey_scopes_gen.go
868+
touch"$@"
869+
863870
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
864871
go run scripts/typegen/main.go rbac typescript>"$@"
865872
(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