comms: fix guest registration via MAS admin API
This commit is contained in:
parent
70e40b281f
commit
e44ee3ab2d
@ -14,11 +14,14 @@ data:
|
|||||||
from urllib import error, parse, request
|
from urllib import error, parse, request
|
||||||
|
|
||||||
MAS_BASE = os.environ.get("MAS_BASE", "http://matrix-authentication-service:8080").rstrip("/")
|
MAS_BASE = os.environ.get("MAS_BASE", "http://matrix-authentication-service:8080").rstrip("/")
|
||||||
|
MAS_ADMIN_API_BASE = os.environ.get("MAS_ADMIN_API_BASE", "http://matrix-authentication-service:8081/api/admin/v1").rstrip("/")
|
||||||
|
SYNAPSE_BASE = os.environ.get("SYNAPSE_BASE", "http://othrys-synapse-matrix-synapse:8008").rstrip("/")
|
||||||
SERVER_NAME = os.environ.get("MATRIX_SERVER_NAME", "live.bstein.dev")
|
SERVER_NAME = os.environ.get("MATRIX_SERVER_NAME", "live.bstein.dev")
|
||||||
|
|
||||||
MAS_ADMIN_CLIENT_ID = os.environ["MAS_ADMIN_CLIENT_ID"]
|
MAS_ADMIN_CLIENT_ID = os.environ["MAS_ADMIN_CLIENT_ID"]
|
||||||
MAS_ADMIN_CLIENT_SECRET_FILE = os.environ.get("MAS_ADMIN_CLIENT_SECRET_FILE", "/etc/mas/admin-client/client_secret")
|
MAS_ADMIN_CLIENT_SECRET_FILE = os.environ.get("MAS_ADMIN_CLIENT_SECRET_FILE", "/etc/mas/admin-client/client_secret")
|
||||||
MAS_ADMIN_SCOPE = os.environ.get("MAS_ADMIN_SCOPE", "urn:mas:admin")
|
MAS_ADMIN_SCOPE = os.environ.get("MAS_ADMIN_SCOPE", "urn:mas:admin")
|
||||||
|
SESSION_TTL_SEC = int(os.environ.get("SESSION_TTL_SEC", "43200"))
|
||||||
|
|
||||||
RATE_WINDOW_SEC = int(os.environ.get("RATE_WINDOW_SEC", "60"))
|
RATE_WINDOW_SEC = int(os.environ.get("RATE_WINDOW_SEC", "60"))
|
||||||
RATE_MAX = int(os.environ.get("RATE_MAX", "30"))
|
RATE_MAX = int(os.environ.get("RATE_MAX", "30"))
|
||||||
@ -93,51 +96,52 @@ data:
|
|||||||
_admin_token_at = now
|
_admin_token_at = now
|
||||||
return _admin_token
|
return _admin_token
|
||||||
|
|
||||||
def _gql(admin_token, query, variables):
|
|
||||||
status, payload = _json(
|
|
||||||
"POST",
|
|
||||||
f"{MAS_BASE}/graphql",
|
|
||||||
headers={"Authorization": f"Bearer {admin_token}"},
|
|
||||||
body={"query": query, "variables": variables},
|
|
||||||
timeout=20,
|
|
||||||
)
|
|
||||||
if status != 200:
|
|
||||||
raise RuntimeError("gql_http_failed")
|
|
||||||
if payload.get("errors"):
|
|
||||||
raise RuntimeError("gql_error")
|
|
||||||
return payload.get("data") or {}
|
|
||||||
|
|
||||||
def _generate_localpart():
|
def _generate_localpart():
|
||||||
return "guest-" + secrets.token_hex(6)
|
return "guest-" + secrets.token_hex(6)
|
||||||
|
|
||||||
def _generate_displayname():
|
def _generate_displayname():
|
||||||
return f"{random.choice(ADJ)}-{random.choice(NOUN)}"
|
return f"{random.choice(ADJ)}-{random.choice(NOUN)}"
|
||||||
|
|
||||||
def _add_user(admin_token, username):
|
def _admin_api(admin_token, method, path, body=None):
|
||||||
data = _gql(
|
return _json(
|
||||||
admin_token,
|
method,
|
||||||
"mutation($input:AddUserInput!){addUser(input:$input){status user{id username}}}",
|
f"{MAS_ADMIN_API_BASE}{path}",
|
||||||
{"input": {"username": username, "skipHomeserverCheck": True}},
|
headers={"Authorization": f"Bearer {admin_token}"},
|
||||||
)
|
body=body,
|
||||||
res = data.get("addUser") or {}
|
timeout=20,
|
||||||
status = res.get("status")
|
|
||||||
user = res.get("user") or {}
|
|
||||||
return status, user.get("id"), user.get("username")
|
|
||||||
|
|
||||||
def _set_display_name(admin_token, user_id, displayname):
|
|
||||||
_gql(
|
|
||||||
admin_token,
|
|
||||||
"mutation($input:SetDisplayNameInput!){setDisplayName(input:$input){status}}",
|
|
||||||
{"input": {"userId": user_id, "displayName": displayname}},
|
|
||||||
)
|
)
|
||||||
|
|
||||||
def _create_oauth2_session(admin_token, user_id, scope):
|
def _create_user(admin_token, username):
|
||||||
data = _gql(
|
status, payload = _admin_api(admin_token, "POST", "/users", {"username": username})
|
||||||
|
if status != 201:
|
||||||
|
return status, None
|
||||||
|
user = payload.get("data") or {}
|
||||||
|
return status, user.get("id")
|
||||||
|
|
||||||
|
def _create_session(admin_token, user_id, scope):
|
||||||
|
status, payload = _admin_api(
|
||||||
admin_token,
|
admin_token,
|
||||||
"mutation($input:CreateOAuth2SessionInput!){createOauth2Session(input:$input){accessToken}}",
|
"POST",
|
||||||
{"input": {"userId": user_id, "scope": scope, "permanent": False}},
|
"/personal-sessions",
|
||||||
|
{
|
||||||
|
"actor_user_id": user_id,
|
||||||
|
"human_name": "guest session",
|
||||||
|
"scope": scope,
|
||||||
|
"expires_in": SESSION_TTL_SEC,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
if status != 201:
|
||||||
|
return None
|
||||||
|
return (payload.get("data", {}).get("attributes", {}) or {}).get("access_token")
|
||||||
|
|
||||||
|
def _set_display_name(access_token, user_id, displayname):
|
||||||
|
_json(
|
||||||
|
"PUT",
|
||||||
|
f"{SYNAPSE_BASE}/_matrix/client/v3/profile/{parse.quote(user_id, safe='')}/displayname",
|
||||||
|
headers={"Authorization": f"Bearer {access_token}"},
|
||||||
|
body={"displayname": displayname},
|
||||||
|
timeout=20,
|
||||||
)
|
)
|
||||||
return (data.get("createOauth2Session") or {}).get("accessToken")
|
|
||||||
|
|
||||||
def _rate_check(ip, now):
|
def _rate_check(ip, now):
|
||||||
win, cnt = _rate.get(ip, (now, 0))
|
win, cnt = _rate.get(ip, (now, 0))
|
||||||
@ -216,21 +220,20 @@ data:
|
|||||||
mas_user_id = None
|
mas_user_id = None
|
||||||
for _ in range(5):
|
for _ in range(5):
|
||||||
localpart = _generate_localpart()
|
localpart = _generate_localpart()
|
||||||
status, mas_user_id, _ = _add_user(admin_token, localpart)
|
status, mas_user_id = _create_user(admin_token, localpart)
|
||||||
if status == "ADDED":
|
if status == 201 and mas_user_id:
|
||||||
break
|
break
|
||||||
mas_user_id = None
|
mas_user_id = None
|
||||||
if not mas_user_id or not localpart:
|
if not mas_user_id or not localpart:
|
||||||
raise RuntimeError("add_user_failed")
|
raise RuntimeError("add_user_failed")
|
||||||
|
|
||||||
try:
|
access_token = _create_session(admin_token, mas_user_id, "urn:matrix:client:api:*")
|
||||||
_set_display_name(admin_token, mas_user_id, displayname)
|
|
||||||
except Exception:
|
|
||||||
pass
|
|
||||||
|
|
||||||
access_token = _create_oauth2_session(admin_token, mas_user_id, "urn:matrix:client:api:*")
|
|
||||||
if not access_token:
|
if not access_token:
|
||||||
raise RuntimeError("session_failed")
|
raise RuntimeError("session_failed")
|
||||||
|
try:
|
||||||
|
_set_display_name(access_token, f"@{localpart}:{SERVER_NAME}", displayname)
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
except Exception:
|
except Exception:
|
||||||
return self._send_json(502, {"errcode": "M_UNKNOWN", "error": "guest_provision_failed"})
|
return self._send_json(502, {"errcode": "M_UNKNOWN", "error": "guest_provision_failed"})
|
||||||
|
|
||||||
|
|||||||
@ -13,7 +13,7 @@ spec:
|
|||||||
template:
|
template:
|
||||||
metadata:
|
metadata:
|
||||||
annotations:
|
annotations:
|
||||||
checksum/config: guest-register-proxy-4
|
checksum/config: guest-register-proxy-5
|
||||||
labels:
|
labels:
|
||||||
app.kubernetes.io/name: matrix-guest-register
|
app.kubernetes.io/name: matrix-guest-register
|
||||||
spec:
|
spec:
|
||||||
@ -43,6 +43,12 @@ spec:
|
|||||||
value: 01KDXMVQBQ5JNY6SEJPZW6Z8BM
|
value: 01KDXMVQBQ5JNY6SEJPZW6Z8BM
|
||||||
- name: MAS_ADMIN_CLIENT_SECRET_FILE
|
- name: MAS_ADMIN_CLIENT_SECRET_FILE
|
||||||
value: /etc/mas/admin-client/client_secret
|
value: /etc/mas/admin-client/client_secret
|
||||||
|
- name: MAS_ADMIN_API_BASE
|
||||||
|
value: http://matrix-authentication-service:8081/api/admin/v1
|
||||||
|
- name: SYNAPSE_BASE
|
||||||
|
value: http://othrys-synapse-matrix-synapse:8008
|
||||||
|
- name: SESSION_TTL_SEC
|
||||||
|
value: "43200"
|
||||||
- name: MATRIX_SERVER_NAME
|
- name: MATRIX_SERVER_NAME
|
||||||
value: live.bstein.dev
|
value: live.bstein.dev
|
||||||
- name: RATE_WINDOW_SEC
|
- name: RATE_WINDOW_SEC
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user