Fix interactive 2FA
aaronkollasch opened this issue · 2 comments
aaronkollasch commented
Running jupyter-o2 with --2fa
produces the following error:
Connecting to <user>@o2.hms.harvard.edu
RUN: ssh <user>@o2.hms.harvard.edu
Traceback (most recent call last):
File "anaconda/lib/python3.7/site-packages/pexpect/expect.py", line 111, in expect_loop
incoming = spawn.read_nonblocking(spawn.maxread, timeout)
File "anaconda/lib/python3.7/site-packages/pexpect/pty_spawn.py", line 485, in read_nonblocking
return super(spawn, self).read_nonblocking(size)
File "anaconda/lib/python3.7/site-packages/pexpect/spawnbase.py", line 176, in read_nonblocking
raise EOF('End Of File (EOF). Empty string style platform.')
pexpect.exceptions.EOF: End Of File (EOF). Empty string style platform.
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "anaconda/bin/jupyter-o2", line 10, in <module>
sys.exit(main())
File "anaconda/lib/python3.7/site-packages/jupyter_o2/jupyter_o2.py", line 649, in main
jupyter_o2_runner.run()
File "anaconda/lib/python3.7/site-packages/jupyter_o2/jupyter_o2.py", line 348, in run
if self.connect() or self.keep_alive:
File "anaconda/lib/python3.7/site-packages/jupyter_o2/jupyter_o2.py", line 374, in connect
if not self._login_ssh.login_2fa(self.host, self.user, self.__pass, self.codes_2fa):
File "anaconda/lib/python3.7/site-packages/jupyter_o2/jupyter_o2.py", line 84, in login_2fa
self.set_unique_prompt()
File "anaconda/lib/python3.7/site-packages/pexpect/pxssh.py", line 491, in set_unique_prompt
i = self.expect ([TIMEOUT, self.PROMPT], timeout=10)
File "anaconda/lib/python3.7/site-packages/pexpect/spawnbase.py", line 341, in expect
timeout, searchwindowsize, async_)
File "anaconda/lib/python3.7/site-packages/pexpect/spawnbase.py", line 369, in expect_list
return exp.expect_loop(timeout)
File "anaconda/lib/python3.7/site-packages/pexpect/expect.py", line 117, in expect_loop
return self.eof(e)
File "anaconda/lib/python3.7/site-packages/pexpect/expect.py", line 63, in eof
raise EOF(msg)
pexpect.exceptions.EOF: End Of File (EOF). Empty string style platform.
<jupyter_o2.jupyter_o2.CustomSSH object at 0x10749acf8>
command: /usr/bin/ssh
args: ['/usr/bin/ssh', '-o', 'ForwardX11=yes', '-o', 'LocalForward=8887 127.0.0.1:8887', '-o', 'PubkeyAuthentication=no', '-q', '-oRSAAuthentication=no', '-o', 'PubkeyAuthentication=no', '-l', '<user>', 'o2.hms.harvard.edu']
buffer (last 100 chars): b''
before (last 100 chars): b'S passcodes to XXX-XXX-XXXX\r\n\r\nPasscode or option (1-3): \r\nIncorrect passcode. Please try again.\r\n\r\n'
after: <class 'pexpect.exceptions.EOF'>
match: None
match_index: None
exitstatus: None
flag_eof: True
pid: 66259
child_fd: 8
closed: False
timeout: 60
delimiter: <class 'pexpect.exceptions.EOF'>
logfile: None
logfile_read: None
logfile_send: None
maxread: 2000
ignorecase: False
searchwindowsize: None
delaybeforesend: 0.05
delayafterclose: 0.1
delayafterterminate: 0.1
searcher: searcher_re:
0: TIMEOUT
1: re.compile(b'\\[PEXPECT\\][\\$\\#] ')
Cleaning up
Closing login_ssh
aaronkollasch commented
Non-interactive 2FA still works, so the current workaround is to use the arguments --2fa --2fa-code 1
to request Duo pushes automatically.
aaronkollasch commented
While an interactive 2FA prompt may be more versatile for different Duo authentication methods, the current approach (automatically send code 1
) is more convenient as the 2FA dialog does not need to be navigated twice.
It is also more stable as it doesn't require a workaround for pexpect to allow programmatic exit from the interact()
mode.
Thus the interactive mode fix is not a priority.