Skip to content

Commit 6f3a32b

Browse files
Merge pull request #1305 from nlabriet/sshdriver-credentials
driver/sshdriver: Add credential overriding NetworkService's
2 parents 3b1df77 + 0d8b82b commit 6f3a32b

File tree

2 files changed

+21
-9
lines changed

2 files changed

+21
-9
lines changed

doc/configuration.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1623,6 +1623,8 @@ Arguments:
16231623
explicitly use the SFTP protocol for file transfers instead of scp's default protocol
16241624
- explicit_scp_mode (bool, default=False): if set to True, `put()`, `get()`, and `scp()` will
16251625
explicitly use the SCP protocol for file transfers instead of scp's default protocol
1626+
- username (str, default=username from `NetworkService`): username used by SSH
1627+
- password (str, default=password from `NetworkService`): password used by SSH
16261628

16271629
UBootDriver
16281630
~~~~~~~~~~~

labgrid/driver/sshdriver.py

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -35,19 +35,29 @@ class SSHDriver(CommandMixin, Driver, CommandProtocol, FileTransferProtocol):
3535
connection_timeout = attr.ib(default=float(get_ssh_connect_timeout()), validator=attr.validators.instance_of(float))
3636
explicit_sftp_mode = attr.ib(default=False, validator=attr.validators.instance_of(bool))
3737
explicit_scp_mode = attr.ib(default=False, validator=attr.validators.instance_of(bool))
38+
username = attr.ib(default="", validator=attr.validators.instance_of(str))
39+
password = attr.ib(default="", validator=attr.validators.instance_of(str))
3840

3941
def __attrs_post_init__(self):
4042
super().__attrs_post_init__()
4143
self._keepalive = None
4244

45+
def _get_username(self):
46+
"""Get the username from this class or from NetworkService"""
47+
return self.username or self.networkservice.username
48+
49+
def _get_password(self):
50+
"""Get the password from this class or from NetworkService"""
51+
return self.password or self.networkservice.password
52+
4353
def on_activate(self):
4454
self.ssh_prefix = ["-o", "LogLevel=ERROR"]
4555
if self.keyfile:
4656
keyfile_path = self.keyfile
4757
if self.target.env:
4858
keyfile_path = self.target.env.config.resolve_path(self.keyfile)
4959
self.ssh_prefix += ["-i", keyfile_path ]
50-
if not self.networkservice.password:
60+
if not self._get_password():
5161
self.ssh_prefix += ["-o", "PasswordAuthentication=no"]
5262

5363
self.control = self._start_own_master()
@@ -99,7 +109,7 @@ def _start_own_master_once(self, timeout):
99109
"-o", "ControlPersist=300", "-o",
100110
"UserKnownHostsFile=/dev/null", "-o", "StrictHostKeyChecking=no",
101111
"-o", "ServerAliveInterval=15", "-MN", "-S", control.replace('%', '%%'), "-p",
102-
str(self.networkservice.port), "-l", self.networkservice.username,
112+
str(self.networkservice.port), "-l", self._get_username(),
103113
self.networkservice.address]
104114

105115
# proxy via the exporter if we have an ifname suffix
@@ -119,14 +129,14 @@ def _start_own_master_once(self, timeout):
119129

120130
env = os.environ.copy()
121131
pass_file = ''
122-
if self.networkservice.password:
132+
if self._get_password():
123133
fd, pass_file = tempfile.mkstemp()
124134
os.fchmod(fd, stat.S_IRWXU)
125135
#with openssh>=8.4 SSH_ASKPASS_REQUIRE can be used to force SSH_ASK_PASS
126136
#openssh<8.4 requires the DISPLAY var and a detached process with start_new_session=True
127137
env = {'SSH_ASKPASS': pass_file, 'DISPLAY':'', 'SSH_ASKPASS_REQUIRE':'force'}
128138
with open(fd, 'w') as f:
129-
f.write("#!/bin/sh\necho " + shlex.quote(self.networkservice.password))
139+
f.write("#!/bin/sh\necho " + shlex.quote(self._get_password()))
130140

131141
self.process = subprocess.Popen(args, env=env,
132142
stdout=subprocess.PIPE,
@@ -163,7 +173,7 @@ def _start_own_master_once(self, timeout):
163173
f"Subprocess timed out [{subprocess_timeout}s] while executing {args}",
164174
)
165175
finally:
166-
if self.networkservice.password and os.path.exists(pass_file):
176+
if self._get_password() and os.path.exists(pass_file):
167177
os.remove(pass_file)
168178

169179
if not os.path.exists(control):
@@ -194,7 +204,7 @@ def _run(self, cmd, codec="utf-8", decodeerrors="strict", timeout=None):
194204
raise ExecutionError("Keepalive no longer running")
195205

196206
complete_cmd = ["ssh", "-x", *self.ssh_prefix,
197-
"-p", str(self.networkservice.port), "-l", self.networkservice.username,
207+
"-p", str(self.networkservice.port), "-l", self._get_username(),
198208
self.networkservice.address
199209
] + cmd.split(" ")
200210
self.logger.debug("Sending command: %s", complete_cmd)
@@ -467,7 +477,7 @@ def put(self, filename, remotepath=''):
467477
"-P", str(self.networkservice.port),
468478
"-r",
469479
filename,
470-
f"{self.networkservice.username}@{self.networkservice.address}:{remotepath}"
480+
f"{self._get_username()}@{self.networkservice.address}:{remotepath}"
471481
]
472482

473483
if self.explicit_sftp_mode and self._scp_supports_explicit_sftp_mode():
@@ -496,7 +506,7 @@ def get(self, filename, destination="."):
496506
*self.ssh_prefix,
497507
"-P", str(self.networkservice.port),
498508
"-r",
499-
f"{self.networkservice.username}@{self.networkservice.address}:{filename}",
509+
f"{self._get_username()}@{self.networkservice.address}:{filename}",
500510
destination
501511
]
502512

@@ -520,7 +530,7 @@ def get(self, filename, destination="."):
520530

521531
def _cleanup_own_master(self):
522532
"""Exit the controlmaster and delete the tmpdir"""
523-
complete_cmd = f"ssh -x -o ControlPath={self.control.replace('%', '%%')} -O exit -p {self.networkservice.port} -l {self.networkservice.username} {self.networkservice.address}".split(' ') # pylint: disable=line-too-long
533+
complete_cmd = f"ssh -x -o ControlPath={self.control.replace('%', '%%')} -O exit -p {self.networkservice.port} -l {self._get_username()} {self.networkservice.address}".split(' ') # pylint: disable=line-too-long
524534
res = subprocess.call(
525535
complete_cmd,
526536
stdin=subprocess.DEVNULL,

0 commit comments

Comments
 (0)