When managing multiple servers across teams, SSH public key authentication solves password fatigue but introduces new administrative overhead. Traditional authorized_keys
editing becomes unsustainable at scale:
# Problematic manual approach
ssh admin@server1 "echo 'ssh-rsa AAAAB3Nza... user1@pc' >> ~/.ssh/authorized_keys"
ssh admin@server2 "echo 'ssh-rsa AAAAB3Nza... user1@pc' >> ~/.ssh/authorized_keys"
# Repeat for N servers and M users...
Modern tooling provides three architectural approaches:
1. Configuration Management Integration
Ansible's authorized_key
module enables declarative management:
# ansible/playbooks/ssh_keys.yml
- hosts: all_servers
tasks:
- name: Add developer keys
ansible.posix.authorized_key:
user: "{{ deploy_user }}"
state: present
key: "{{ lookup('file', 'keys/{{ user }}.pub') }}"
when: "'developers' in group_names"
2. Dedicated SSH Key Distribution Tools
Open-source solutions like ssh-cert-authority
provide RBAC capabilities:
# Generate time-bound certificates
ssh-cert-authority -b 30d -n dev_team user1.pub
# Outputs signed certificate valid for 30 days
3. Cloud-Native IAM Bridges
AWS EC2 Instance Connect demonstrates cloud provider integrations:
# Push temporary key via AWS CLI
aws ec2-instance-connect send-ssh-public-key \
--instance-id i-1234567890 \
--availability-zone us-west-2a \
--instance-os-user ec2-user \
--ssh-public-key file://my_key.pub
Implementing periodic key rotation prevents stale credentials:
#!/bin/bash
# Monthly key rotation script
for user in $(getent passwd | grep '/home' | cut -d: -f1); do
rotate_key "$user" --expiry 30 --notify-email "$user@company.com"
done
Centralized logging with fail2ban enhances security:
# /etc/fail2ban/jail.d/ssh.conf
[sshd]
enabled = true
maxretry = 3
findtime = 1h
bantime = 1d
logpath = /var/log/ssh_keys_audit.log
Managing SSH public keys across multiple systems with rotating team members creates significant operational overhead. Consider these common scenarios:
- New team members require access to 15+ servers
- Compromised keys need immediate revocation across all environments
- Role changes demand granular permission updates
1. Ansible with Vault:
# ansible/playbooks/ssh_keys.yml
- hosts: all_servers
vars_files:
- vault/keys.yml
tasks:
- name: Deploy authorized_keys
ansible.posix.authorized_key:
user: "{{ deploy_user }}"
state: present
key: "{{ item }}"
with_items: "{{ ssh_keys }}"
2. Puppet SSH Module:
# puppet/manifests/ssh_keys.pp
class ssh_keys {
ssh_authorized_key { 'dev1@company':
user => 'deploy',
type => 'ssh-rsa',
key => 'AAAAB3Nza...',
}
}
AWS Systems Manager example for EC2 instances:
# AWS CLI command
aws ssm send-command \
--document-name "AWS-RunShellScript" \
--parameters 'commands=["echo ssh-rsa AAAAB3... >> ~/.ssh/authorized_keys"]' \
--instance-ids i-1234567890abcdef0
Python script with parallel execution:
import paramiko
from concurrent.futures import ThreadPoolExecutor
def update_key(host):
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(host, username='keyupdater')
with open('authorized_keys', 'r') as f:
key_content = f.read()
sftp = ssh.open_sftp()
with sftp.file('/home/user/.ssh/authorized_keys', 'w') as f:
f.write(key_content)
ssh.close()
hosts = ['server1', 'server2', 'server3']
with ThreadPoolExecutor(max_workers=10) as executor:
executor.map(update_key, hosts)
- Implement key expiration policies
- Use certificate-based SSH when possible
- Audit logs for all key modifications
- Enforce MFA for key rotation procedures