@@ -35,19 +35,29 @@ class SSHDriver(CommandMixin, Driver, CommandProtocol, FileTransferProtocol):
35
35
connection_timeout = attr .ib (default = float (get_ssh_connect_timeout ()), validator = attr .validators .instance_of (float ))
36
36
explicit_sftp_mode = attr .ib (default = False , validator = attr .validators .instance_of (bool ))
37
37
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 ))
38
40
39
41
def __attrs_post_init__ (self ):
40
42
super ().__attrs_post_init__ ()
41
43
self ._keepalive = None
42
44
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
+
43
53
def on_activate (self ):
44
54
self .ssh_prefix = ["-o" , "LogLevel=ERROR" ]
45
55
if self .keyfile :
46
56
keyfile_path = self .keyfile
47
57
if self .target .env :
48
58
keyfile_path = self .target .env .config .resolve_path (self .keyfile )
49
59
self .ssh_prefix += ["-i" , keyfile_path ]
50
- if not self .networkservice . password :
60
+ if not self ._get_password () :
51
61
self .ssh_prefix += ["-o" , "PasswordAuthentication=no" ]
52
62
53
63
self .control = self ._start_own_master ()
@@ -99,7 +109,7 @@ def _start_own_master_once(self, timeout):
99
109
"-o" , "ControlPersist=300" , "-o" ,
100
110
"UserKnownHostsFile=/dev/null" , "-o" , "StrictHostKeyChecking=no" ,
101
111
"-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 () ,
103
113
self .networkservice .address ]
104
114
105
115
# proxy via the exporter if we have an ifname suffix
@@ -119,14 +129,14 @@ def _start_own_master_once(self, timeout):
119
129
120
130
env = os .environ .copy ()
121
131
pass_file = ''
122
- if self .networkservice . password :
132
+ if self ._get_password () :
123
133
fd , pass_file = tempfile .mkstemp ()
124
134
os .fchmod (fd , stat .S_IRWXU )
125
135
#with openssh>=8.4 SSH_ASKPASS_REQUIRE can be used to force SSH_ASK_PASS
126
136
#openssh<8.4 requires the DISPLAY var and a detached process with start_new_session=True
127
137
env = {'SSH_ASKPASS' : pass_file , 'DISPLAY' :'' , 'SSH_ASKPASS_REQUIRE' :'force' }
128
138
with open (fd , 'w' ) as f :
129
- f .write ("#!/bin/sh\n echo " + shlex .quote (self .networkservice . password ))
139
+ f .write ("#!/bin/sh\n echo " + shlex .quote (self ._get_password () ))
130
140
131
141
self .process = subprocess .Popen (args , env = env ,
132
142
stdout = subprocess .PIPE ,
@@ -163,7 +173,7 @@ def _start_own_master_once(self, timeout):
163
173
f"Subprocess timed out [{ subprocess_timeout } s] while executing { args } " ,
164
174
)
165
175
finally :
166
- if self .networkservice . password and os .path .exists (pass_file ):
176
+ if self ._get_password () and os .path .exists (pass_file ):
167
177
os .remove (pass_file )
168
178
169
179
if not os .path .exists (control ):
@@ -194,7 +204,7 @@ def _run(self, cmd, codec="utf-8", decodeerrors="strict", timeout=None):
194
204
raise ExecutionError ("Keepalive no longer running" )
195
205
196
206
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 () ,
198
208
self .networkservice .address
199
209
] + cmd .split (" " )
200
210
self .logger .debug ("Sending command: %s" , complete_cmd )
@@ -467,7 +477,7 @@ def put(self, filename, remotepath=''):
467
477
"-P" , str (self .networkservice .port ),
468
478
"-r" ,
469
479
filename ,
470
- f"{ self .networkservice . username } @{ self .networkservice .address } :{ remotepath } "
480
+ f"{ self ._get_username () } @{ self .networkservice .address } :{ remotepath } "
471
481
]
472
482
473
483
if self .explicit_sftp_mode and self ._scp_supports_explicit_sftp_mode ():
@@ -496,7 +506,7 @@ def get(self, filename, destination="."):
496
506
* self .ssh_prefix ,
497
507
"-P" , str (self .networkservice .port ),
498
508
"-r" ,
499
- f"{ self .networkservice . username } @{ self .networkservice .address } :{ filename } " ,
509
+ f"{ self ._get_username () } @{ self .networkservice .address } :{ filename } " ,
500
510
destination
501
511
]
502
512
@@ -520,7 +530,7 @@ def get(self, filename, destination="."):
520
530
521
531
def _cleanup_own_master (self ):
522
532
"""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
524
534
res = subprocess .call (
525
535
complete_cmd ,
526
536
stdin = subprocess .DEVNULL ,
0 commit comments