Conversation
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
Resolve caller identity before the namespace-scoped binding lookup, then authorize against the stored target. Preserve 401 responses and mask missing or target-denied bindings as 404. Add provider and endpoint regression coverage and refresh generated TypeScript route descriptions.
4c7725d to
39138dd
Compare
|
|
||
| context = {"target_type": target_type, "target_id": target_id} | ||
| try: | ||
| return await authorizer.authorize(request, operation, context) |
There was a problem hiding this comment.
The principal returned by authorize() should be same as what we received earlier at identity = await authorizer.resolve_identity(request, operation) if both work properly. For any reason if there is namespace_key mistmatch from both then incorrect namespace_key would execute for the binding. Good to have,
principal = await authorizer.authorize(request, operation, context)
if principal.namespace_key != identity.namespace_key:
raise ... # fail closed
return principal
There was a problem hiding this comment.
Good catch. I added a namespace equality check after target authorization and before the handler receives the principal in 2edb64d. If the identity and target grants disagree, the route fails closed with the existing 404 CONTROL_BINDING_NOT_FOUND response, keeping inaccessible and missing IDs indistinguishable. I also added a parameterized GET/PATCH/DELETE regression test that verifies the binding remains unchanged. Local pre-push lint/typecheck and GitHub Python CI passed.
Problem
SAO-17527 reports 10/10 failures for
DELETE /api/v1/control-bindings/{binding_id}in demo-v2-poc. The ID route sentcontrol_bindings.writewithout target context. Orbit rejected that request with 400, which Agent Control surfaced as 502. GET and PATCH use the same by-ID authorization pattern by source inspection; their failure was not reproduced live for this ticket.Change
control_bindings.readorcontrol_bindings.writewith its stored target. The handler reads or mutates the row in the authorized namespace again.AGENT_CONTROL_AUTH_UPSTREAM_IDENTITY_URLis optional; compatible custom upstreams can set it to opt into stored-target authorization. Those deployments do not need a new setting to keep their prior behavior.Validation
a63d331), the full local server suite passed (936 tests); focused auth and control-binding suites passed (193 tests), including GET/PATCH/DELETE compatibility checks for a custom upstream that rejects target context.dcf5901, local Ruff lint and server mypy passed. DB-free configuration and mock HTTP checks covered Orbit URL derivation, custom upstream fallback, explicit URL precedence, and identity/target authorization requests.2edb64d, a GET/PATCH/DELETE regression test covers an identity/target-authorization namespace mismatch and checks that the binding remains unchanged. Localmake prepushpassed after installing declared optional test dependencies. The DB-backed endpoint test could not run locally because PostgreSQL and Docker were unavailable.2edb64d.Rollout and remaining risk
POST /internal/auth/resolve_tenant_contextand that its management authorization URL matches the known path. Target-aware ID calls add one identity request before the stored-target authorization request.