Partner API: server-side enrollment key creation (POST /enrollment-keys) #2815
Replies: 3 comments 1 reply
|
The proposal is close; the highest-risk part is the token lifecycle rather than the route itself. The API key scope, organization ownership, site ownership, and RLS boundary should all be checked before creating the key, with an explicit rejection for a site outside the requested organization. For the generated enrollment key, I would require a bounded TTL and maxUsage, hash it at rest, return the raw value only in the creation response, and make consumption atomic so concurrent requests cannot exceed maxUsage. Rate limits, audit events, and an idempotency strategy would also be useful. Avoid putting the raw key in URLs or logs, and make sure error payloads never echo it. The implementation should specify the 201 response schema and errors for invalid scope, expired keys, exhausted keys, and cross-organization access. A migration test plus concurrency tests around maxUsage would give confidence that the database function and application allowlist are updated consistently. |
|
Thanks for the detailed review — we've addressed the feedback before submitting.
|
|
Reviewed — and yes, this is a gap we want to close. Server-side minting for provisioning pipelines is a legitimate need the session-bound UI flow doesn't serve, and a scoped service-principal permission is the right mechanism for it. Full review is on the PR (#2826): the structure is right and the migration is clean, but there are five things to fix before merge — the biggest being that the new write scope currently lands in the default scope set (so it isn't opt-in as described), and that the TTL path skips the partner-configured expiry cap the user-facing routes enforce. Details with file references are in the review. Once those land I'm happy to merge this — thanks for pairing the proposal with a working implementation. |
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Use case
MSP tools and integrators that automate device onboarding need a way to generate enrollment tokens server-side without a full user session. Today the only option is
POST /api/v1/enrollment-keys, which requiresAuthorization: Bearer <JWT>— meaning a user must authenticate (including any MFA step-up) before a token can be issued.For server-to-server automation this is a blocking gap. The Partner API already has the right auth model (
X-API-Keywith service principal scopes) and RLS pattern for this kind of integration.Proposed addition
Add
POST /enrollment-keysto the Partner API (under/api/v1/partner-api/), gated by a newenrollment-keys:writescope on the calling service principal.Request:
Behavior mirrors the existing user-facing endpoint:
principal.accessibleOrgIdssiteIdownership validated against the specified orgThe new
enrollment-keys:writescope is opt-in — not included in any default scope set — so existing service principal keys are unaffected.Why the Partner API and not a new endpoint?
The Partner API already handles the service-principal auth, RLS context, and org-scoping logic that this feature needs. Adding it there keeps the pattern consistent and avoids introducing a second auth scheme for automation use cases.
Implementation
I have a working implementation ready as a PR from a fork if the team is open to it. The change is four files:
apps/api/src/routes/partnerApi/enrollmentKeys.tsenrollment-keys:writeadded toPARTNER_SERVICE_PRINCIPAL_SCOPESinpartnerServicePrincipalScopes.tsapps/api/src/routes/partnerApi/index.tsbreeze_valid_partner_service_principal_scopes(the SQL function backing thepartner_service_principals_scopes_checkconstraint) must be updated to include the new scope value. Without this, any attempt to addenrollment-keys:writeto an existing service principal is rejected at the database level. The migration usesCREATE OR REPLACE FUNCTIONso it is safe to apply to an existing installation without dropping the constraint or any data.Happy to adjust scope naming, parameter defaults, or anything else to fit the project's conventions.
All reactions