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

feat: add public RBAC scope catalog for user-requestable permissions#19913

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Merged
ThomasK33 merged 1 commit intomainfromthomask33/09-22-add_curated_scope_catalog
Sep 26, 2025
Merged
Show file tree
Hide file tree
Changes fromall 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
5 changes: 5 additions & 0 deletionscoderd/rbac/scopes.go
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -205,6 +205,11 @@ func parseLowLevelScope(name ScopeName) (resource string, action policy.Action,
if!exists {
return"","",false
}

ifact==policy.WildcardSymbol {
returnres,policy.WildcardSymbol,true
}

if_,exists:=def.Actions[policy.Action(act)];!exists {
return"","",false
}
Expand Down
87 changes: 87 additions & 0 deletionscoderd/rbac/scopes_catalog.go
View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
package rbac

import (
"sort"
"strings"
)

// externalLowLevel is the curated set of low-level scope names exposed to users.
// Any valid resource:action pair not in this set is considered internal-only
// and must not be user-requestable.
varexternalLowLevel=map[ScopeName]struct{}{
// Workspaces
"workspace:read": {},
"workspace:create": {},
"workspace:update": {},
"workspace:delete": {},
"workspace:ssh": {},
"workspace:start": {},
"workspace:stop": {},
"workspace:application_connect": {},
"workspace:*": {},

// Templates
"template:read": {},
"template:create": {},
"template:update": {},
"template:delete": {},
"template:use": {},
"template:*": {},

// API keys (self-management)
"api_key:read": {},
"api_key:create": {},
"api_key:update": {},
"api_key:delete": {},
"api_key:*": {},

// Files
"file:read": {},
"file:create": {},
"file:*": {},

// Users (personal profile only)
"user:read_personal": {},
"user:update_personal": {},

// User secrets
"user_secret:read": {},
"user_secret:create": {},
"user_secret:update": {},
"user_secret:delete": {},
"user_secret:*": {},
}

// IsExternalScope returns true if the scope is public, including the
// `all` and `application_connect` special scopes and the curated
// low-level resource:action scopes.
funcIsExternalScope(nameScopeName)bool {
switchname {
caseScopeAll,ScopeApplicationConnect:
returntrue
}
if_,ok:=externalLowLevel[name];ok {
returntrue
}

returnfalse
}

// ExternalScopeNames returns a sorted list of all public scopes, which includes
// the `all` and `application_connect` special scopes and the curated public
// low-level names.
funcExternalScopeNames() []string {
names:=make([]string,0,len(externalLowLevel)+2)
names=append(names,string(ScopeAll))
names=append(names,string(ScopeApplicationConnect))

// curated low-level names, filtered for validity
forname:=rangeexternalLowLevel {
if_,_,ok:=parseLowLevelScope(name);ok {
names=append(names,string(name))
}
}

sort.Slice(names,func(i,jint)bool {returnstrings.Compare(names[i],names[j])<0 })
returnnames
}
51 changes: 51 additions & 0 deletionscoderd/rbac/scopes_catalog_internal_test.go
View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
package rbac

import (
"sort"
"testing"

"github.com/stretchr/testify/require"
)

funcTestExternalScopeNames(t*testing.T) {
t.Parallel()

names:=ExternalScopeNames()
require.NotEmpty(t,names)

// Ensure sorted ascending
sorted:=append([]string(nil),names...)
sort.Strings(sorted)
require.Equal(t,sorted,names)

// Ensure each entry parses and expands to site-only
for_,name:=rangenames {
// Skip `all` and `application_connect` since they do not
// expand into a low level scope.
// They are handled differently.
ifname==string(ScopeAll)||name==string(ScopeApplicationConnect) {
continue
}

res,act,ok:=parseLowLevelScope(ScopeName(name))
require.Truef(t,ok,"catalog entry should parse: %s",name)

s,err:=ScopeName(name).Expand()
require.NoErrorf(t,err,"catalog entry should expand: %s",name)
require.Len(t,s.Site,1)
require.Equal(t,res,s.Site[0].ResourceType)
require.Equal(t,act,s.Site[0].Action)
require.Empty(t,s.Org)
require.Empty(t,s.User)
}
}

funcTestIsExternalScope(t*testing.T) {
t.Parallel()

require.True(t,IsExternalScope("workspace:read"))
require.True(t,IsExternalScope("template:use"))
require.True(t,IsExternalScope("workspace:*"))
require.False(t,IsExternalScope("debug_info:read"))// internal-only
require.False(t,IsExternalScope("unknown:read"))
}
3 changes: 2 additions & 1 deletionscripts/check-scopes/README.md
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -40,4 +40,5 @@ When the tool reports missing values:
make -B gen/db&& make lint/check-scopes
```

3. Decide whether each new scope is public (exposed in the catalog) or internal-only (handled by the catalog task).
3. Decide whether each new scope is public (exposed in the catalog) or internal-only.
- 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.
2 changes: 1 addition & 1 deletionscripts/check-scopes/main.go
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -53,7 +53,7 @@ func main() {
_,_=fmt.Fprintf(os.Stderr," ALTER TYPE api_key_scope ADD VALUE IF NOT EXISTS '%s';\n",m)
}
_,_=fmt.Fprintln(os.Stderr)
_,_=fmt.Fprintln(os.Stderr,"Also decide if each new scope ispublic (exposed in thecatalog) or internal-only (catalog task).")
_,_=fmt.Fprintln(os.Stderr,"Also decide if each new scope isexternal (exposed in the`externalLowLevel` in coderd/rbac/scopes_catalog.go) or internal-only.")
os.Exit(1)
}

Expand Down
Loading

[8]ページ先頭

©2009-2025 Movatter.jp