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

Commit6466375

Browse files
committed
feat: add curated public API key scope catalog
Add public low-level scope catalog to RBAC system with curated set ofuser-requestable scopes. Includes workspace, template, API key, file,personal user, and user secret scopes. Updates scope checkingdocumentation to reference new catalog location in rbac package.
1 parentf290472 commit6466375

File tree

5 files changed

+146
-2
lines changed

5 files changed

+146
-2
lines changed

‎coderd/rbac/scopes.go‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,11 @@ func parseLowLevelScope(name ScopeName) (resource string, action policy.Action,
205205
if!exists {
206206
return"","",false
207207
}
208+
209+
ifact==policy.WildcardSymbol {
210+
returnres,policy.WildcardSymbol,true
211+
}
212+
208213
if_,exists:=def.Actions[policy.Action(act)];!exists {
209214
return"","",false
210215
}

‎coderd/rbac/scopes_catalog.go‎

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
package rbac
2+
3+
import (
4+
"sort"
5+
"strings"
6+
)
7+
8+
// externalLowLevel is the curated set of low-level scope names exposed to users.
9+
// Any valid resource:action pair not in this set is considered internal-only
10+
// and must not be user-requestable.
11+
varexternalLowLevel=map[ScopeName]struct{}{
12+
// Workspaces
13+
"workspace:read": {},
14+
"workspace:create": {},
15+
"workspace:update": {},
16+
"workspace:delete": {},
17+
"workspace:ssh": {},
18+
"workspace:start": {},
19+
"workspace:stop": {},
20+
"workspace:application_connect": {},
21+
"workspace:*": {},
22+
23+
// Templates
24+
"template:read": {},
25+
"template:create": {},
26+
"template:update": {},
27+
"template:delete": {},
28+
"template:use": {},
29+
"template:*": {},
30+
31+
// API keys (self-management)
32+
"api_key:read": {},
33+
"api_key:create": {},
34+
"api_key:update": {},
35+
"api_key:delete": {},
36+
"api_key:*": {},
37+
38+
// Files
39+
"file:read": {},
40+
"file:create": {},
41+
"file:*": {},
42+
43+
// Users (personal profile only)
44+
"user:read_personal": {},
45+
"user:update_personal": {},
46+
47+
// User secrets
48+
"user_secret:read": {},
49+
"user_secret:create": {},
50+
"user_secret:update": {},
51+
"user_secret:delete": {},
52+
"user_secret:*": {},
53+
}
54+
55+
// IsExternalScope returns true if the scope is public, including the
56+
// `all` and `application_connect` special scopes and the curated
57+
// low-level resource:action scopes.
58+
funcIsExternalScope(nameScopeName)bool {
59+
switchname {
60+
caseScopeAll,ScopeApplicationConnect:
61+
returntrue
62+
}
63+
if_,ok:=externalLowLevel[name];ok {
64+
returntrue
65+
}
66+
67+
returnfalse
68+
}
69+
70+
// ExternalScopeNames returns a sorted list of all public scopes, which includes
71+
// the `all` and `application_connect` special scopes and the curated public
72+
// low-level names.
73+
funcExternalScopeNames() []string {
74+
names:=make([]string,0,len(externalLowLevel)+2)
75+
names=append(names,string(ScopeAll))
76+
names=append(names,string(ScopeApplicationConnect))
77+
78+
// curated low-level names, filtered for validity
79+
forname:=rangeexternalLowLevel {
80+
if_,_,ok:=parseLowLevelScope(name);ok {
81+
names=append(names,string(name))
82+
}
83+
}
84+
85+
sort.Slice(names,func(i,jint)bool {returnstrings.Compare(names[i],names[j])<0 })
86+
returnnames
87+
}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
package rbac
2+
3+
import (
4+
"sort"
5+
"testing"
6+
7+
"github.com/stretchr/testify/require"
8+
)
9+
10+
funcTestExternalScopeNames(t*testing.T) {
11+
t.Parallel()
12+
13+
names:=ExternalScopeNames()
14+
require.NotEmpty(t,names)
15+
16+
// Ensure sorted ascending
17+
sorted:=append([]string(nil),names...)
18+
sort.Strings(sorted)
19+
require.Equal(t,sorted,names)
20+
21+
// Ensure each entry parses and expands to site-only
22+
for_,name:=rangenames {
23+
// Skip `all` and `application_connect` since they do not
24+
// expand into a low level scope.
25+
// They are handled differently.
26+
ifname==string(ScopeAll)||name==string(ScopeApplicationConnect) {
27+
continue
28+
}
29+
30+
res,act,ok:=parseLowLevelScope(ScopeName(name))
31+
require.Truef(t,ok,"catalog entry should parse: %s",name)
32+
33+
s,err:=ScopeName(name).Expand()
34+
require.NoErrorf(t,err,"catalog entry should expand: %s",name)
35+
require.Len(t,s.Site,1)
36+
require.Equal(t,res,s.Site[0].ResourceType)
37+
require.Equal(t,act,s.Site[0].Action)
38+
require.Empty(t,s.Org)
39+
require.Empty(t,s.User)
40+
}
41+
}
42+
43+
funcTestIsExternalScope(t*testing.T) {
44+
t.Parallel()
45+
46+
require.True(t,IsExternalScope("workspace:read"))
47+
require.True(t,IsExternalScope("template:use"))
48+
require.True(t,IsExternalScope("workspace:*"))
49+
require.False(t,IsExternalScope("debug_info:read"))// internal-only
50+
require.False(t,IsExternalScope("unknown:read"))
51+
}

‎scripts/check-scopes/README.md‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,4 +40,5 @@ When the tool reports missing values:
4040
make -B gen/db&& make lint/check-scopes
4141
```
4242

43-
3. Decide whether each new scope is public (exposed in the catalog) or internal-only (handled by the catalog task).
43+
3. Decide whether each new scope is public (exposed in the catalog) or internal-only.
44+
- If public, add it to the curated map in`coderd/rbac/scopes_catalog.go` (`externalLowLevel`) so it appears in the public catalog and can be requested by users.

‎scripts/check-scopes/main.go‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ func main() {
5353
_,_=fmt.Fprintf(os.Stderr," ALTER TYPE api_key_scope ADD VALUE IF NOT EXISTS '%s';\n",m)
5454
}
5555
_,_=fmt.Fprintln(os.Stderr)
56-
_,_=fmt.Fprintln(os.Stderr,"Also decide if each new scope ispublic (exposed in thecatalog) or internal-only (catalog task).")
56+
_,_=fmt.Fprintln(os.Stderr,"Also decide if each new scope isexternal (exposed in the`externalLowLevel` in coderd/rbac/scopes_catalog.go) or internal-only.")
5757
os.Exit(1)
5858
}
5959

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp