
Mastering SSH Key Management with the Ansible Authorized Key Module
Managing SSH access across a fleet of servers can quickly become a complex and error-prone task. Manually copying public keys, ensuring the correct permissions, and revoking access for departing team members is not just tedious—it’s a security risk. This is where Ansible, and specifically its powerful authorized_key
module, comes into play, transforming a manual chore into a reliable, automated process.
This guide will walk you through how to use the Ansible authorized_key
module to securely and efficiently manage SSH keys on your remote systems.
Why Automate SSH Key Management?
Before diving into the technical details, it’s important to understand the benefits of automating this process:
- Enhanced Security: Automation eliminates the inconsistencies and human errors that can lead to security vulnerabilities. You can enforce a single, authoritative source for who has access.
- Scalability: Whether you’re managing five servers or five thousand, an Ansible playbook scales effortlessly. Adding or removing a user’s access across the entire infrastructure takes seconds.
- Consistency: Every server will have the exact same configuration. You can be confident that the
authorized_keys
file on every machine is correct and hasn’t been manually altered. - Auditing and Compliance: An automated playbook serves as documentation. It’s easy to see exactly who should have access, making security audits straightforward.
Getting Started: How to Add an SSH Key with Ansible
The most common task is adding a user’s public SSH key to a remote server to grant them access. The authorized_key
module makes this incredibly simple.
Let’s assume you have a user’s public key file (e.g., jane_doe.pub
) on your Ansible control node. The playbook to distribute this key to a user named jane
on all your web servers would look like this:
---
- name: Manage SSH Keys for Web Servers
hosts: webservers
become: true
tasks:
- name: Add Jane Doe's SSH public key
ansible.posix.authorized_key:
user: jane
state: present
key: "{{ lookup('file', 'keys/jane_doe.pub') }}"
Let’s break down the key parameters:
user: jane
: This specifies the user account on the remote server whose.ssh/authorized_keys
file will be managed.state: present
: This ensures the key exists in the file. If it’s not there, Ansible will add it. If it’s already present, Ansible will do nothing, making the operation idempotent.key: "{{ lookup('file', 'keys/jane_doe.pub') }}"
: This is the core of the operation. Thelookup
function reads the content of the specified public key file from your control node and passes it to the module. This is the recommended way to handle keys, as it avoids pasting long key strings directly into your playbook.
How to Remove an SSH Key
When a user’s access needs to be revoked, you simply need to change the state. Modifying the previous playbook to remove the key is as easy as changing one word.
---
- name: Revoke SSH Access
hosts: webservers
become: true
tasks:
- name: Remove Jane Doe's SSH public key
ansible.posix.authorized_key:
user: jane
state: absent
key: "{{ lookup('file', 'keys/jane_doe.pub') }}"
By changing the state to state: absent
, Ansible will ensure the key is removed from the jane
user’s authorized_keys
file on all targeted hosts.
Enforcing Exclusive Access for Ultimate Control
What if you want to ensure that only a specific list of keys exists on a server, and no others? This is crucial for high-security environments where you need to guarantee that no unauthorized keys have been manually added.
For this, the exclusive
parameter is your most powerful tool.
When you set exclusive: yes
, the module will remove any keys in the user’s authorized_keys
file that are not explicitly defined in your playbook task.
Warning: This is a powerful feature. If used incorrectly, you could accidentally lock legitimate users out of a system. Use it with a clear and definitive list of keys.
Here is an example of managing a definitive list of keys for the admin
user:
---
- name: Enforce Strict SSH Key Policy for Admin User
hosts: all
become: true
vars:
admin_keys:
- "ssh-rsa AAAA... [email protected]"
- "ssh-ed25519 BBBB... [email protected]"
tasks:
- name: Manage admin user's authorized keys exclusively
ansible.posix.authorized_key:
user: admin
state: present
key: "{{ item }}"
exclusive: yes
with_items: "{{ admin_keys }}"
In this playbook:
- We define a list of approved keys in the
admin_keys
variable. - The task loops through this list using
with_items
. exclusive: yes
tells Ansible to first remove all existing keys from theadmin
user’s file and then add only the keys specified inadmin_keys
.
Security Tips and Best Practices
To make your SSH key management even more robust, consider these tips:
- Restrict Keys by Source IP: You can add extra security by using the
key_options
parameter. This allows you to prepend options to the key in theauthorized_keys
file, such as restricting where a user can log in from.
“`yaml- name: Add a key restricted to a specific IP
ansible.posix.authorizedkey:
user: dev
state: present
key: “{{ lookup(‘file’, ‘keys/dev.pub’) }}”
keyoptions: ‘from=”10.20.30.40″‘
“`
- name: Add a key restricted to a specific IP
- Principle of Least Privilege: Only grant SSH access to users who absolutely need it. Use separate, non-privileged user accounts for application services and daily tasks.
- Use Ansible Vault for Variables: If you store keys as variables instead of files, protect them using Ansible Vault to keep them encrypted at rest.
- Regularly Audit Your Playbooks: Your Ansible playbooks are your source of truth. Regularly review who is in your key lists to ensure access policies are up-to-date.
By leveraging the ansible.posix.authorized_key
module, you can build a secure, scalable, and fully automated system for managing SSH access across your entire infrastructure.
Source: https://centlinux.com/ansible-posix-authorized-key/