connect fix 3
This commit is contained in:
@ -23,7 +23,12 @@ from app.rbac import user_has_role_for_host
|
||||
from app.recordings.recorder import SessionRecorder
|
||||
from app.security import active_sessions
|
||||
from app.security.audit import write_audit_event
|
||||
from app.ssh_proxy.proxy import HostNotConfiguredError, connect_to_host, load_host
|
||||
from app.ssh_proxy.proxy import (
|
||||
HostNotConfiguredError,
|
||||
PrivateKeyUnusableError,
|
||||
connect_to_host,
|
||||
load_host,
|
||||
)
|
||||
|
||||
logger = logging.getLogger("jumphost.ssh_proxy.ws")
|
||||
router = APIRouter()
|
||||
@ -50,6 +55,10 @@ async def _pump_ssh_to_ws(process: asyncssh.SSHClientProcess, websocket: WebSock
|
||||
async def ssh_terminal(websocket: WebSocket, host_id: int):
|
||||
user = await get_current_user_ws(websocket)
|
||||
if user is None:
|
||||
# Auch die Ablehnungen VOR dem Sitzungsbeginn gehoeren protokolliert:
|
||||
# bisher schloss dieser Pfad das Socket kommentarlos, im
|
||||
# Verbindungslog war der Fehlversuch dadurch unsichtbar.
|
||||
logger.warning("SSH-Verbindung abgelehnt: keine gueltige Sitzung (host_id=%s)", host_id)
|
||||
await websocket.close(code=4401)
|
||||
return
|
||||
|
||||
@ -57,6 +66,10 @@ async def ssh_terminal(websocket: WebSocket, host_id: int):
|
||||
if not user.is_admin and not await user_has_role_for_host(
|
||||
conn, user_id=user.id, host_id=host_id, role_name="ssh_connect"
|
||||
):
|
||||
logger.warning(
|
||||
"SSH-Verbindung abgelehnt: Benutzer %s hat keine Berechtigung 'ssh_connect' fuer Host %s",
|
||||
user.username, host_id,
|
||||
)
|
||||
await websocket.close(code=4403)
|
||||
return
|
||||
|
||||
@ -66,6 +79,7 @@ async def ssh_terminal(websocket: WebSocket, host_id: int):
|
||||
try:
|
||||
host = await load_host(conn, host_id)
|
||||
except HostNotConfiguredError as exc:
|
||||
logger.warning("SSH-Verbindung abgelehnt (host_id=%s): %s", host_id, exc)
|
||||
await websocket.send_json({"type": "error", "message": str(exc)})
|
||||
await websocket.close(code=4404)
|
||||
return
|
||||
@ -125,8 +139,27 @@ async def ssh_terminal(websocket: WebSocket, host_id: int):
|
||||
# Best-Effort-Fehlermeldung an einen ggf. bereits getrennten Client;
|
||||
# der eigentliche Fehler ist bereits oben geloggt (logger.warning).
|
||||
logger.debug("Fehlermeldung konnte nicht mehr an Client gesendet werden", exc_info=True)
|
||||
except HostNotConfiguredError:
|
||||
except PrivateKeyUnusableError as exc:
|
||||
# Der haeufigste Grund, warum eine SSH-Sitzung nie zustande kam: der
|
||||
# hinterlegte Private Key ist passphrasegeschuetzt und die Passphrase
|
||||
# fehlt oder passt nicht. asyncssh wirft dafuer einen KeyImportError
|
||||
# (ein ValueError, KEIN asyncssh.Error), der frueher an allen
|
||||
# Handlern vorbei bis aus der Route hinauslief -- der Browser sah nur
|
||||
# ein wortloses Verbindungsende. Der Text ist bewusst konkret und
|
||||
# nennt die Stelle im Adminbereich, an der es zu beheben ist.
|
||||
logger.warning("SSH-Sitzung %s: Schluessel unbrauchbar: %s", session_id, exc)
|
||||
end_reason = "error"
|
||||
try:
|
||||
await websocket.send_json({"type": "error", "message": str(exc)})
|
||||
except Exception:
|
||||
logger.debug("Fehlermeldung konnte nicht mehr an Client gesendet werden", exc_info=True)
|
||||
except HostNotConfiguredError as exc:
|
||||
logger.warning("SSH-Sitzung %s abgebrochen: %s", session_id, exc)
|
||||
end_reason = "error"
|
||||
try:
|
||||
await websocket.send_json({"type": "error", "message": str(exc)})
|
||||
except Exception:
|
||||
logger.debug("Fehlermeldung konnte nicht mehr an Client gesendet werden", exc_info=True)
|
||||
except asyncio.CancelledError:
|
||||
# Zwangs-Beendigung durch einen Superadmin ueber die Sessionview
|
||||
# (POST /admin/sessions/{id}/terminate, siehe app/security/active_sessions.py).
|
||||
|
||||
Reference in New Issue
Block a user