TorbatYar/scripts/apply_keycloak_token_lifespans_prod.py
Mortezakoohjani 4ae54abb26 Keep accounting sessions alive with Keycloak lifespan and forced token refresh.
Raise realm access/SSO timeouts and stop sending expired JWTs when refresh fails.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-24 16:29:36 +03:30

72 lines
2.8 KiB
Python

"""Apply Keycloak token lifespan patch on production app host."""
from __future__ import annotations
import base64
import sys
from pathlib import Path
import paramiko
ROOT = Path(__file__).resolve().parents[1]
SCRIPT = ROOT / "backend" / "services" / "identity-access" / "scripts" / "patch_keycloak_token_lifespans.py"
APP_HOST = "192.168.10.162"
APP_USER = "morteza"
APP_PASS = "Moli@5404"
REMOTE = "/home/morteza/torbatyar"
def run(client: paramiko.SSHClient, cmd: str, timeout: int = 120) -> tuple[int, str]:
print(">>>", cmd[:200])
_i, o, e = client.exec_command(cmd, timeout=timeout, get_pty=True)
out = o.read().decode("utf-8", "replace") + e.read().decode("utf-8", "replace")
code = o.channel.recv_exit_status()
print(out[-4000:])
return code, out
def main() -> int:
text = SCRIPT.read_text(encoding="utf-8")
b64 = base64.b64encode(text.encode()).decode()
c = paramiko.SSHClient()
c.set_missing_host_key_policy(paramiko.AutoAddPolicy())
c.connect(APP_HOST, username=APP_USER, password=APP_PASS, timeout=30, allow_agent=False, look_for_keys=False)
try:
# Upload script into identity container path via host bind mount
run(
c,
f"mkdir -p {REMOTE}/backend/services/identity-access/scripts && "
f"echo {b64} | base64 -d > {REMOTE}/backend/services/identity-access/scripts/patch_keycloak_token_lifespans.py",
)
# Dry-run via keycloak network from identity container (KEYCLOAK on docker network)
code, _ = run(
c,
"sg docker -c \"docker compose -f /home/morteza/torbatyar/docker-compose.yml exec -T "
"-e KEYCLOAK_SERVER_URL=http://keycloak:8080 "
"-e KEYCLOAK_ADMIN=admin -e KEYCLOAK_ADMIN_PASSWORD=admin "
"identity-access-service python scripts/patch_keycloak_token_lifespans.py\"",
)
# Apply
code, out = run(
c,
"sg docker -c \"docker compose -f /home/morteza/torbatyar/docker-compose.yml exec -T "
"-e KEYCLOAK_SERVER_URL=http://keycloak:8080 "
"-e KEYCLOAK_ADMIN=admin -e KEYCLOAK_ADMIN_PASSWORD=admin "
"identity-access-service python scripts/patch_keycloak_token_lifespans.py --apply\"",
)
if code != 0:
# Fallback: run on host against published 8080
run(
c,
f"cd {REMOTE}/backend/services/identity-access && "
"KEYCLOAK_SERVER_URL=http://127.0.0.1:8080 KEYCLOAK_ADMIN=admin KEYCLOAK_ADMIN_PASSWORD=admin "
"python3 scripts/patch_keycloak_token_lifespans.py --apply",
)
return 0 if "OK realm" in out or code == 0 else 1
finally:
c.close()
if __name__ == "__main__":
raise SystemExit(main())