Skip to content

Instantly share code, notes, and snippets.

@stecman
Last active May 29, 2026 06:51
Show Gist options
  • Select an option

  • Save stecman/0836eaba7a1833028fe6f65e8cb1078b to your computer and use it in GitHub Desktop.

Select an option

Save stecman/0836eaba7a1833028fe6f65e8cb1078b to your computer and use it in GitHub Desktop.
SSH-key based sudo authentication with Ansible

SSH key-based sudo authentication

To run privileged tasks without resorting to passwordless-sudo (NOPASSWD), you can use the libpam ssh_agent_auth module to authenticate based on SSH public keys in a separate authorized keys file.

This module requires SSH connections to be made with the -A command line option, or the ForwardAgent yes config option. You also need a local SSH agent running with the required key added.

I've presented this as an Ansible playbook + variables as it's a useful application and wasn't completely straight forward to get working. There's no requirement to use Ansible though.

Identifying staff on shared accounts

In cases where a shared user account is used, this has the nice benefit of identifying the individual key used to authenticate privileged escalation:

sudo[4624]: pam_ssh_agent_auth: matching key found: file/command /etc/security/sudo_authorized_keys, line 2
sudo[4624]: pam_ssh_agent_auth: Found matching ED25519 key: SHA256:EWdJKhuDw199fJzAJM1Zc5E1PzhW9zHUMyLlTW+zivI
sudo[4624]: pam_ssh_agent_auth: Authenticated: `ubuntu' as `ubuntu' using /etc/security/sudo_authorized_keys

This hash can be mapped back to the public key in your sudo_authorized_keys file using:

$ ssh-keygen -l -f /etc/security/sudo_authorized_keys
256 SHA256:EWdJKhuDw199fJzAJM1Zc5E1PzhW9zHUMyLlTW+zivI john@example.com(ED25519)

Other notes

  • This doesn't bypass the normal sudo prerequisites: a user with the correct key still needs to be in the sudoers file (eg. added to the sudo group)

  • The configuration here tries SSH agent authentication, then falls back to interactive password authentication

  • This doesn't seem to work with hardware-backed ed25519-sk keys at the time of writing (May 2026), but other SSH key types work correctly.

- name: Provision key-based sudo authentication
hosts: all
become: true
tasks:
- name: Create authorized_keys file for sudo authentication
copy:
content: |
{% for user in admin_users %}
# {{ user['username'] }} ({{ user['fullname']}})
{{ user['pubkey_sudo'] }}
{% endfor %}
dest: /etc/security/sudo_authorized_keys
- name: Install PAM ssh-agent auth module
apt:
name:
- libpam-ssh-agent-auth
state: present
- name: Configure PAM to use SSH agent authentication for sudo
lineinfile:
dest: /etc/pam.d/sudo
line: "auth sufficient pam_ssh_agent_auth.so file=/etc/security/sudo_authorized_keys"
regexp: "^auth.*pam_ssh_agent_auth\\.so"
insertbefore: "^@include common-auth"
state: present
create: no
backup: yes
- name: Configure sudo for SSH agent authentication
lineinfile:
dest: /etc/sudoers
regexp: '^Defaults.*SSH_AUTH_SOCK"$'
line: 'Defaults env_keep += "SSH_AUTH_SOCK"'
state: present
create: no
backup: yes
validate: '/usr/sbin/visudo --check -f %s'
# Use SSH agent forwarding to make agent accessible for key-based sudo authentication
ansible_ssh_common_args: -A
# Allow sudo authentication through ssh-agent forwarding to work with --non-interactive flag.
# This isn't needed when using sudo interactively, but Ansible passes "-n" which breaks that.
# The -S option is needed for compatibility with --ask-become-pass/-K for initial deployment.
ansible_become_flags: -S --preserve-env=SSH_AUTH_SOCK
admin_users:
- username: john
fullname: John Good
pubkey_sudo: ssh-ed25519 AAAA...
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment