api/v2: refuse an unknown keyType

This commit is contained in:
Kristoffer Dalby committed 2026-10-30 14:55:37 +00:00
1 parent e13ed03e70
commit 70d96ccd8f
3 files changed
+29 -7

No files matched your search

+8 -3
View File
@@ -156,11 +156,16 @@ func registerKeys(api huma.API, b Backend) {
return nil, err
}
if in.Body.KeyType == keyTypeClient {
switch in.Body.KeyType {
case keyTypeClient:
return createOAuthClient(ctx, b, in.Body)
case "", keyTypeAuth:
return createAuthKey(ctx, b, in.Body)
default:
return nil, huma.Error400BadRequest(
"invalid key type, " + strconv.Quote(in.Body.KeyType) + " is not supported",
)
}
return createAuthKey(ctx, b, in.Body)
})
huma.Register(api, huma.Operation{
+2 -4
View File
@@ -71,9 +71,7 @@ var apiv2CompatSkipReasons = map[string]string{
"key-list/setup-token-keys/4/tags": mintTagsNotEchoed,
"key-list/setup-token-keys/6/tags": mintTagsNotEchoed,
"oauth/K2/0/status": unknownKeyType,
"oauth/K2/0/outcome": unknownKeyType,
"oauth/K5/0/status": unknownKeyType,
"oauth/K5/0/status": unknownKeyType,
"oauth/E4/0/status": tagRefusalStatus,
"oauth/E5/0/status": tagRefusalStatus,
@@ -202,7 +200,7 @@ const (
const (
mintScopeRefusalStatus = "TOKEN_SCOPE_REFUSAL_STATUS: SaaS refuses a token scope the client lacks with 403 and a message; headscale with 400 invalid_scope"
mintTagsNotEchoed = "TOKEN_TAGS_NOT_ECHOED: SaaS's token answer names the token's tags; headscale's has no tags"
unknownKeyType = "UNKNOWN_KEY_TYPE: SaaS refuses an unknown keyType with 400 before it checks scopes; headscale makes an auth key from it"
unknownKeyType = "UNKNOWN_KEY_TYPE: SaaS refuses an unknown keyType with 400 before it checks scopes; headscale checks the scope first and answers 403"
tagRefusalStatus = "TAG_REFUSAL_STATUS: SaaS refuses a tag outside the token's grant with 400 requested tags are invalid or not permitted; headscale with 403"
keyListWithoutAll = "KEY_LIST_WITHOUT_ALL: without all=true SaaS lists an OAuth token only the auth keys OAuth tokens made, whatever its tags and theirs; headscale lists every key"
keyListInvalidKeys = "KEY_LIST_INVALID_KEYS: SaaS leaves spent and revoked auth keys out of a listing; headscale lists them"
+19
View File
@@ -275,6 +275,25 @@ func TestAPIv2OAuth_ValidationErrorsBounded(t *testing.T) {
assert.Equal(t, "and 980 more", out.Data[0].Errors[20])
}
// TestAPIv2OAuth_UnknownKeyTypeRefused: a keyType other than auth or client
// is refused, not taken as an auth key.
func TestAPIv2OAuth_UnknownKeyTypeRefused(t *testing.T) {
app, baseURL, admin := newOAuthTestServer(t)
status, body := apiReq(t, http.MethodPost, baseURL+"/api/v2/tailnet/-/keys", admin, map[string]any{
"keyType": "nosuch",
"capabilities": map[string]any{"devices": map[string]any{"create": map[string]any{
"reusable": true, "ephemeral": false, "preauthorized": true, "tags": []string{"tag:ci"},
}}},
})
assert.Equal(t, http.StatusBadRequest, status)
assert.Contains(t, string(body), `invalid key type, \"nosuch\" is not supported`)
keys, err := app.state.ListPreAuthKeys()
require.NoError(t, err)
assert.Empty(t, keys)
}
// TestAPIv2OAuth_UnknownPropertiesIgnored: a body property the API does not
// define is ignored, at the top and nested, as Tailscale's API does.
func TestAPIv2OAuth_UnknownPropertiesIgnored(t *testing.T) {