zsh-users
 help / color / mirror / code / Atom feed
* Backgrounding part of 'ssh-agent $cmd'
@ 2013-01-16  6:59 Daniel Shahaf
  2013-01-16 17:35 ` Bart Schaefer
  0 siblings, 1 reply; 7+ messages in thread
From: Daniel Shahaf @ 2013-01-16  6:59 UTC (permalink / raw)
  To: zsh-users

tldr: I have a piece of code that prompts for password and then
establishes N ssh connections in the foreground, and I'd like the
SSH connections to be established in the background.

More specifically, my workflow involves establishing several 'ssh -MNf'
connections every morning, and running a command that prompts for
a password:

    foo_ssh_preseed() {
      ssh-agent sh -x -e -c '
        ssh-add ~/.ssh/foo.id_rsa
        for h in host1 host2 host3; do 
          ssh -MNf $h &
        done
        wait
        ssh-add -D'
    }
    foo_main() {
      foo_ssh_preseed # the workaround places an 'if' around this line
      foo_internal    # prompts for password; is interactive/long-running
    }

Right now, what happens is:

   ssh-add prompts for password
   I wait while SSH connections are being established
   foo_internal prompts for password

I can avoid the delay by running foo_ssh_preseed() in a new terminal
emulator tab; or by running it directly in the same tab, ^Zing it, and
then running foo_internal (while foo_ssh_preseed is doing its work).

I'd like to remove the complication of an extra tab or explicit ^Z:
I'd like the workflow to be

    Run foo_main
    Answer ssh-add password prompt
    # No interactive wait at this point.
    Answer the foo_internal password prompt
    (Use foo; the -MNf's will finish in a second or two.)

Thoughts?

Thanks,

Daniel


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Backgrounding part of 'ssh-agent $cmd'
  2013-01-16  6:59 Backgrounding part of 'ssh-agent $cmd' Daniel Shahaf
@ 2013-01-16 17:35 ` Bart Schaefer
  2013-01-18  6:18   ` Daniel Shahaf
  0 siblings, 1 reply; 7+ messages in thread
From: Bart Schaefer @ 2013-01-16 17:35 UTC (permalink / raw)
  To: zsh-users

On Jan 16,  8:59am, Daniel Shahaf wrote:
} Subject: Backgrounding part of 'ssh-agent $cmd'
}
} More specifically, my workflow involves establishing several 'ssh -MNf'
} connections every morning

Are you running this on an Xorg desktop?  Some Xorg distributions set
up ssh-agent directly under the session manager so all applications
on the desktop use the same agent.  Unless you specifically need to
run a separate agent for this, you might check whether one is already
available.  I source a file from my .zlogin that looks like this
(details elided):

  (( SSH_AGENT_PID )) || return 0
  [[ $(ssh-add -L) = *"no identities"* ]] || return 0
  ssh-add ...

The ssh-add command in this setup is clever enough to invoke zenity or
gdialog or the equivalent to pop up a window for the password.  Have
you tried something like

    ssh-add ~/.ssh/foo.id_rsa </dev/null >>& .ssh-add-errors

to see if it finds some other way to prompt you?  If that works, then
you can just background the entire foo_ssh_preseed call, whether or
not you already have an ssh-agent for the desktop session.


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Backgrounding part of 'ssh-agent $cmd'
  2013-01-16 17:35 ` Bart Schaefer
@ 2013-01-18  6:18   ` Daniel Shahaf
  2013-01-18  7:26     ` Bart Schaefer
  0 siblings, 1 reply; 7+ messages in thread
From: Daniel Shahaf @ 2013-01-18  6:18 UTC (permalink / raw)
  To: Bart Schaefer; +Cc: zsh-users

Bart Schaefer wrote on Wed, Jan 16, 2013 at 09:35:14 -0800:
> On Jan 16,  8:59am, Daniel Shahaf wrote:
> } Subject: Backgrounding part of 'ssh-agent $cmd'
> }
> } More specifically, my workflow involves establishing several 'ssh -MNf'
> } connections every morning
> 
> Are you running this on an Xorg desktop?  Some Xorg distributions set
> up ssh-agent directly under the session manager so all applications
> on the desktop use the same agent.  Unless you specifically need to
> run a separate agent for this, you might check whether one is already
> available.

Yes, and yes my distribution sets up a session-global ssh-agent
instance.  Using a separate agent was a means to an end: not having the
ssh keys decrypted in memory whilst the laptop is hibernating.

> I source a file from my .zlogin that looks like this
> (details elided):
> 
>   (( SSH_AGENT_PID )) || return 0
>   [[ $(ssh-add -L) = *"no identities"* ]] || return 0
>   ssh-add ...
> 
> The ssh-add command in this setup is clever enough to invoke zenity or
> gdialog or the equivalent to pop up a window for the password.  Have
> you tried something like
> 
>     ssh-add ~/.ssh/foo.id_rsa </dev/null >>& .ssh-add-errors
> 
> to see if it finds some other way to prompt you?  If that works, then
> you can just background the entire foo_ssh_preseed call, whether or
> not you already have an ssh-agent for the desktop session.

Yes, 'ssh-add ~/.ssh/foo.id_rsa </dev/null' does prompt
me with a GUI window.

> 

So, combining your and Christian's inputs, it appears I have two options:

- Add the key to the global agent at login (or after hibernte), and
  install a suspend- or screensaver- hook that clears the agent.

- Retain my current code, with the following modification:
  * 'ssh-add foo.id_rsa' -> 'ssh-add foo.id_rsa </dev/null'
  * 'foo_ssh_preseed' -> 'foo_ssh_preseed &'

I've tried the second approach and it appears to work as intended: I get
prompted for my SSH password (graphically), then foo_ssh_preseed runs in
the background (dumping stderr to foreground) and foo_main proceeds in
the foreground.

Which is what I was after; thank you.

Thanks also to Christian for the pointers to the suspend- and
screensaver- hooks --- I haven't tried them yet, but they represent
a viable alternative.

Cheers

Daniel


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Backgrounding part of 'ssh-agent $cmd'
  2013-01-18  6:18   ` Daniel Shahaf
@ 2013-01-18  7:26     ` Bart Schaefer
  2013-01-18 14:13       ` Daniel Shahaf
  0 siblings, 1 reply; 7+ messages in thread
From: Bart Schaefer @ 2013-01-18  7:26 UTC (permalink / raw)
  To: zsh-users

I'm glad my suggestion answered your question, but I don't think that I
have solved your actual problem.  Wandering a bit afield of zsh here ...

On Jan 18,  8:18am, Daniel Shahaf wrote:
}
} Yes, and yes my distribution sets up a session-global ssh-agent
} instance.  Using a separate agent was a means to an end: not having the
} ssh keys decrypted in memory whilst the laptop is hibernating.

I'm not sure you've actually accomplished that.  From what you've
described, you're counting on the set of ssh created in foo_ssh_preseed
to exit because the network connections time out while the laptop sleeps?

That means "ssh-add -D" doesn't run until the laptop *wakes up again*
and the "wait" in foo_ssh_preseed returns.  The agent's memory state
is dumped in the hibernate data with the keys still loaded.  Boot from
removable media and that data could be mined.  Am I missing something?

You would need Christian's suspend-hook idea to get "ssh-add -D" to
run before the laptop hibernates.  In which case you might as well
use the session-global agent ...


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Backgrounding part of 'ssh-agent $cmd'
  2013-01-18  7:26     ` Bart Schaefer
@ 2013-01-18 14:13       ` Daniel Shahaf
  2013-01-18 15:35         ` Bart Schaefer
  0 siblings, 1 reply; 7+ messages in thread
From: Daniel Shahaf @ 2013-01-18 14:13 UTC (permalink / raw)
  To: Bart Schaefer; +Cc: zsh-users

Bart Schaefer wrote on Thu, Jan 17, 2013 at 23:26:02 -0800:
> I'm glad my suggestion answered your question, but I don't think that I
> have solved your actual problem.  Wandering a bit afield of zsh here ...
> 

The part that I find less than ideal so far is that, under load, the GUI
ssh-askpass dialog appears after foo_main has started.  It's a problem,
not because of the ordering (it's not a problem even to run
foo_ssh_preseed only after foo_main has started), but because my "enter
ssh pw, enter foo_main pw" muscle memory gets bypassed.

> On Jan 18,  8:18am, Daniel Shahaf wrote:
> }
> } Yes, and yes my distribution sets up a session-global ssh-agent
> } instance.  Using a separate agent was a means to an end: not having the
> } ssh keys decrypted in memory whilst the laptop is hibernating.
> 
> I'm not sure you've actually accomplished that.  From what you've
> described, you're counting on the set of ssh created in foo_ssh_preseed
> to exit because the network connections time out while the laptop sleeps?
> 

Indeed.

> That means "ssh-add -D" doesn't run until the laptop *wakes up again*
> and the "wait" in foo_ssh_preseed returns.  The agent's memory state
> is dumped in the hibernate data with the keys still loaded.  Boot from
> removable media and that data could be mined.  Am I missing something?
> 

'ssh -MNf' daemonizes itself, so foo_ssh_preseed takes about 5 seconds
from start to finish.

<OT>The daemons open and keep open SSH TCP connections, so that subsequent
interactive 'ssh host1' commands don't need to do the TCP handshake and
SSH authentication handshake --- which speeds them up.  This relies on
ControlPath (and maybe ServerAliveInterval) being set in ~/.ssh/config.</OT>

I'd tell you exactly how long foo_ssh_preseed takes, but time(1zsh)
doesn't work on functions:

% zsh -fc 'time () { sleep 1 } ' 
% zsh -fc 'f(){ sleep 1 } ; time f'  

> You would need Christian's suspend-hook idea to get "ssh-add -D" to
> run before the laptop hibernates.  In which case you might as well
> use the session-global agent ...

Thanks,

Daniel


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Backgrounding part of 'ssh-agent $cmd'
  2013-01-18 14:13       ` Daniel Shahaf
@ 2013-01-18 15:35         ` Bart Schaefer
  2013-01-21  3:58           ` Daniel Shahaf
  0 siblings, 1 reply; 7+ messages in thread
From: Bart Schaefer @ 2013-01-18 15:35 UTC (permalink / raw)
  To: zsh-users

On Jan 18,  4:13pm, Daniel Shahaf wrote:
>
> The part that I find less than ideal so far is that, under load, the GUI
> ssh-askpass dialog appears after foo_main has started.

You could do it like this:

  ( # Subshell so caller's environment won't be changed; could instead
    # declare locals, but this is immune to changes in ssh-agent
    eval `ssh-agent`
    ssh-add ~/.ssh/foo.id_rsa
    {
      for h in host1 host2 host3; do 
        ssh -MNf $h &
      done
      wait
    } always {
      ssh-agent -k
    } &
  )

Then you don't have to background foo_ssh_preseed, and your preferred
order of events is retained.

> > Am I missing something?
> 
> 'ssh -MNf' daemonizes itself

Ah, of course.


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Backgrounding part of 'ssh-agent $cmd'
  2013-01-18 15:35         ` Bart Schaefer
@ 2013-01-21  3:58           ` Daniel Shahaf
  0 siblings, 0 replies; 7+ messages in thread
From: Daniel Shahaf @ 2013-01-21  3:58 UTC (permalink / raw)
  To: Bart Schaefer; +Cc: zsh-users

Bart Schaefer wrote on Fri, Jan 18, 2013 at 07:35:22 -0800:
> On Jan 18,  4:13pm, Daniel Shahaf wrote:
> >
> > The part that I find less than ideal so far is that, under load, the GUI
> > ssh-askpass dialog appears after foo_main has started.
> 
> You could do it like this:
> 
>   ( # Subshell so caller's environment won't be changed; could instead
>     # declare locals, but this is immune to changes in ssh-agent
>     eval `ssh-agent`
>     ssh-add ~/.ssh/foo.id_rsa
>     {
>       for h in host1 host2 host3; do 
>         ssh -MNf $h &
>       done
>       wait
>     } always {
>       ssh-agent -k
>     } &
>   )
> 
> Then you don't have to background foo_ssh_preseed, and your preferred
> order of events is retained.

Thanks!  This makes the ssh prompt textual again, while keeping the loop
backgrounded; that's perfect.

To summarise, now I have:

foo_ssh_preseed() {
  if [ -S ~/.ssh/ControlPath/host1 ]
  then
    return
  fi
  zsh -fc '
    # Subshell so caller"s environment won"t be changed; could instead
    # declare locals, but this is immune to changes in ssh-agent
    eval `ssh-agent | tee /dev/stderr`
    ssh-add ~/.ssh/foo.id_rsa
    {
      for h in \
          host1 host2 host3 \
      ; do 
        ssh -MNf $h &
      done
      wait
    } always {
      ssh-agent -k
    } &
  '
}

Which relies on ControlPath,ServerAliveInterval,IdentityFile being set
in ~/.ssh/config.

I also had the subshell use -f --- mainly because I didn't know of
anything else in my configuration would interfere with the always{}
block, but upon review I notice it has the side-effect of making the
enclosing function a valid /bin/sh function.

Thanks again.

Daniel


^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2013-01-21  3:58 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-01-16  6:59 Backgrounding part of 'ssh-agent $cmd' Daniel Shahaf
2013-01-16 17:35 ` Bart Schaefer
2013-01-18  6:18   ` Daniel Shahaf
2013-01-18  7:26     ` Bart Schaefer
2013-01-18 14:13       ` Daniel Shahaf
2013-01-18 15:35         ` Bart Schaefer
2013-01-21  3:58           ` Daniel Shahaf

Code repositories for project(s) associated with this public inbox

	https://git.vuxu.org/mirror/zsh/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).