portal: request keycloak rotation on vaultwarden confirm

This commit is contained in:
Brad Stein 2026-01-23 00:35:27 -03:00
parent 944cb24538
commit 8a3377959c
5 changed files with 36 additions and 0 deletions

View File

@ -257,6 +257,36 @@ def _password_rotation_requested(conn, request_code: str) -> bool:
return bool(row) return bool(row)
def _request_keycloak_password_rotation(conn, request_code: str, username: str) -> None:
if not username:
raise ValueError("username missing")
if not admin_client().ready():
raise RuntimeError("keycloak admin unavailable")
user = admin_client().find_user(username) or {}
user_id = user.get("id") if isinstance(user, dict) else None
if not isinstance(user_id, str) or not user_id:
raise RuntimeError("keycloak user not found")
full = admin_client().get_user(user_id)
actions = full.get("requiredActions")
actions_list: list[str] = []
if isinstance(actions, list):
actions_list = [a for a in actions if isinstance(a, str)]
if "UPDATE_PASSWORD" not in actions_list:
actions_list.append("UPDATE_PASSWORD")
admin_client().update_user_safe(user_id, {"requiredActions": actions_list})
conn.execute(
"""
INSERT INTO access_request_onboarding_artifacts (request_code, artifact, value_hash)
VALUES (%s, %s, NOW()::text)
ON CONFLICT (request_code, artifact) DO NOTHING
""",
(request_code, _KEYCLOAK_PASSWORD_ROTATION_REQUESTED_ARTIFACT),
)
def _extract_attr(attrs: Any, key: str) -> str: def _extract_attr(attrs: Any, key: str) -> str:
if not isinstance(attrs, dict): if not isinstance(attrs, dict):
return "" return ""
@ -940,6 +970,12 @@ def register(app) -> None:
missing = sorted(prerequisites - current_completed) missing = sorted(prerequisites - current_completed)
if missing: if missing:
return jsonify({"error": "step is blocked", "blocked_by": missing}), 409 return jsonify({"error": "step is blocked", "blocked_by": missing}), 409
if step == "vaultwarden_master_password":
try:
_request_keycloak_password_rotation(conn, code, row.get("username") or "")
except Exception:
return jsonify({"error": "failed to request keycloak password rotation"}), 502
conn.execute( conn.execute(
""" """
INSERT INTO access_request_onboarding_steps (request_code, step) INSERT INTO access_request_onboarding_steps (request_code, step)

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 958 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 61 KiB