reproman icon indicating copy to clipboard operation
reproman copied to clipboard

Make possible to establish ssh sessions via password authentication

Open yarikoptic opened this issue 6 years ago • 8 comments
trafficstars

  • [x] if Fabric could ask for credentials (currently we just blow with PasswordRequiredException) or we would need to catch/ask/provide
  • [ ] establish the controlpath for repeated relogins without authentication

yarikoptic avatar Nov 29 '18 19:11 yarikoptic

here is the helper we have in DataLad https://github.com/datalad/datalad/blob/master/datalad/support/sshconnector.py#L67

yarikoptic avatar Dec 06 '18 19:12 yarikoptic

  • [ ] try Mux-transport-for-client branch of radssh which is now submitted as a PR https://github.com/paramiko/paramiko/pull/1341/files so we could pass controlpath

yarikoptic avatar Dec 13 '18 19:12 yarikoptic

The first go around with using the Mux-transport-for-client paramiko branch showed that the new code only connects to existing ControlMaster proxy connections and does not create them.

It was also found that the code depends on a ControlMaster running at least OpenSSH v7.4. Here is the exception raised when trying to connect to my locally setup control master using the ssh command line tool which has a version of OpenSSH_7.2p2:

Unable to connect to ControlPath '/home/matt/.ssh/ssh-root@localhost:32768' - Mux proxy
request rejected (Requires OpenSSH 7.4 or greater) - got unexpected reply: 0x80000003 
paramiko.Message('\x00\x00\x00\x02\x00\x00\x00\x13unsupported request')

mjtravers avatar Dec 20 '18 19:12 mjtravers

Was able to connect without a password via the ControlMaster process after setting up a openssh-client version >= v7.4 using the multiplexer branch of paramiko

mjtravers avatar Dec 20 '18 22:12 mjtravers

so, that PR relies on this new version in 7.4: https://www.openssh.com/txt/release-7.4

 * ssh(1): Add a proxy multiplexing mode to ssh(1) inspired by the
   version in PuTTY by Simon Tatham. This allows a multiplexing
   client to communicate with the master process using a subset of
   the SSH packet and channels protocol over a Unix-domain socket,
   with the main process acting as a proxy that translates channel
   IDs, etc.  This allows multiplexing mode to run on systems that
   lack file- descriptor passing (used by current multiplexing
   code) and potentially, in conjunction with Unix-domain socket
   forwarding, with the client and multiplexing master process on
   different machines. Multiplexing proxy mode may be invoked using
   "ssh -O proxy ..."

from reading which it suggests that it was added primarily for "systems that lack file- descriptor passing (used by current multiplexing code) "... I wonder which systems those are? ;) anyways -- I think we could be hopeful and look forward. I.e. assume that this support will come in and enable it only in the cases where there is a recent enough openssh. Otherwise - keys/agents and retyping password.

yarikoptic avatar Dec 20 '18 23:12 yarikoptic

On the call yesterday there was mention of keeping the password in memory with something like

diff --git a/reproman/resource/ssh.py b/reproman/resource/ssh.py
index cff875e2a..49134bad5 100644
--- a/reproman/resource/ssh.py
+++ b/reproman/resource/ssh.py
@@ -57,6 +57,8 @@ class SSH(Resource):
     status = attrib()
     _connection = attrib()
 
+    _password = None
+
     def _connection_open(self):
         try:
             self.status = "CONNECTING"
@@ -84,6 +86,9 @@ def connect(self, password=None):
         if self.key_filename:
             key_filename = [self.key_filename]
 
+        if password is None:
+            password = self._password
+
         self._connection = Connection(
             self.host,
             user=self.user,
@@ -117,6 +122,7 @@ def connect(self, password=None):
                 connect_kwargs={'password': password}
             )
             self._connection_open()
+        self._password = password
 
     def create(self):
         """

But playing around with that, I don't think that's a viable approach (at least my simple-minded version above) because you still get hit with repeated password prompts from paramiko.

kyleam avatar Jun 25 '19 19:06 kyleam

Observation: self._password binds to instance (which come and go), what if keep in a dict at class level with hosts as keys?

yarikoptic avatar Jun 25 '19 21:06 yarikoptic

@yarikoptic:

Observation: self._password binds to instance (which come and go), what if keep in a dict at class level with hosts as keys?

My conclusion is based on instrumenting .connect(), and I get prompted (from paramiko, not our code, as I mentioned above) before entering .connect() a second time, so I don't think it matters. But I could of course be missing something, so please feel free to play around with that patch.

kyleam avatar Jun 25 '19 22:06 kyleam