Specifically for use with Ansible, I’m known to recommend adding NOPASSWD: ALL to the sudoers entry and be done with it. No mucking about with sudo passwords (in essence users’ login passwords), no -K option, no passwords in clear-text files because people are unwilling to use Ansible vault, etc. It makes lives easier all around, and yes, I am aware that there are people who get the screaming heebie-jeebies when I say NOPASSWD:. So be it.

There is an alternative to authenticating use of sudo using SSH agent forwarding instead of login passwords. If you’re new to agent forwarding, I recommend you read the Illustrated Guide to SSH Agent Forwarding, which explains the concept and its pitfalls very well.

We’re going to have sudo use PAM (pluggable authentication modules) to ask our remote SSH agent whether we’re permitted to use sudo. Nifty. No passwords will be harmed or transported over the network in doing so.

ssh agent

pam_ssh_agent_auth is a PAM module which permits PAM authentication via a forwarded SSH agent; as such it can be used to provide authentication for anything that supports PAM. This can be used on most Linux variants as well as on FreeBSD. I’ve explictly not linked to the original Sourceforge page as that’s not been maintained in what feels like forever. I’ve had good experience with the version packaged for FreeBSD which has had some patches applied to it.

I install the sudo and pam_ssh_agent_auth packages and configure the former to use the latter by inserting the first line:

$ cat /usr/local/etc/pam.d/sudo
auth     sufficient  pam_ssh_agent_auth.so  file=/etc/security/authorized_keys
auth     include     system
account  include     system
session  required    pam_permit.so
password include     system

I add public keys of users permitted to authenticate to the file I specify in the PAM configuration.

$ cat /etc/security/authorized_keys
ssh-ed25519 AAAAC3Nza[...]D6K1Fvn7EpD0Oz Ansible mgmt at JPM enterprises

In sudoers proper, I configure an environment variable sudo should keep (theoretically not required on newer versions, but that failed for me) and set up users which should be permitted sudo. Note how I change Jane’s entry to no longer have NOPASSWD on it:

Defaults env_keep += "SSH_AUTH_SOCK"
# jane ALL=(ALL) NOPASSWD: ALL
jane ALL=(ALL) ALL

Let’s see if that works:

$ eval $(ssh-agent)
Agent pid 75648
$ ssh-add .ssh/ansibull
Enter passphrase for .ssh/ansibull:
Identity added: .ssh/ansibull (Ansible mgmt at JPM enterprises)
$ ssh -A -l jane 192.168.1.190 sudo id
uid=0(root) gid=0(wheel) groups=0(wheel),5(operator)

That looks good. Recall that -A on our SSH client means agent forwarding, which we can also provide as -o ForwardAgent=true or specify in ssh_config on the client.

Ansible

I mentioned above that sudoers is used by Ansible on platforms which support it. Can we use PAM SSH agent forwarding for authenticating sudo here as well?

I set up my inventory with ansible_become_pass set to any value; Ansible complains about a “Missing sudo password” otherwise. (Why is a different question, and I’ve not found an answer yet.) Note that the password is just a placebo – we won’t use it, and it’s not Jane’s password.

$ cat inventory
[boxes]
alice ansible_host=192.168.1.190

[boxes:vars]
ansible_user=jane
ansible_python_interpreter=/usr/local/bin/python3.8
ansible_ssh_common_args="-o ForwardAgent=true"
ansible_become_pass=001

Let’s try and access the machine alice, and then attempt with “become”:

$ ansible alice -m command -a id
alice | CHANGED | rc=0 >>
uid=1014(jane) gid=1014(jane) groups=1014(jane)

$ ansible alice -b -m command -a id
alice | CHANGED | rc=0 >>
uid=0(root) gid=0(wheel) groups=0(wheel),5(operator)

This works well. If you are like I and want to actually see whether sudo is “phoning home” for asking the agent, launch ssh-agent with the -d option to see it being spoken to by the client on the target host.

I am aware there are people who don’t approve of SSH agent forwarding either. So be it.

Updates

  • Grant reminds me that this also works for su(1); as mentioned above, it will work with any component which supports PAM authentication.

SSH, PAM, and Ansible :: 21 Nov 2021 :: e-mail