[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

How to use ssh-agent in windows in python?

On 29May2019 22:37, Fc Zwtyds <fczwtyds at> wrote:
>? 2019-05-27 11:19, Cameron Simpson ??:
>>The output of "ssh-agent -s" is Bourne shell variable assignment 
>>syntax. You need to parse that [...]
>  I want to rewrite the shell script to python script so I have had 
>changed the "ssh-agent -s" to 'ssh-agent cmd' in python script for the 
>consistence on windows.

I'm not sure you need to do that. In fact, I'm fairly sure you don't.

When you run "ssh-agent cmd" the agent starts as before, but instead of 
reporting its communication socket and process id it dispatches command 
and runs for the duration of that command, then exits.

Before ssh-agent dispatches "cmd" (here I mean a generic command, though 
that command might well be "cmd.exe"), it first puts the necessary 
environment variables into the command's environment.

There are two such values: the communication socket and the ssh-agent 
process id. The socket is so that the other ssh commands can talk to it, 
and the process id is so that it can be terminated when no longer 
wanted. For the "ssh-agent cmd" form there's no need to use the process 
id, since ssh-agent itself will exit after "cmd" finishes.

Let's look at what "ssh-agent -s" produces. This is on a UNIX system (my 

  [~]fleet*> ssh-agent -s
  SSH_AUTH_SOCK=/Users/cameron/tmp/ssh-vuvXU6vrCAxz/agent.50746; export SSH_AUTH_SOCK;
  SSH_AGENT_PID=50754; export SSH_AGENT_PID;
  echo Agent pid 50754;

You can see the socket path and the process id there. The paths will be 
a bit different on Windows.

So if I do a process listing (this is a UNIX "ps" command, you will need 
to do the equivalent Windows thing) and search for that process id we 

  [~]fleet*1> ps ax | grep 62928
  62928   ??  Ss     0:00.00 ssh-agent -s
  66204 s027  S+     0:00.00 grep 62928

So there's the ssh-agent process and also the "grep" command itself 
because the process id is present on its command line.

Note that at this point my shell (cmd.exe equivalent in Windows) does 
not know about the new ssh-agent. This is because I haven't put those 
environment values into the shell environment: the output above is just 
written to the display. So when I go:

  [~]fleet*> ssh-add -l

it shows me 4 ssh keys. This is because I already have an agent which 
has some keys loaded. If my shell were talking to the new agent the list 
would be empty. Let's do that.

  [~]fleet*> SSH_AUTH_SOCK=/Users/cameron/tmp/ssh-vuvXU6vrCAxz/agent.50746
  [~]fleet*> SSH_AGENT_PID=50754
  [~]fleet*> export SSH_AUTH_SOCK SSH_AGENT_PID
  [~]fleet*> ssh-add -l
  The agent has no identities.

So now this shell is using the new agent. You see there's no magic here: 
other commands do not know about the agent until we tell then about it 
using these environment variables.

What I was suggesting is that you perform this process from Python, 
which I believe was your original plan.

So let's adapt the the comand you presented below, and also dig into why 
what you've tried hasn't worked. So, your subprocess call:

  import subprocess
  p = subprocess.Popen('cmd', stdin = subprocess.PIPE, stdout = subprocess.PIPE, stderr = subprocess.PIPE, shell = True, universal_newlines = True)
  outinfo, errinfo = p.communicate('ssh-agent cmd\n')
  print('outinfo is \n %s' % stdoutinfo)
  print('errinfo is \n %s' % stderrinfo)

This does the follow things:

1: Start a subprocess running "cmd". You get back a Popen object "p" for 
use with that process.

2: Run p.communicate("ssh-agent cmd\n"). This sends that to the input of 
the "cmd" subprocess and collects the output.

An important thing to know here is the .communicate is a complete 
interaction with the subprocess. The subprocess' _entire_ input is the 
string you've supplied, and the entire output of the subprocess until it 
completes is collected.

So, what's going on is this:

1: start "cmd"
2: send "ssh-agent cmd\n" to it.
3: collect output and wait for it to exit.