Restrict POST /configuration endpoint to loopback#3669
Conversation
The POST /configuration endpoint used in late-configured (hosted) mode now requires the request to originate from a loopback address. An optional bootstrap token (DAB_CONFIG_AUTH_TOKEN env var, X-DAB-CONFIG-AUTH header) can be required as an additional check. Backward compatible: in-process callers (TestServer) and loopback callers without a token continue to work.
There was a problem hiding this comment.
Pull request overview
This PR hardens the late-bound hosted-mode POST /configuration bootstrap endpoint by restricting access to loopback callers and (optionally) requiring a bootstrap token header, reducing exposure prior to the auth middleware running.
Changes:
- Added
IsConfigurationRequestAuthorized(HttpContext)and enforced it in the/configurationgating middleware (returning403 Forbiddenwhen unauthorized). - Introduced optional bootstrap-token validation via
DAB_CONFIG_AUTH_TOKEN+X-DAB-CONFIG-AUTHusing fixed-time comparison. - Added new test coverage for authorization behavior across loopback/non-loopback and token combinations.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
| src/Service/Startup.cs | Adds loopback + optional bootstrap-token authorization gating for POST /configuration. |
| src/Service.Tests/Configuration/ConfigurationEndpointAuthorizationTests.cs | Adds unit + TestServer coverage for the new authorization behavior. |
- Handle ::ffff:127.0.0.1 (dual-stack Kestrel) as loopback by calling MapToIPv4 first - Fix stray quote in IsConfigurationRequestAuthorized XML doc - Add matrix row covering IPv4-mapped IPv6 loopback
…tion Other tests in the assembly (e.g. TestLoadingLocalCosmosSettings) set ASPNETCORE_ENVIRONMENT and DAB_ENVIRONMENT without cleanup. Those env vars caused FileSystemRuntimeConfigLoader to find an environment-specific dab-config.*.json on disk and auto-initialize the runtime, which made POST /configuration return 409 Conflict before the new security middleware was exercised, breaking the EndToEnd matrix in CI. Snapshot and clear ASPNETCORE_ENVIRONMENT and DAB_ENVIRONMENT before creating the TestServer, and restore them in a finally block. Verified locally by setting ASPNETCORE_ENVIRONMENT=CosmosDb_NoSql in the parent shell and rerunning all 22 tests successfully.
anushakolan
left a comment
There was a problem hiding this comment.
Just a minor comment to address; otherwise LGTM.
It would be helpful to create a tracking task and link it to this PR, along with relevant context. This makes it easier to understand the background and motivations for the change in the future.
RubenCerna2079
left a comment
There was a problem hiding this comment.
LGTM! Approving with the expectation that the comment from Anusha gets resolved.
Addresses two review comments on PR #3669: 1. (anushakolan) Move DAB_CONFIG_AUTH_TOKEN, ASPNETCORE_ENVIRONMENT, and DAB_ENVIRONMENT snapshot/restore into TestInitialize/TestCleanup so any pre-existing values are preserved verbatim. Previously TestCleanup reset DAB_CONFIG_AUTH_TOKEN to null which could perturb other tests. 2. (RubenCerna2079) Add explicit unit-test matrix rows for private/public IPv4 with correct token, wrong token, and missing header so the 'non-loopback is always denied regardless of token' contract is regression-locked. Matrix grows from 14 to 18 rows; total tests 22 -> 26. Verified locally by setting both ASPNETCORE_ENVIRONMENT=CosmosDb_NoSql and DAB_CONFIG_AUTH_TOKEN=preexisting-value in the parent shell: all 26 tests pass and both env vars retain their original values after the run.
Summary
Restrict the late-configured
POST /configurationendpoint so it is only callable from the loopback interface, with an optional bootstrap-token check on top.Why
POST /configurationis used in hosted mode (e.g. Azure Static Web Apps) to deliver the runtime config — including the database connection string — to an uninitialized DAB instance. It currently runs before the authentication middleware and has no other access control, which is more permissive than required for what is effectively a host-to-runtime bootstrap channel.Change
In
src/Service/Startup.cs, the existing middleware that gatesPOST /configurationnow also checksIsConfigurationRequestAuthorized(HttpContext)and returns403 Forbiddenif it fails. The check enforces:RemoteIpAddress(in-process callers such asTestServer) is treated as loopback.DAB_CONFIG_AUTH_TOKENenvironment variable is set, the request must include a matchingX-DAB-CONFIG-AUTHheader (fixed-time comparison).The rest of the middleware ordering is unchanged.
Backward compatibility
TestServertests keep working unchanged.Tests