Apply the HTTP→HTTPS redirect ahead of route matching, exempting the liveness routes #70

Open
opened 2026-10-27 09:43:38 +00:00 by james.oates · 1 comment
Owner

Follow-on from #69, which fixed the login by refusing cleartext on the session routes. This is the general fix DevInfra proposed as option (1) there: move the redirect out of proxy_handler and layer it over the whole app, so it covers every route rather than only unmatched ones.

Not started — needs a decision first, which is why it is split out.

The blocker

/health (in session_routes) and /ready (in admin_routes) are both matched routes, so they are served on plaintext today. A redirect layered over the whole app would 301 them. A monitoring probe that does not follow redirects, or that follows one to a certificate it does not trust, goes red — so the naive version of this change trades a credential leak for a monitoring outage. #67 is already open about health having no reachable non-admin surface, and that should probably be settled first or together.

So this needs an explicit exemption list, and a decision on what belongs in it. At minimum /health and /ready.

Also worth deciding

The redirect currently consults the service list for skip_https_redirect before firing. proxy_handler already loads services for routing, so the read is free there; as a layer over the whole app it would add a services query to every admin and API request. Either accept that, scope the opt-out check to the fallback path, or reshape it.

What is already done

access::request_is_https is the single trust-gated definition of whether a request arrived over TLS (added in #69), so this change does not need to re-derive it.

Nothing here is urgent: the credential path is closed by #69's refusal, which also holds where an operator disables the redirect entirely — something this change cannot do.

Follow-on from #69, which fixed the login by refusing cleartext on the session routes. This is the general fix DevInfra proposed as option (1) there: move the redirect out of `proxy_handler` and layer it over the whole app, so it covers every route rather than only unmatched ones. **Not started — needs a decision first, which is why it is split out.** ## The blocker `/health` (in `session_routes`) and `/ready` (in `admin_routes`) are both matched routes, so they are served on plaintext today. A redirect layered over the whole app would `301` them. A monitoring probe that does not follow redirects, or that follows one to a certificate it does not trust, goes red — so the naive version of this change trades a credential leak for a monitoring outage. #67 is already open about health having no reachable non-admin surface, and that should probably be settled first or together. So this needs an explicit exemption list, and a decision on what belongs in it. At minimum `/health` and `/ready`. ## Also worth deciding The redirect currently consults the service list for `skip_https_redirect` before firing. `proxy_handler` already loads services for routing, so the read is free there; as a layer over the whole app it would add a services query to every admin and API request. Either accept that, scope the opt-out check to the fallback path, or reshape it. ## What is already done `access::request_is_https` is the single trust-gated definition of whether a request arrived over TLS (added in #69), so this change does not need to re-derive it. Nothing here is urgent: the credential path is closed by #69's refusal, which also holds where an operator disables the redirect entirely — something this change cannot do.
james.oates added this to the v2.1 milestone 2026-10-27 09:43:38 +00:00
Author
Owner

Deferred: not requested, and no longer guards anything (James's rule, 2026-10-27). Milestone removed, left open.

The credential path this would have covered is already closed by #69's refusal, which is also strictly stronger for that route: it holds when an operator sets redirect_http_to_https = false, where a redirect does nothing at all. What remains here is generality — covering every matched route uniformly — and nothing is asking for it.

Against that, it still carries the cost recorded above: it would 301 /health and /ready, so it needs an exemption list designed alongside #67, and it would add a services query to every admin and API request. Building it now would be paying that to make a guarantee no deployment needs.

Worth reopening into a milestone if a route other than the session routes is ever found serving something that must not cross in cleartext. #71 is the live candidate, and it has its own problem (loopback automation) rather than being solved by this.

**Deferred: not requested, and no longer guards anything (James's rule, 2026-10-27).** Milestone removed, left open. The credential path this would have covered is already closed by #69's refusal, which is also strictly stronger for that route: it holds when an operator sets `redirect_http_to_https = false`, where a redirect does nothing at all. What remains here is generality — covering every matched route uniformly — and nothing is asking for it. Against that, it still carries the cost recorded above: it would `301` `/health` and `/ready`, so it needs an exemption list designed alongside #67, and it would add a services query to every admin and API request. Building it now would be paying that to make a guarantee no deployment needs. Worth reopening into a milestone if a route other than the session routes is ever found serving something that must not cross in cleartext. #71 is the live candidate, and it has its own problem (loopback automation) rather than being solved by this.
james.oates removed this from the v2.1 milestone 2026-10-27 15:12:23 +00:00
Sign in to join this conversation.
No labels
No milestone
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
IsoHex/edge-router#70
No description provided.