Retire bao.coulomb.social callbacks from the KeyCape openbao-admin client
The name was retired on 2026-09-15. Remove both public UI callbacks from the code-defined client (openbao-client-config.py, create-secrets.sh), stop probing them in verify-openbao-client.sh, and fail verification in openbao-client-config.py and verify-t07.sh if either is registered again. The CLI and operator-tunneled 127.0.0.1:18200 callbacks remain. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Assistant: claude-code Assistant-Model: opus Assistant-Process: 299762@bnt-lap001 Assistant-Session: d3d3cea1-869c-44f1-be2a-3d6d3550e72e
This commit is contained in:
parent
a356f640ac
commit
3b14469afb
6 changed files with 51 additions and 18 deletions
|
|
@ -128,22 +128,21 @@ kubectl rollout restart deployment/keycape -n sso
|
||||||
```
|
```
|
||||||
|
|
||||||
The `openbao-admin` client is intentionally a public PKCE client for the
|
The `openbao-admin` client is intentionally a public PKCE client for the
|
||||||
current operator flow. It registers both the OpenBao CLI callback URIs and the
|
current operator flow. It registers the OpenBao CLI callback URIs and the
|
||||||
browser UI callbacks for `bao.coulomb.social`:
|
operator-tunneled browser UI callback:
|
||||||
|
|
||||||
```text
|
```text
|
||||||
http://localhost:8250/oidc/callback
|
http://localhost:8250/oidc/callback
|
||||||
http://127.0.0.1:8250/oidc/callback
|
http://127.0.0.1:8250/oidc/callback
|
||||||
http://127.0.0.1:18200/ui/vault/auth/netkingdom/oidc/callback
|
http://127.0.0.1:18200/ui/vault/auth/netkingdom/oidc/callback
|
||||||
https://bao.coulomb.social/ui/vault/auth/netkingdom/oidc/callback
|
|
||||||
https://bao.coulomb.social/ui/vault/auth/keycape/oidc/callback
|
|
||||||
```
|
```
|
||||||
|
|
||||||
The preferred browser UI callback is paired with the named Railiance Platform
|
The browser UI callback is paired with the named Railiance Platform operator
|
||||||
operator tunnel at `http://127.0.0.1:18200`. The public callback remains during
|
tunnel at `http://127.0.0.1:18200`. The public `bao.coulomb.social` callbacks
|
||||||
the bounded listener rollback window. The preferred browser auth mount is
|
were retired with that name on 2026-09-15; `openbao-client-config.py` and
|
||||||
`netkingdom`; `keycape` remains a compatibility alias. Keep the CLI callbacks
|
`verify-t07.sh` fail if either is registered again. The preferred browser auth
|
||||||
unless there is a separate decision to retire CLI login.
|
mount is `netkingdom`; `keycape` remains a compatibility alias. Keep the CLI
|
||||||
|
callbacks unless there is a separate decision to retire CLI login.
|
||||||
|
|
||||||
To add or refresh only the OpenBao client in a live cluster, do not decrypt the
|
To add or refresh only the OpenBao client in a live cluster, do not decrypt the
|
||||||
bootstrap secret bundle and do not re-run the full secret generator. Patch the
|
bootstrap secret bundle and do not re-run the full secret generator. Patch the
|
||||||
|
|
|
||||||
|
|
@ -140,8 +140,6 @@ clients:
|
||||||
- "http://localhost:8250/oidc/callback"
|
- "http://localhost:8250/oidc/callback"
|
||||||
- "http://127.0.0.1:8250/oidc/callback"
|
- "http://127.0.0.1:8250/oidc/callback"
|
||||||
- "http://127.0.0.1:18200/ui/vault/auth/netkingdom/oidc/callback"
|
- "http://127.0.0.1:18200/ui/vault/auth/netkingdom/oidc/callback"
|
||||||
- "https://bao.coulomb.social/ui/vault/auth/netkingdom/oidc/callback"
|
|
||||||
- "https://bao.coulomb.social/ui/vault/auth/keycape/oidc/callback"
|
|
||||||
allowedScopes: ["openid", "profile", "email", "groups"]
|
allowedScopes: ["openid", "profile", "email", "groups"]
|
||||||
grantTypes: ["authorization_code"]
|
grantTypes: ["authorization_code"]
|
||||||
clientType: "public"
|
clientType: "public"
|
||||||
|
|
|
||||||
|
|
@ -31,14 +31,18 @@ OPENBAO_CLIENT = {
|
||||||
"http://localhost:8250/oidc/callback",
|
"http://localhost:8250/oidc/callback",
|
||||||
"http://127.0.0.1:8250/oidc/callback",
|
"http://127.0.0.1:8250/oidc/callback",
|
||||||
"http://127.0.0.1:18200/ui/vault/auth/netkingdom/oidc/callback",
|
"http://127.0.0.1:18200/ui/vault/auth/netkingdom/oidc/callback",
|
||||||
"https://bao.coulomb.social/ui/vault/auth/netkingdom/oidc/callback",
|
|
||||||
"https://bao.coulomb.social/ui/vault/auth/keycape/oidc/callback",
|
|
||||||
],
|
],
|
||||||
"allowedScopes": ["openid", "profile", "email", "groups"],
|
"allowedScopes": ["openid", "profile", "email", "groups"],
|
||||||
"grantTypes": ["authorization_code"],
|
"grantTypes": ["authorization_code"],
|
||||||
"clientType": "public",
|
"clientType": "public",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# bao.coulomb.social was retired on 2026-09-15; its callbacks must not return.
|
||||||
|
RETIRED_OPENBAO_REDIRECT_URIS = (
|
||||||
|
"https://bao.coulomb.social/ui/vault/auth/netkingdom/oidc/callback",
|
||||||
|
"https://bao.coulomb.social/ui/vault/auth/keycape/oidc/callback",
|
||||||
|
)
|
||||||
|
|
||||||
RAPP_QONTO_CLIENT = {
|
RAPP_QONTO_CLIENT = {
|
||||||
"clientId": "rapp-qonto-client",
|
"clientId": "rapp-qonto-client",
|
||||||
"displayName": "rapp-qonto workload",
|
"displayName": "rapp-qonto workload",
|
||||||
|
|
@ -223,6 +227,16 @@ def client_errors(config: dict[str, Any], required: dict[str, Any]) -> list[str]
|
||||||
return errors
|
return errors
|
||||||
|
|
||||||
|
|
||||||
|
def retired_redirect_errors(config: dict[str, Any]) -> list[str]:
|
||||||
|
clients = config.get("clients") if isinstance(config.get("clients"), list) else []
|
||||||
|
target = next(
|
||||||
|
(client for client in clients if isinstance(client, dict) and client.get("clientId") == OPENBAO_CLIENT["clientId"]),
|
||||||
|
{},
|
||||||
|
)
|
||||||
|
retired = sorted(set(RETIRED_OPENBAO_REDIRECT_URIS) & set(target.get("redirectUris") or []))
|
||||||
|
return [f"{OPENBAO_CLIENT['clientId']}.redirectUris retired: {', '.join(retired)}"] if retired else []
|
||||||
|
|
||||||
|
|
||||||
def upsert_client(config: dict[str, Any], required: dict[str, Any]) -> dict[str, Any]:
|
def upsert_client(config: dict[str, Any], required: dict[str, Any]) -> dict[str, Any]:
|
||||||
clients = config.get("clients")
|
clients = config.get("clients")
|
||||||
if not isinstance(clients, list):
|
if not isinstance(clients, list):
|
||||||
|
|
@ -265,7 +279,7 @@ def render_patch(config: dict[str, Any]) -> None:
|
||||||
|
|
||||||
|
|
||||||
def verify(config: dict[str, Any]) -> None:
|
def verify(config: dict[str, Any]) -> None:
|
||||||
errors = client_errors(config, OPENBAO_CLIENT) + client_errors(config, RAPP_QONTO_CLIENT) + lldap_errors(config)
|
errors = client_errors(config, OPENBAO_CLIENT) + client_errors(config, RAPP_QONTO_CLIENT) + retired_redirect_errors(config) + lldap_errors(config)
|
||||||
if errors:
|
if errors:
|
||||||
for error in errors:
|
for error in errors:
|
||||||
print(f"[FAIL] {error}")
|
print(f"[FAIL] {error}")
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,25 @@ class OpenBaoClientConfigTest(unittest.TestCase):
|
||||||
[f"openbao-admin.redirectUris missing: {LOOPBACK_CALLBACK}"],
|
[f"openbao-admin.redirectUris missing: {LOOPBACK_CALLBACK}"],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def test_retired_public_callbacks_are_not_declared(self) -> None:
|
||||||
|
for uri in MODULE.RETIRED_OPENBAO_REDIRECT_URIS:
|
||||||
|
self.assertNotIn(uri, MODULE.OPENBAO_CLIENT["redirectUris"])
|
||||||
|
|
||||||
|
def test_retired_public_callback_fails_verification(self) -> None:
|
||||||
|
client = dict(MODULE.OPENBAO_CLIENT)
|
||||||
|
retired = MODULE.RETIRED_OPENBAO_REDIRECT_URIS[0]
|
||||||
|
client["redirectUris"] = [*MODULE.OPENBAO_CLIENT["redirectUris"], retired]
|
||||||
|
self.assertEqual(
|
||||||
|
MODULE.retired_redirect_errors({"clients": [client]}),
|
||||||
|
[f"openbao-admin.redirectUris retired: {retired}"],
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_upsert_removes_retired_callbacks(self) -> None:
|
||||||
|
stale = dict(MODULE.OPENBAO_CLIENT)
|
||||||
|
stale["redirectUris"] = [*MODULE.OPENBAO_CLIENT["redirectUris"], *MODULE.RETIRED_OPENBAO_REDIRECT_URIS]
|
||||||
|
updated = MODULE.upsert_client({"clients": [stale]}, MODULE.OPENBAO_CLIENT)
|
||||||
|
self.assertEqual(MODULE.retired_redirect_errors(updated), [])
|
||||||
|
|
||||||
def test_upsert_preserves_unrelated_clients(self) -> None:
|
def test_upsert_preserves_unrelated_clients(self) -> None:
|
||||||
config = {"clients": [{"clientId": "unrelated", "clientType": "public"}]}
|
config = {"clients": [{"clientId": "unrelated", "clientType": "public"}]}
|
||||||
updated = MODULE.upsert_client(config, MODULE.OPENBAO_CLIENT)
|
updated = MODULE.upsert_client(config, MODULE.OPENBAO_CLIENT)
|
||||||
|
|
|
||||||
|
|
@ -49,8 +49,6 @@ probe_redirect() {
|
||||||
|
|
||||||
probe_redirect "CLI" "http://localhost:8250/oidc/callback"
|
probe_redirect "CLI" "http://localhost:8250/oidc/callback"
|
||||||
probe_redirect "operator-tunneled browser UI netkingdom mount" "http://127.0.0.1:18200/ui/vault/auth/netkingdom/oidc/callback"
|
probe_redirect "operator-tunneled browser UI netkingdom mount" "http://127.0.0.1:18200/ui/vault/auth/netkingdom/oidc/callback"
|
||||||
probe_redirect "browser UI netkingdom mount" "https://bao.coulomb.social/ui/vault/auth/netkingdom/oidc/callback"
|
|
||||||
probe_redirect "browser UI keycape compatibility mount" "https://bao.coulomb.social/ui/vault/auth/keycape/oidc/callback"
|
|
||||||
|
|
||||||
KC_POD=$("$KUBECTL" get pod -n "$NAMESPACE" \
|
KC_POD=$("$KUBECTL" get pod -n "$NAMESPACE" \
|
||||||
-l app.kubernetes.io/name=keycape \
|
-l app.kubernetes.io/name=keycape \
|
||||||
|
|
|
||||||
|
|
@ -188,8 +188,6 @@ required_redirects = {
|
||||||
"http://localhost:8250/oidc/callback",
|
"http://localhost:8250/oidc/callback",
|
||||||
"http://127.0.0.1:8250/oidc/callback",
|
"http://127.0.0.1:8250/oidc/callback",
|
||||||
"http://127.0.0.1:18200/ui/vault/auth/netkingdom/oidc/callback",
|
"http://127.0.0.1:18200/ui/vault/auth/netkingdom/oidc/callback",
|
||||||
"https://bao.coulomb.social/ui/vault/auth/netkingdom/oidc/callback",
|
|
||||||
"https://bao.coulomb.social/ui/vault/auth/keycape/oidc/callback",
|
|
||||||
}
|
}
|
||||||
required_scopes = {"openid", "profile", "email", "groups"}
|
required_scopes = {"openid", "profile", "email", "groups"}
|
||||||
missing_redirects = sorted(required_redirects - set(target.get("redirectUris") or []))
|
missing_redirects = sorted(required_redirects - set(target.get("redirectUris") or []))
|
||||||
|
|
@ -200,6 +198,13 @@ if target.get("clientType") != "public":
|
||||||
if missing_redirects:
|
if missing_redirects:
|
||||||
print("openbao-admin missing redirect URI(s): " + ", ".join(missing_redirects))
|
print("openbao-admin missing redirect URI(s): " + ", ".join(missing_redirects))
|
||||||
raise SystemExit(4)
|
raise SystemExit(4)
|
||||||
|
retired_redirects = sorted({
|
||||||
|
"https://bao.coulomb.social/ui/vault/auth/netkingdom/oidc/callback",
|
||||||
|
"https://bao.coulomb.social/ui/vault/auth/keycape/oidc/callback",
|
||||||
|
} & set(target.get("redirectUris") or []))
|
||||||
|
if retired_redirects:
|
||||||
|
print("openbao-admin still registers retired redirect URI(s): " + ", ".join(retired_redirects))
|
||||||
|
raise SystemExit(6)
|
||||||
if missing_scopes:
|
if missing_scopes:
|
||||||
print("openbao-admin missing scope(s): " + ", ".join(missing_scopes))
|
print("openbao-admin missing scope(s): " + ", ".join(missing_scopes))
|
||||||
raise SystemExit(5)
|
raise SystemExit(5)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue