fix(backend): non-login SSH and strict loginctl parse, SSH retry (0.20.31)
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -35,6 +35,21 @@ SESSION_EVENT_TYPES_LINUX = frozenset(
|
||||
)
|
||||
SESSION_EVENT_TYPES_WINDOWS = frozenset({"rdp.login.success"})
|
||||
|
||||
_LOGIND_SESSION_ID_RE = re.compile(r"^\d+$|^c\d+$", re.IGNORECASE)
|
||||
_LOGIND_USER_RE = re.compile(r"^[a-z_][a-z0-9._-]*$", re.IGNORECASE)
|
||||
_LOGIND_STATES = frozenset(
|
||||
{
|
||||
"active",
|
||||
"online",
|
||||
"closing",
|
||||
"opening",
|
||||
"degraded",
|
||||
"lingering",
|
||||
"preparing",
|
||||
"unknown",
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class HostSessionRow:
|
||||
@@ -78,14 +93,27 @@ def is_windows_host_event(event: Event) -> bool:
|
||||
return host is not None and is_windows_host(host)
|
||||
|
||||
|
||||
def _looks_like_loginctl_row(parts: list[str]) -> bool:
|
||||
if len(parts) < 6:
|
||||
return False
|
||||
sid, uid, user, state = parts[0], parts[1], parts[2], parts[5].lower()
|
||||
if not _LOGIND_SESSION_ID_RE.match(sid):
|
||||
return False
|
||||
if not uid.isdigit():
|
||||
return False
|
||||
if not _LOGIND_USER_RE.match(user):
|
||||
return False
|
||||
return state in _LOGIND_STATES
|
||||
|
||||
|
||||
def parse_loginctl_sessions(stdout: str) -> list[HostSessionRow]:
|
||||
rows: list[HostSessionRow] = []
|
||||
for line in stdout.splitlines():
|
||||
text = line.strip()
|
||||
if not text:
|
||||
if not text or text.startswith("SESSION"):
|
||||
continue
|
||||
parts = text.split()
|
||||
if len(parts) < 3:
|
||||
if not _looks_like_loginctl_row(parts):
|
||||
continue
|
||||
sid, user = parts[0], parts[2]
|
||||
tty = parts[4] if len(parts) > 4 and parts[4] != "-" else None
|
||||
@@ -143,7 +171,7 @@ def list_linux_sessions(host: Host, cfg: LinuxAdminConfig) -> tuple[list[HostSes
|
||||
if not is_linux_host(host):
|
||||
raise SshHostNotLinuxError("Host is not Linux")
|
||||
targets = iter_ssh_targets(host)
|
||||
cmd = "loginctl list-sessions --no-legend --no-pager 2>/dev/null || who -u"
|
||||
cmd = "loginctl list-sessions --no-legend --no-pager"
|
||||
last: SshCommandResult | None = None
|
||||
for target in targets:
|
||||
result = run_ssh_command(
|
||||
@@ -154,6 +182,7 @@ def list_linux_sessions(host: Host, cfg: LinuxAdminConfig) -> tuple[list[HostSes
|
||||
connect_timeout_sec=15,
|
||||
command_timeout_sec=45,
|
||||
need_root=True,
|
||||
login_shell=False,
|
||||
)
|
||||
last = result
|
||||
if result.ok and result.stdout.strip():
|
||||
@@ -184,6 +213,7 @@ def terminate_linux_session(
|
||||
connect_timeout_sec=15,
|
||||
command_timeout_sec=45,
|
||||
need_root=True,
|
||||
login_shell=False,
|
||||
)
|
||||
last = result
|
||||
if result.ok:
|
||||
@@ -286,6 +316,7 @@ def _terminate_linux_user_sessions(host: Host, cfg: LinuxAdminConfig, user: str)
|
||||
connect_timeout_sec=15,
|
||||
command_timeout_sec=45,
|
||||
need_root=True,
|
||||
login_shell=False,
|
||||
)
|
||||
last = result
|
||||
if result.ok:
|
||||
|
||||
Reference in New Issue
Block a user