# Paramiko and ssh-agent

**URL:** <https://forum.ansible.com/t/paramiko-and-ssh-agent/11910>\
**Category:** Ansible Project\
**Created:** [September 19, 2012, 6:03pm UTC](https://forum.ansible.com/t/paramiko-and-ssh-agent/11910 "2012-09-19T18:03:28Z")\
**Posts on this page:** 11\
**Page:** 1

<div class="post-metadata">

**Author:** ![Aleksej\_Romanov](https://avatars.discourse-cdn.com/v4/letter/a/278dde/32.png) [@Aleksej\_Romanov](https://forum.ansible.com/u/Aleksej_Romanov)\
**Post date:** [September 19, 2012, 6:03pm UTC](https://forum.ansible.com/t/paramiko-and-ssh-agent/11910/1 "2012-09-19T18:03:28Z")

</div>

Hello.

Now Paramiko transport use have the following logic regarding to usage  
of ssh-agent (and default ~/.ssh/id\_{d,r}sa keys):

ssh.connect(self.host, username=user, allow\_agent=True, \  
look\_for\_keys=True\<...\>

So it always uses ssh-agent first, even if password is supplied to  
Ansible with -k option. Also it always tries default SSH keys [1].

This is a problem if ssh-agent stores keys with 'confirmation required'  
mode (keys added with ssh-add -c). Since Ansible connects to target for  
every separate task, ssh-agent asks for confirmation way too much times  
for big playbooks. Despite the fact that authtorization is performed  
with password and ssh-agent is not related at all.

(As a side note, this 'try everything what we can' approach can mask  
errors and does not look like the best way for me even if it would not  
cause troubles)

I thought that it may be reasonable to stop checking default id\_{d,r}sa  
keys if key or password is provided. And if password is provided, then  
also stop to talk with ssh-agent.  
But Paramiko can use 'password' argument to SSHClient.connect() both as  
password to decrypt private key and as password to authenticate with SSH  
server. So it is not clear for Ansible if password provided with -k  
option is intended for authentication via SSH or as passphrase for  
~/.ssh/id\_rsa.

So I'm not sure what can be done here. May be separate options for  
private key password and remote system SSH password, not -k for both?  
Would such patch be useful for anyone and accepted?

I understand that most Ansible users are not affected. But we placed  
Ansible at a central server and allow it to login to our systems by  
means of agent forwarding. And so it is desirable to keep keys with  
'confirmation required' mode. But tons of unneeded requests to ssh-agent  
make Ansible unusable. Paramiko transport is really needed for initial  
setup as native 'ssh' supports only keys, not passwords.

[1]:  
[http://www.lag.net/paramiko/docs/paramiko.SSHClient-class.html#connect](http://www.lag.net/paramiko/docs/paramiko.SSHClient-class.html#connect)

---

<div class="post-metadata">

**Author:** ![Michael\_DeHaan](https://avatars.discourse-cdn.com/v4/letter/m/c4cdca/32.png) [@Michael\_DeHaan](https://forum.ansible.com/u/Michael_DeHaan)\
**Post date:** [September 19, 2012, 6:24pm UTC](https://forum.ansible.com/t/paramiko-and-ssh-agent/11910/2 "2012-09-19T18:24:55Z")

</div>

My suggestion would be just use -c ssh as paramiko is there for ease of initial usage and for older SSH hosts that can't do ControlPersist.

-- Michael

---

<div class="post-metadata">

**Author:** ![Aleksej\_Romanov](https://avatars.discourse-cdn.com/v4/letter/a/278dde/32.png) [@Aleksej\_Romanov](https://forum.ansible.com/u/Aleksej_Romanov)\
**Post date:** [September 19, 2012, 6:42pm UTC](https://forum.ansible.com/t/paramiko-and-ssh-agent/11910/3 "2012-09-19T18:42:21Z")

</div>

Yes, we use -c ssh, but Paramiko is needed for basic host setup  
(includes SSHd configuration and setting authorized\_keys). Native ssh  
does not support password authentication.

By the way, I bet Debian and Red Hat systems without ControlPersist are  
quite usual in bigger companies (where configuration management systems  
are important).

---

<div class="post-metadata">

**Author:** ![Michael\_DeHaan](https://avatars.discourse-cdn.com/v4/letter/m/c4cdca/32.png) [@Michael\_DeHaan](https://forum.ansible.com/u/Michael_DeHaan)\
**Post date:** [September 19, 2012, 7:11pm UTC](https://forum.ansible.com/t/paramiko-and-ssh-agent/11910/4 "2012-09-19T19:11:51Z")

</div>

You can use a newer SSH on the control machine to talk to older RHEL systems, etc.

I don't think we want to change our paramiko connection policy but since modules are pluggable you could easily tweak it and make a variant connection plugin to meet your use case.

-- Michael

---

<div class="post-metadata">

**Author:** ![Michael\_Gliwinski](https://avatars.discourse-cdn.com/v4/letter/m/f0a364/32.png) [@Michael\_Gliwinski](https://forum.ansible.com/u/Michael_Gliwinski)\
**Post date:** [September 21, 2012, 12:20pm UTC](https://forum.ansible.com/t/paramiko-and-ssh-agent/11910/5 "2012-09-21T12:20:27Z")

</div>

> So it always uses ssh-agent first, even if password is supplied to  
> Ansible with -k option. Also it always tries default SSH keys [1].

...

> I thought that it may be reasonable to stop checking default id\_{d,r}sa  
> keys if key or password is provided. And if password is provided, then  
> also stop to talk with ssh-agent.

IIRC, you can `unset SSH_AUTH_SOCK` to prevent it from talking to ssh-agent.

---

<div class="post-metadata">

**Author:** ![Dag\_Wieers](https://avatars.discourse-cdn.com/v4/letter/d/45deac/32.png) [@Dag\_Wieers](https://forum.ansible.com/u/Dag_Wieers)\
**Post date:** [September 24, 2012, 11:28pm UTC](https://forum.ansible.com/t/paramiko-and-ssh-agent/11910/6 "2012-09-24T23:28:41Z")

</div>

For those interested in (or forced to) running Ansible without ControlPersist, paramiko could work a lot better if each Runner task did not spawn a new connection, but connections would be reused and connections idle for a certain idle time would be closed (in fact this would be ControlPersist implemented in Ansible).

It was discussed here:

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[https://github.com/ansible/ansible/issues/987](https://github.com/ansible/ansible/issues/987)

This would speed up Ansible considerably using paramiko. We just need someone with the skills and persistence to implement it 😉

---

<div class="post-metadata">

**Author:** ![Michael\_DeHaan](https://avatars.discourse-cdn.com/v4/letter/m/c4cdca/32.png) [@Michael\_DeHaan](https://forum.ansible.com/u/Michael_DeHaan)\
**Post date:** [September 25, 2012, 1:45am UTC](https://forum.ansible.com/t/paramiko-and-ssh-agent/11910/7 "2012-09-25T01:45:01Z")

</div>

> This would speed up Ansible considerably using paramiko. We just need  
> someone with the skills and persistence to implement it 😉

Yep, the issue/idea queue is quite large at the moment. If someone  
else wants to take a look (preferably someone who has a vested  
interest in using the paramiko connection type over a decent number of  
hosts), that would be welcome.

---

<div class="post-metadata">

**Author:** ![Aleksej\_Romanov](https://avatars.discourse-cdn.com/v4/letter/a/278dde/32.png) [@Aleksej\_Romanov](https://forum.ansible.com/u/Aleksej_Romanov)\
**Post date:** [September 25, 2012, 6:42am UTC](https://forum.ansible.com/t/paramiko-and-ssh-agent/11910/8 "2012-09-25T06:42:41Z")

</div>

We already patched code a bit, but yes, deleting SSH\_AUTH\_SOCK helps  
and would be easier, thank you!

diff --git a/lib/ansible/runner/connection\_plugins/paramiko\_ssh.py b/lib/ansible/runner/connection\_plugins/paramiko\_ssh.py  
index d4083f5..e89c778 100644  
--- a/lib/ansible/runner/connection\_plugins/paramiko\_ssh.py  
+++ b/lib/ansible/runner/connection\_plugins/paramiko\_ssh.py  
@@ -58,8 +58,18 @@ class Connection(object):  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ssh = paramiko.SSHClient()  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ssh.set\_missing\_host\_key\_policy(paramiko.AutoAddPolicy())

+ # If password is given, don't mess with anything else at all  
+ # If private key is explicitly specified, don't try default ~/.ssh/id\_dsa and ~/.ssh/id\_rsa  
+ # Otherwise use Paramiko's default: first try ssh-agent and after that id\_{d,r}sa  
+ allow\_agent = True  
+ look\_for\_keys = True  
+ if not self.runner.remote\_pass is None:  
+ allow\_agent = False  
+ look\_for\_keys = False  
+ elif not self.runner.private\_key\_file is None:  
+ look\_for\_keys = False  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;try:  
- ssh.connect(self.host, username=user, allow\_agent=True, look\_for\_keys=True,  
+ ssh.connect(self.host, username=user, allow\_agent=allow\_agent, look\_for\_keys=look\_for\_keys,  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;key\_filename=self.runner.private\_key\_file, password=self.runner.remote\_pass,  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;timeout=self.runner.timeout, port=self.port)  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;except Exception, e:

---

<div class="post-metadata">

**Author:** ![Michael\_DeHaan](https://avatars.discourse-cdn.com/v4/letter/m/c4cdca/32.png) [@Michael\_DeHaan](https://forum.ansible.com/u/Michael_DeHaan)\
**Post date:** [September 25, 2012, 11:55am UTC](https://forum.ansible.com/t/paramiko-and-ssh-agent/11910/9 "2012-09-25T11:55:28Z")

</div>

Does setting look\_for\_keys=False make it not look for regular SSH  
keys? That seems quite undesirable because while you might not be  
setting a keyfile, you could have keys of your own. This would more  
or less force usage of ssh-agent.

I'm fine with the part that disables the agent if the password is set  
-- send me a pull request.

---

<div class="post-metadata">

**Author:** ![Aleksej\_Romanov](https://avatars.discourse-cdn.com/v4/letter/a/278dde/32.png) [@Aleksej\_Romanov](https://forum.ansible.com/u/Aleksej_Romanov)\
**Post date:** [September 26, 2012, 2:18pm UTC](https://forum.ansible.com/t/paramiko-and-ssh-agent/11910/10 "2012-09-26T14:18:02Z")

</div>

> Does setting look\_for\_keys=False make it not look for regular SSH  
> keys? That seems quite undesirable because while you might not be  
> setting a keyfile, you could have keys of your own. This would more  
> or less force usage of ssh-agent.

This makes Ansible not look for ~/.ssh/id\_dsa and ~/.ssh/id\_rsa if  
private\_key\_file is set. I believe this is correct behaviour: if user  
specified private key, we don't need to try default ones.

---

<div class="post-metadata">

**Author:** ![Michael\_DeHaan](https://avatars.discourse-cdn.com/v4/letter/m/c4cdca/32.png) [@Michael\_DeHaan](https://forum.ansible.com/u/Michael_DeHaan)\
**Post date:** [September 26, 2012, 2:20pm UTC](https://forum.ansible.com/t/paramiko-and-ssh-agent/11910/11 "2012-09-26T14:20:54Z")

</div>

ok, send me a pull request and I can try it.
