Problem
Namespace API keys are meant to be namespace-scoped and not tied to a user
(api-key is described as "namespace related and not tied to any user"). Several
account-level routes do not enforce this: they accept an API key when they should
reject it. The most concrete case is that an API key can enumerate the
namespace's API keys.
Affected routes (api/routes/routes.go)
ListAPIKeys (GET /api/namespaces/api-key): no BlockAPIKey, and it
succeeds. An API key can list the namespace's API keys. This is asymmetric
with CreateAPIKey / UpdateAPIKey / DeleteAPIKey, which all carry
routesmiddleware.BlockAPIKey.
GetNamespaceList (GET /api/namespaces): no BlockAPIKey. The service
scopes the result to the caller's tenant, so a key gets only its own
namespace, but this account-level "list namespaces" route should not accept a
key at all.
CreateNamespace (POST /api/namespaces): no BlockAPIKey. The service
requires a resolvable user, so with a key it fails with "user not found"
(404) instead of a clean 403.
LeaveNamespace (DELETE /api/namespaces/{tenant}/members): no BlockAPIKey.
Needs a user/member, so it fails for a key.
Current behavior
Three of these are safe by accident: the service layer rejects or scopes the
request. But they return a confusing 404 / no-op instead of a clean 403, and the
block is implicit rather than enforced at the routing layer. ListAPIKeys is the
real gap: it actually succeeds for an API key.
Proposed fix
Add routesmiddleware.BlockAPIKey to these four routes, matching the existing
api-key management routes. This returns a clean 403 and makes the contract
explicit and enforced at the routing layer rather than relying on the service
failing.
Related
The OpenAPI customer documentation currently marks these four operations with
x-internal: true to keep them out of the published spec. Once BlockAPIKey is
added, the api-key scheme can be removed from their security blocks and the
x-internal overrides dropped, so the customer doc is derived purely from
security.
Problem
Namespace API keys are meant to be namespace-scoped and not tied to a user
(
api-keyis described as "namespace related and not tied to any user"). Severalaccount-level routes do not enforce this: they accept an API key when they should
reject it. The most concrete case is that an API key can enumerate the
namespace's API keys.
Affected routes (
api/routes/routes.go)ListAPIKeys(GET /api/namespaces/api-key): noBlockAPIKey, and itsucceeds. An API key can list the namespace's API keys. This is asymmetric
with
CreateAPIKey/UpdateAPIKey/DeleteAPIKey, which all carryroutesmiddleware.BlockAPIKey.GetNamespaceList(GET /api/namespaces): noBlockAPIKey. The servicescopes the result to the caller's tenant, so a key gets only its own
namespace, but this account-level "list namespaces" route should not accept a
key at all.
CreateNamespace(POST /api/namespaces): noBlockAPIKey. The servicerequires a resolvable user, so with a key it fails with "user not found"
(404) instead of a clean 403.
LeaveNamespace(DELETE /api/namespaces/{tenant}/members): noBlockAPIKey.Needs a user/member, so it fails for a key.
Current behavior
Three of these are safe by accident: the service layer rejects or scopes the
request. But they return a confusing 404 / no-op instead of a clean 403, and the
block is implicit rather than enforced at the routing layer.
ListAPIKeysis thereal gap: it actually succeeds for an API key.
Proposed fix
Add
routesmiddleware.BlockAPIKeyto these four routes, matching the existingapi-key management routes. This returns a clean 403 and makes the contract
explicit and enforced at the routing layer rather than relying on the service
failing.
Related
The OpenAPI customer documentation currently marks these four operations with
x-internal: trueto keep them out of the published spec. OnceBlockAPIKeyisadded, the
api-keyscheme can be removed from theirsecurityblocks and thex-internaloverrides dropped, so the customer doc is derived purely fromsecurity.