From 8cf124530cfbe6b7de5d58f16ee1ac94cdcb7b1c Mon Sep 17 00:00:00 2001 From: tegwick Date: Thu, 6 Aug 2026 21:51:11 +0200 Subject: [PATCH] Harden Control Plane login; fix /ui redirect Strip whitespace/quotes on pasted tokens; clearer error naming the OpenBao founding-admin path. Redirect /ui to /ui/. Image 0.1.3. --- k8s/railiance/bootstrap-job.yaml | 2 +- k8s/railiance/deployment.yaml | 2 +- k8s/railiance/migrate-job.yaml | 2 +- src/target_revenue/service/combined.py | 7 +++++++ src/target_revenue/service/control_plane_app.py | 17 ++++++++++++++--- 5 files changed, 24 insertions(+), 6 deletions(-) diff --git a/k8s/railiance/bootstrap-job.yaml b/k8s/railiance/bootstrap-job.yaml index 864a54b..aef4999 100644 --- a/k8s/railiance/bootstrap-job.yaml +++ b/k8s/railiance/bootstrap-job.yaml @@ -30,7 +30,7 @@ spec: fsGroup: 10001 containers: - name: bootstrap - image: forgejo.coulomb.social/coulomb/target-revenue:0.1.2 + image: forgejo.coulomb.social/coulomb/target-revenue:0.1.3 imagePullPolicy: IfNotPresent env: - name: TRF_BOOTSTRAP_BINKY diff --git a/k8s/railiance/deployment.yaml b/k8s/railiance/deployment.yaml index 6247c65..7c37cab 100644 --- a/k8s/railiance/deployment.yaml +++ b/k8s/railiance/deployment.yaml @@ -25,7 +25,7 @@ spec: fsGroup: 10001 containers: - name: target-revenue - image: forgejo.coulomb.social/coulomb/target-revenue:0.1.2 + image: forgejo.coulomb.social/coulomb/target-revenue:0.1.3 imagePullPolicy: IfNotPresent ports: - name: http diff --git a/k8s/railiance/migrate-job.yaml b/k8s/railiance/migrate-job.yaml index bb79d80..ff8f1c1 100644 --- a/k8s/railiance/migrate-job.yaml +++ b/k8s/railiance/migrate-job.yaml @@ -28,7 +28,7 @@ spec: fsGroup: 10001 containers: - name: migrate - image: forgejo.coulomb.social/coulomb/target-revenue:0.1.2 + image: forgejo.coulomb.social/coulomb/target-revenue:0.1.3 imagePullPolicy: IfNotPresent env: - name: TRF_RUN_MIGRATIONS diff --git a/src/target_revenue/service/combined.py b/src/target_revenue/service/combined.py index f59bf3c..e61baa0 100644 --- a/src/target_revenue/service/combined.py +++ b/src/target_revenue/service/combined.py @@ -15,6 +15,7 @@ default so a single Service port works without Traefik strip-prefix. from __future__ import annotations from fastapi import FastAPI +from fastapi.responses import RedirectResponse from .app import app as trust_service_app from .control_plane_app import app as control_plane_app @@ -27,6 +28,12 @@ def healthz() -> dict[str, str]: return {"status": "ok"} +@app.get("/ui") +def ui_no_trailing_slash() -> RedirectResponse: + """Browsers often hit /ui without a trailing slash; the mount needs /ui/.""" + return RedirectResponse(url="/ui/", status_code=307) + + # More specific mount first. app.mount("/ui", control_plane_app) app.mount("/", trust_service_app) diff --git a/src/target_revenue/service/control_plane_app.py b/src/target_revenue/service/control_plane_app.py index 402d646..2063317 100644 --- a/src/target_revenue/service/control_plane_app.py +++ b/src/target_revenue/service/control_plane_app.py @@ -166,11 +166,22 @@ def login_submit( token: str = Form(...), conn: Connection = Depends(get_connection), ): + # OpenBao / password-manager paste often includes trailing newlines or quotes. + cleaned = token.strip().strip('"').strip("'").strip() + if not cleaned: + return _redirect("/login", request, "Credential token is required.", "danger") try: - registry.authenticate(conn, token) + registry.authenticate(conn, cleaned) except registry.RegistrationError: - return _redirect("/login", request, "Invalid or revoked credential token.", "danger") - request.session["token"] = token + return _redirect( + "/login", + request, + "Invalid or revoked credential token. Use field `token` from " + "OpenBao path platform/operators/founding-admin/revenue " + "(not a runtime DSN or signing key).", + "danger", + ) + request.session["token"] = cleaned return _redirect("/", request)