Skip to content

Commit 5ad34e5

Browse files
committed
ssh: stabilize SSH MaxSessions read
Mix /etc/sshd/sshd_config and sshd -T to read MaxSessions. Signed-off-by: Andrea Cervesato <andrea.cervesato@suse.com>
1 parent e0ef9f2 commit 5ad34e5

1 file changed

Lines changed: 33 additions & 10 deletions

File tree

libkirk/channels/ssh.py

Lines changed: 33 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import contextlib
1111
import importlib.util
1212
import logging
13+
import re
1314
import time
1415
from typing import Any, Dict, List, Optional
1516

@@ -155,6 +156,37 @@ def _create_command(
155156

156157
return script
157158

159+
async def _read_max_sessions(self) -> int:
160+
"""
161+
Read the SSH MaxSessions value and return it.
162+
"""
163+
max_sessions = 10
164+
165+
# pyrefly: ignore[missing-attribute]
166+
ret = await self._conn.run(
167+
"grep -i '^MaxSessions' /etc/ssh/sshd_config",
168+
timeout=5,
169+
)
170+
if ret.returncode == 0:
171+
match = re.search(r"^MaxSessions (?P<value>\d+)", ret.stdout)
172+
if match:
173+
max_sessions = int(match.group("value"))
174+
return max_sessions
175+
176+
# pyrefly: ignore[missing-attribute]
177+
ret = await self._conn.run(
178+
"sudo sshd -T | grep maxsessions",
179+
timeout=5,
180+
)
181+
if ret.returncode == 0:
182+
match = re.search(r"^maxsessions (?P<value>\d+)", ret.stdout)
183+
if match:
184+
max_sessions = int(match.group("value"))
185+
186+
self._logger.info("Maximum SSH sessions: %d", max_sessions)
187+
188+
return max_sessions
189+
158190
def setup(self, **kwargs: Dict[str, Any]) -> None:
159191
if not importlib.util.find_spec("asyncssh"):
160192
raise CommunicationError("'asyncssh' library is not available")
@@ -226,17 +258,8 @@ async def communicate(self, iobuffer: Optional[IOBuffer] = None) -> None:
226258
known_hosts=self._known_hosts,
227259
)
228260

229-
# pyrefly: ignore[missing-attribute]
230-
# read maximum number of sessions and limit `run_command`
231-
# concurrent calls to that by using a semaphore
232-
ret = await self._conn.run(
233-
r'sed -n "s/^MaxSessions\s*\([[:digit:]]*\)/\1/p" '
234-
"/etc/ssh/sshd_config"
235-
)
236-
237-
max_sessions = ret.stdout or 10
261+
max_sessions = await self._read_max_sessions()
238262

239-
self._logger.info("Maximum SSH sessions: %d", max_sessions)
240263
self._session_sem = asyncio.Semaphore(max_sessions)
241264
except (asyncssh.Error, ConnectionError) as err:
242265
if not self._stop:

0 commit comments

Comments
 (0)