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: replace ExternalAPIKeyScopes with detailed ScopeCatalog#20248

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

Draft
ThomasK33 wants to merge1 commit intothomask33/09-30-api_allowlist_structured_json
base:thomask33/09-30-api_allowlist_structured_json
Choose a base branch
Loading
fromthomask33/10-09-add_scope_catalog_api
Draft
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
64 changes: 52 additions & 12 deletionscoderd/apidoc/docs.go
View file
Open in desktop

Some generated files are not rendered by default. Learn more abouthow customized files appear on GitHub.

64 changes: 52 additions & 12 deletionscoderd/apidoc/swagger.json
View file
Open in desktop

Some generated files are not rendered by default. Learn more abouthow customized files appear on GitHub.

2 changes: 1 addition & 1 deletioncoderd/coderd.go
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -1051,7 +1051,7 @@ func New(options *Options) *API {
// All CSP errors will be logged
r.Post("/csp/reports", api.logReportCSPViolations)

r.Get("/auth/scopes", api.listExternalScopes)
r.Get("/auth/scopes", api.listScopeCatalog)

r.Get("/buildinfo", buildInfoHandler(buildInfo))
// /regions is overridden in the enterprise version
Expand Down
90 changes: 90 additions & 0 deletionscoderd/rbac/scopes_catalog.go
View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,29 @@
package rbac

import (
"fmt"
"sort"
"strings"

"golang.org/x/exp/slices"

"github.com/coder/coder/v2/coderd/rbac/policy"
)

// 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.
type LowLevelScopeMeta struct {
Name ScopeName
Resource string
Action policy.Action
}

type CompositeScopeMeta struct {
Name ScopeName
ExpandsTo []ScopeName
}

var externalLowLevel = map[ScopeName]struct{}{
// Workspaces
"workspace:read": {},
Expand DownExpand Up@@ -63,6 +79,8 @@ var externalComposite = map[ScopeName]struct{}{
"coder:apikeys.manage_self": {},
}

var externalSpecial = []ScopeName{ScopeAll, ScopeApplicationConnect}

// IsExternalScope returns true if the scope is public, including the
// `all` and `application_connect` special scopes and the curated
// low-level resource:action scopes.
Expand DownExpand Up@@ -105,3 +123,75 @@ func ExternalScopeNames() []string {
sort.Slice(names, func(i, j int) bool { return strings.Compare(names[i], names[j]) < 0 })
return names
}

// ExternalLowLevelCatalog returns metadata for all public low-level scopes.
func ExternalLowLevelCatalog() []LowLevelScopeMeta {
metas := make([]LowLevelScopeMeta, 0, len(externalLowLevel))
for name := range externalLowLevel {
resource, action, ok := parseLowLevelScope(name)
if !ok {
continue
}
metas = append(metas, LowLevelScopeMeta{
Name: name,
Resource: resource,
Action: action,
})
}
sort.Slice(metas, func(i, j int) bool {
if metas[i].Resource == metas[j].Resource {
return metas[i].Name < metas[j].Name
}
return metas[i].Resource < metas[j].Resource
})
return metas
}

// ExternalCompositeCatalog returns metadata for public composite coder:* scopes.
func ExternalCompositeCatalog() []CompositeScopeMeta {
metas := make([]CompositeScopeMeta, 0, len(externalComposite))
for name := range externalComposite {
perms, ok := compositePerms[name]
if !ok {
continue
}
expands := make([]ScopeName, 0)
for resource, actions := range perms {
for _, action := range actions {
expands = append(expands, ScopeName(fmt.Sprintf("%s:%s", resource, action)))
}
}
slices.Sort(expands)
metas = append(metas, CompositeScopeMeta{
Name: name,
ExpandsTo: uniqueScopeNames(expands),
})
}
sort.Slice(metas, func(i, j int) bool { return metas[i].Name < metas[j].Name })
return metas
}

// ExternalSpecialScopes returns the list of legacy/special public scopes that
// are not part of the low-level or composite catalogs but remain requestable
// for backward compatibility.
func ExternalSpecialScopes() []ScopeName {
out := make([]ScopeName, len(externalSpecial))
copy(out, externalSpecial)
slices.Sort(out)
return out
}

func uniqueScopeNames(in []ScopeName) []ScopeName {
if len(in) == 0 {
return nil
}
out := make([]ScopeName, 0, len(in))
last := ScopeName("")
for i, name := range in {
if i == 0 || name != last {
out = append(out, name)
last = name
}
}
return out
}
46 changes: 36 additions & 10 deletionscoderd/scopes_catalog.go
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -8,23 +8,49 @@ import (
"github.com/coder/coder/v2/codersdk"
)

// listExternalScopes returns the curated list of API key scopes (resource:action)
// requestable via the API.
// listScopeCatalog returns the curated catalog of API key scopes that users
// can request. The catalog groups scopes into legacy “specials”, low-level
// resource:action atoms, and composite coder:* scopes.
//
// @Summary List API key scopes
// @ID list-api-key-scopes
// @Tags Authorization
// @Produce json
// @Success 200 {object} codersdk.ExternalAPIKeyScopes
// @Success 200 {object} codersdk.ScopeCatalog
// @Router /auth/scopes [get]
func (*API) listExternalScopes(rw http.ResponseWriter, r *http.Request) {
scopes := rbac.ExternalScopeNames()
external := make([]codersdk.APIKeyScope, 0, len(scopes))
for _, scope := range scopes {
external = append(external, codersdk.APIKeyScope(scope))
func (*API) listScopeCatalog(rw http.ResponseWriter, r *http.Request) {
lowMeta := rbac.ExternalLowLevelCatalog()
low := make([]codersdk.ScopeCatalogLowLevel, 0, len(lowMeta))
for _, meta := range lowMeta {
low = append(low, codersdk.ScopeCatalogLowLevel{
Name: codersdk.APIKeyScope(meta.Name),
Resource: codersdk.RBACResource(meta.Resource),
Action: string(meta.Action),
})
}

httpapi.Write(r.Context(), rw, http.StatusOK, codersdk.ExternalAPIKeyScopes{
External: external,
compMeta := rbac.ExternalCompositeCatalog()
composites := make([]codersdk.ScopeCatalogComposite, 0, len(compMeta))
for _, meta := range compMeta {
expands := make([]codersdk.APIKeyScope, 0, len(meta.ExpandsTo))
for _, name := range meta.ExpandsTo {
expands = append(expands, codersdk.APIKeyScope(name))
}
composites = append(composites, codersdk.ScopeCatalogComposite{
Name: codersdk.APIKeyScope(meta.Name),
ExpandsTo: expands,
})
}

specials := rbac.ExternalSpecialScopes()
specialScopes := make([]codersdk.APIKeyScope, 0, len(specials))
for _, name := range specials {
specialScopes = append(specialScopes, codersdk.APIKeyScope(name))
}

httpapi.Write(r.Context(), rw, http.StatusOK, codersdk.ScopeCatalog{
Specials: specialScopes,
LowLevel: low,
Composites: composites,
})
}
Loading
Loading

[8]ページ先頭

©2009-2025 Movatter.jp