Skip to content

Commit ff097c1

Browse files
committed
feat: add support for Ed25519 key authentication in SSHClient.
Adds the ability to authenticate via Ed25519 private key (pkey_path) in SSHClient. The implementation enforces mutual exclusivity between password and key-based authentication (raises ValueError if both are provided). Only Ed25519 keys are supported; invalid key files raise a descriptive ValueError. BREAKING CHANGE: the SSHClient constructor signature has changed — the `pkey_path` parameter was added, and the order of arguments is slightly adjusted.
1 parent 93594f6 commit ff097c1

1 file changed

Lines changed: 17 additions & 4 deletions

File tree

‎src/imgtests/exec/exec.py‎

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -111,22 +111,35 @@ def run_command(
111111

112112

113113
class SSHClient:
114-
__slots__ = ("hostname", "password", "port", "ssh_session", "username")
114+
__slots__ = ("hostname", "password", "pkey", "port", "ssh_session", "username")
115115

116116
def __init__(
117117
self,
118118
hostname: str,
119119
username: str = "root",
120-
password: str | None = None,
121120
port: int = 22,
121+
password: str | None = None,
122+
pkey_path: str | Path | None = None,
122123
) -> None:
124+
if password and pkey_path:
125+
err_message = "Either password or pkey_path must be provided."
126+
raise ValueError(err_message)
127+
123128
self.hostname = hostname
124129
self.username = username
125130
self.password = password
131+
if pkey_path:
132+
try:
133+
self.pkey = paramiko.Ed25519Key.from_private_key_file(pkey_path)
134+
except paramiko.ssh_exception.SSHException as err:
135+
err_msg = f"Invalid private key file '{pkey_path}'. Only supports Ed25519 keys."
136+
raise ValueError(err_msg) from err
137+
else:
138+
self.pkey = None
126139
self.port = port
127140
self.ssh_session = paramiko.Transport((self.hostname, self.port))
128141
logger.info("Connecting to the host '%s'.", self.hostname)
129-
self.ssh_session.connect(username=self.username, password=self.password)
142+
self.ssh_session.connect(username=self.username, password=self.password, pkey=self.pkey)
130143

131144
@staticmethod
132145
def _read_available(
@@ -228,8 +241,8 @@ def build_from_env(
228241
return SSHClient(
229242
env_var_to_type(address_env, str),
230243
env_var_to_type(user_env, str),
231-
env_var_to_type(password_env, str),
232244
env_var_to_type(port_env, int),
245+
env_var_to_type(password_env, str),
233246
)
234247

235248
def close(self) -> None:

0 commit comments

Comments
 (0)