Distributing SSH Keys with Ansible

This method is designed to fully take over the distribution of SSH Keys, meaning if you use this method you, or individual users, can no longer manually add their own keys to the systems.

./roles/ssh-keys/tasks/main.yml:

---
- name: Making sure .ssh directories exists
  ansible.builtin.file:
    path: /root/.ssh/
    state: directory
    mode: '0700'

- name: Distributing admin-ssh-keys, /root/.ssh/authorized_keys
  template:
    src: authorized_keys
    dest: /root/.ssh/authorized_keys
    mode: 0700
  vars:
    username: root

- name: Making sure .ssh directories exists for users
  ansible.builtin.file:
    path: /home/{{ item.username }}/.ssh
    state: directory
    mode: '0700'
  loop: "{{ sshkeys | json_query(_query) | flatten | unique }}"
  when: item.username != "root" and item.hostname == ansible_fqdn
  vars:
    _query: "[].hosts"


- name: Distributing user-ssh-keys
  template:
    src: authorized_keys
    dest: /home/{{ item.username }}/.ssh/authorized_keys
    mode: 0700
  loop: "{{ sshkeys | json_query(_query) | flatten | unique }}"
  when: item.username != "root" and item.hostname == ansible_fqdn
  vars:
    _query: "[].hosts"
    username: "{{item.username}}"

- name: Fetching
  getent:
    database: passwd

- name: Building lookup table
  set_fact:
    managedkeys: "{{ managedkeys | default({}) | combine( {item.hostname: [item.username]} , list_merge='append') }}"
  loop: "{{ sshkeys | json_query(_query) | flatten | unique }}"
  when: item.username != "root" #and item.hostname == ansible_fqdn
  vars:
    managedkeys: {}
    _query: "[].hosts"

- name: Removing un-managed authorized_keys
  debug:
    msg: User {{ item }} found
  loop: "{{ getent_passwd.keys()|list }}"
  when: item not in managedkeys[ansible_fqdn] and item != "root"

- name: Removing un-managed (all) authorized_keys2
  file:
    path: ~{{item}}/.ssh/authorized_keys2
    state: absent
  loop: "{{ getent_passwd.keys()|list }}"

./roles/ssh-keys/tasks/authorized_keys

# This file is maintained by Ansible, changes will be automatically overwritten
# Username: {{username}}
{%- for sshkey in sshkeys -%}
        {%- if sshkey.admin is defined and sshkey.admin and username == "root" %}


# {{sshkey.owner}}
{{sshkey["key"]}}
        {%- else -%}
                {%- if sshkey["hosts"] is defined -%}
                        {%- for host in sshkey.hosts -%}
                                {%- if ansible_fqdn == host.hostname and username == host.username %}


# {{sshkey.owner}}
ZZZ {{sshkey["key"]}}
                                {%- endif -%}
                        {%- endfor -%}
                {%- endif -%}
        {%- endif -%}
{%- endfor %}


# This file is maintained by Ansible, changes will be automatically overwritten

And finally ./roles/ssh-keys/vars/main.yaml

sshkeys:
  - owner: Firstname Lastname
    admin: true
    key: ssh-rsa AAAA.....PQZ firstname@laptop

  - owner: Another firstname another lastname
    admin: true
    key: ssh-rsa AAAA.....QJE another@workstation

  - owner: Automated backup
    key: ssh-rsa AAAA.....EMT backup@backupcluster
    hosts:
      - hostname: targetsystem.mydomain.com
        username: backup
      - hostname: targetsystem.mydomain.com
        username: mysql
      - hostname: anothertarget.mydomain.com
        username: backup

This will install Firstnames and Another firstnames ssh keys on the root account on all servers targeted with this task, and the automated backup key on targetsystem user backup and mysql and finally on anothertarget user backup.

Every other key on the system will be deleted every time this script is being run, it checks every .ssh folder in every homedir for authorized_keys and authorized_keys2 files and deletes them, unless the homedir belongs to one of the above users. Authorized_keys2 er always deleted since we don’t use them.

If you don’t want this functionality you can remove either both or one of the last blocks in the tasks/main.yaml

Dette indlæg blev udgivet i Ansible, Linux. Bogmærk permalinket.