mirror of
https://github.com/coder/coder.git
synced 2026-11-02 21:50:08 +08:00
fix: canonicalize API key scope aliases at ingress (#28322)
`rbac.IsExternalScope` accepts `all` and `application_connect`, neither
of which is an `api_key_scope` enum member. The plural `Scopes` field
stored the name as given, so `{"scopes":["all"]}` passed validation and
then 500'd inside `apikey.Generate` with `invalid API key scope: "all"`.
Reachable from `coder tokens create --scope all`, from the spellings
`docs/admin/users/sessions-tokens.md` taught, and from the `codersdk`
constants exported for exactly this purpose.
- Canonicalize inside `apikey.Generate`, in the loop that already
validates each name. One statement covers every caller and all three
input paths: plural `Scopes`, deprecated singular `Scope`, and the
default. Replaces two open-coded switches and the handler's own
per-element copy, so one place decides the stored spelling and the
handler only decides what may be requested.
- Deduplicate in the same pass. An alias and its canonical spelling are
two names going in and one name in the column.
- `ExternalScopeNames()` lists every name `IsExternalScope` accepts,
instead of dropping catalog entries that fail to parse. A curated entry
that cannot be stored used to pass every test and 500 at runtime; it now
fails two.
- Split the 400. A misspelled name and an internal `api_key_scope`
member need different words, since no re-spelling makes the second
requestable. Both rejection sites share one helper that names the case
and links the docs.
- Add reject-path tests for `not_a_real_scope` and `debug_info:read`.
The second is a valid enum member the rbac catalog treats as internal,
so before this both handler guards could be deleted with the suite still
green. A further case pins that plural `Scopes` wins when a caller sets
both fields.
- `TestExternalScopesAreStorable` pins the class rather than the two
known instances: every public rbac scope name must be storable.
`coderd/rbac` cannot assert this itself, since `database` imports `rbac`
and not the reverse.
- Docs use the canonical spellings, link the `codersdk.APIKeyScope`
schema, and say which scopes a token cannot request.
Egress is unchanged: `convertAPIKey` still derives a legacy singular
name on the way out. `ExternalScopeNames()` returns the same 57 names as
before, and `codersdk/apikey_scopes_gen.go` regenerates identically.
`rbac.CanonicalScopeName` merged with #28167, so this applies to `main`
and reviews on its own. The OAuth2 provider ignores scopes entirely
today (`authorize.go:237`, `tokens.go:377`, `tokens.go:520`), so it is
unaffected until those TODOs resolve.
Deferred from review: PLAT-528, PLAT-529, PLAT-530, and PLAT-532.
PLAT-532 covers `{"scopes":[]}` and `{"allow_list":[]}` defaulting open,
which predates this PR.
---------
Co-authored-by: McKayla はな <mckayla@hey.com>
This commit is contained in:
@@ -92,7 +92,7 @@ Use our API reference for more information on how to
|
||||
### Set max token length
|
||||
|
||||
You can use the
|
||||
[`CODER_MAX_TOKEN_LIFETIME`](https://coder.com/docs/reference/cli/server#--max-token-lifetime)
|
||||
[`CODER_MAX_TOKEN_LIFETIME`](../../reference/cli/server.md#--max-token-lifetime)
|
||||
server flag to set the maximum duration for long-lived tokens in your
|
||||
deployment.
|
||||
|
||||
@@ -123,7 +123,7 @@ Deleting the user that owns a token revokes every token that user holds at the s
|
||||
|
||||
## API Key Scopes
|
||||
|
||||
API key scopes allow you to limit the permissions of a token to specific operations. By default, tokens are created with the `all` scope, granting full access to all actions the user can perform. For improved security, you can create tokens with limited scopes that restrict access to only the operations needed.
|
||||
API key scopes allow you to limit the permissions of a token to specific operations. By default, tokens are created with the `coder:all` scope, granting full access to all actions the user can perform. For improved security, you can create tokens with limited scopes that restrict access to only the operations needed.
|
||||
|
||||
Scopes follow the format `resource:action`, where `resource` is the type of object (like `workspace`, `template`, or `user`) and `action` is the operation (like `read`, `create`, `update`, or `delete`). You can also use wildcards like `workspace:*` to grant all permissions for a specific resource type.
|
||||
|
||||
@@ -145,9 +145,15 @@ Common scope examples include:
|
||||
- `workspace:*` - Full workspace access (create, read, update, delete)
|
||||
- `template:read` - View template information
|
||||
- `api_key:read` - View API keys (useful for automation)
|
||||
- `application_connect` - Connect to workspace applications
|
||||
- `coder:application_connect` - Connect to workspace applications
|
||||
|
||||
For a complete list of available scopes, see the API reference documentation.
|
||||
The
|
||||
[`codersdk.APIKeyScope` schema](../../reference/api/schemas.md#codersdkapikeyscope)
|
||||
lists every scope name Coder defines, but a token cannot request all of them.
|
||||
Internal scopes such as `debug_info:read` are rejected with a `400` response, so
|
||||
use the `resource:action` and `coder:` names described on this page.
|
||||
|
||||
The older names `all` and `application_connect` are still accepted for backward compatibility. Tokens created with them are stored and listed as `coder:all` and `coder:application_connect`.
|
||||
|
||||
### Allow lists (advanced)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user