Automated Key Distribution
Automated Key Distribution
Manual key distribution doesn't scale and introduces security risks. Automated distribution systems ensure keys reach authorized systems quickly and securely while maintaining audit trails and access controls.
Implement automated key distribution:
#!/bin/bash
# ssh-key-distribution.sh
# Automated SSH key distribution system
# Configuration
DISTRIBUTION_CONFIG="/etc/ssh-distribution/config.json"
ANSIBLE_INVENTORY="/etc/ansible/hosts"
DISTRIBUTION_LOG="/var/log/ssh-key-distribution.log"
# Load distribution rules from configuration
load_distribution_rules() {
if [ ! -f "$DISTRIBUTION_CONFIG" ]; then
cat > "$DISTRIBUTION_CONFIG" << 'EOF'
{
"distribution_rules": [
{
"key_pattern": "dev-*",
"target_groups": ["development_servers"],
"target_users": ["devuser"],
"key_options": "no-port-forwarding,no-X11-forwarding"
},
{
"key_pattern": "prod-*",
"target_groups": ["production_servers"],
"target_users": ["produser"],
"key_options": "from=\"10.0.0.0/8\",no-port-forwarding"
},
{
"key_pattern": "admin-*",
"target_groups": ["all_servers"],
"target_users": ["root", "admin"],
"key_options": ""
}
],
"notification_endpoints": [
"https://slack.webhook.url",
"[email protected]"
]
}
EOF
fi
echo "$DISTRIBUTION_CONFIG"
}
# Distribute key to target systems
distribute_key() {
local key_id=$1
local public_key=$2
local key_options=$3
local target_groups=$4
local target_users=$5
log "Starting distribution of key $key_id"
# Create Ansible playbook for distribution
cat > "/tmp/distribute_key_${key_id}.yml" << EOF
---
- name: Distribute SSH Key ${key_id}
hosts: ${target_groups}
become: yes
tasks:
- name: Ensure .ssh directory exists
file:
path: "/home/{{ item }}/.ssh"
state: directory
owner: "{{ item }}"
group: "{{ item }}"
mode: '0700'
loop: ${target_users}
- name: Add public key to authorized_keys
lineinfile:
path: "/home/{{ item }}/.ssh/authorized_keys"
line: "${key_options} ${public_key} ${key_id}"
create: yes
owner: "{{ item }}"
group: "{{ item }}"
mode: '0600'
loop: ${target_users}
- name: Log key distribution
lineinfile:
path: "/var/log/ssh_keys_distributed.log"
line: "{{ ansible_date_time.iso8601 }} - Added key ${key_id} for users ${target_users}"
create: yes
EOF
# Execute distribution
ansible-playbook -i "$ANSIBLE_INVENTORY" "/tmp/distribute_key_${key_id}.yml" \
--extra-vars "ansible_ssh_private_key_file=/opt/ssh-distribution/deploy_key" \
>> "$DISTRIBUTION_LOG" 2>&1
local result=$?
# Clean up
rm -f "/tmp/distribute_key_${key_id}.yml"
if [ $result -eq 0 ]; then
log "Successfully distributed key $key_id"
send_notification "success" "Key $key_id distributed successfully"
else
log "ERROR: Failed to distribute key $key_id"
send_notification "failure" "Key $key_id distribution failed"
fi
return $result
}
# Remove key from all systems
remove_key_distribution() {
local key_id=$1
log "Removing key $key_id from all systems"
# Create removal playbook
cat > "/tmp/remove_key_${key_id}.yml" << EOF
---
- name: Remove SSH Key ${key_id}
hosts: all
become: yes
tasks:
- name: Find authorized_keys files
find:
paths: ["/home", "/root"]
patterns: "authorized_keys"
recurse: yes
register: auth_keys_files
- name: Remove key from authorized_keys
lineinfile:
path: "{{ item.path }}"
regexp: ".*${key_id}$"
state: absent
loop: "{{ auth_keys_files.files }}"
- name: Log key removal
lineinfile:
path: "/var/log/ssh_keys_removed.log"
line: "{{ ansible_date_time.iso8601 }} - Removed key ${key_id}"
create: yes
EOF
# Execute removal
ansible-playbook -i "$ANSIBLE_INVENTORY" "/tmp/remove_key_${key_id}.yml" \
>> "$DISTRIBUTION_LOG" 2>&1
rm -f "/tmp/remove_key_${key_id}.yml"
log "Key $key_id removed from all systems"
}
# Monitor key distribution health
monitor_distribution_health() {
log "Checking key distribution health..."
# Create health check playbook
cat > "/tmp/key_health_check.yml" << 'EOF'
---
- name: SSH Key Distribution Health Check
hosts: all
become: yes
gather_facts: no
tasks:
- name: Check authorized_keys files
find:
paths: ["/home", "/root"]
patterns: "authorized_keys"
recurse: yes
register: auth_keys_files
- name: Validate authorized_keys permissions
stat:
path: "{{ item.path }}"
loop: "{{ auth_keys_files.files }}"
register: file_stats
- name: Report issues
debug:
msg: "WARNING: {{ item.stat.path }} has incorrect permissions {{ item.stat.mode }}"
when: item.stat.mode != "0600"
loop: "{{ file_stats.results }}"
EOF
# Run health check
ansible-playbook -i "$ANSIBLE_INVENTORY" "/tmp/key_health_check.yml" \
>> "$DISTRIBUTION_LOG" 2>&1
rm -f "/tmp/key_health_check.yml"
}
# Sync keys with identity provider
sync_with_identity_provider() {
log "Syncing SSH keys with identity provider..."
# Example: Sync with LDAP
ldapsearch -x -H ldap://ldap.example.com \
-D "cn=admin,dc=example,dc=com" \
-w "$LDAP_PASSWORD" \
-b "ou=users,dc=example,dc=com" \
"(objectClass=posixAccount)" \
uid sshPublicKey | \
while read -r line; do
if [[ $line =~ ^uid:\ (.+) ]]; then
current_user="${BASH_REMATCH[1]}"
elif [[ $line =~ ^sshPublicKey:\ (.+) ]]; then
ssh_key="${BASH_REMATCH[1]}"
# Distribute key for user
distribute_key "ldap-$current_user" "$ssh_key" "" "all_servers" "[$current_user]"
fi
done
}