Score:2

How to add ssh keys via Ansible when AuthorizedKeysFile is set?

br flag

How can I get Ansible to populate the correct file when my /etc/ssh/sshd_config has AuthorizedKeysFile set to /etc/ssh/authorized_keys/%u? Ansible seems to ignore the setting and places keys in $HOME/.ssh/authorized_keys

playbook:

---
- hosts: all
  vars:
  vars_files:
    - ../group_vars/ssh_root_authorized_keys.yml
  gather_facts: false

  tasks:
    - name: Set up multiple authorized keys
      authorized_key:
        user: root
        state: present
        key: '{{ item.key }}'
      with_items: "{{ root_auth_keys }}"

ssh_root_authorized_keys.yml

root_auth_keys:
  - name: backup@host
    key : "{{ lookup('file', '../group_vars/pubkeys/[email protected]') }}"

  - name: nagios@host
    key : "{{ lookup('file', '../group_vars/pubkeys/[email protected]') }}"
Score:1
in flag

From the documentation:

path: Alternate path to the authorized_keys file

  tasks:
    - name: Set up multiple authorized keys
      authorized_key:
        user: root
        state: present
        key: '{{ item.key }}'
        path: '/etc/ssh/authorized_keys/root'
      with_items: "{{ root_auth_keys }}"
Mohammed Noureldin avatar
pe flag
This doc is outdated
in flag
Thanks for notifying @MohammedNoureldin, I updated the URL. Feel free to suggest edits yourself when you encounter outdated URLs to fix them.
Nstevens avatar
br flag
Thanks. I was hoping Ansible was "path aware" but guess not. I suppose a `stat:` may help here as I have some hosts which do not have `AuthorizedKeysFile` set. Any easy way to determine if this sshd config item is different than default? I'm thinking `shell:` or `cmd:` with `grep` but maybe not.
Score:0
br flag

There are a couple of steps to prepare this functionality. First, get the value of the parameter. There might be more options, e.g. by default

shell> sudo sshd -T | grep authorizedkeysfile
authorizedkeysfile .ssh/authorized_keys .ssh/authorized_keys2

For example, get the first one

    - shell: sshd -T | grep authorizedkeysfile
      register: result
      become: true
    - set_fact:
        AuthorizedKeysFile: "{{ (result.stdout|split)[1] }}"

gives

  AuthorizedKeysFile: .ssh/authorized_keys

The parameter AuthorizedKeysFile may contain %u and %h. See Location of the Authorized Keys File

%h will be replaced by the home directory of the user being authenticated, and %u by the login name of the user

Prepare the database of the home directories

    - getent:
        database: passwd

By default, the module getent stores the database passwd in the dictionary getent_passwd. Home is the 4th attribute, e.g.

    - debug:
        var: getent_passwd['root'][4]

gives

  getent_passwd['root'][4]: /root

Now, given the data

    auth_keys:
      root: [key1, key2, key3]

you can test the functionality

    - shell: sshd -T | grep authorizedkeysfile
      register: result
      become: true
    - set_fact:
        AuthorizedKeysFile: "{{ (result.stdout|split)[1] }}"
    - getent:
        database: passwd
    - debug:
        msg: |
          path: {{ _path }}
          keys: {{ item.value }}
      loop: "{{ auth_keys|dict2items }}"
      vars:
        _user: "{{ item.key }}"
        _home: "{{ getent_passwd[item.key][4] }}"
        _akf: "{{ AuthorizedKeysFile|regex_replace('%u', _user)|
                                     regex_replace('%h', _home) }}"
        _path: "{{ (_akf.0 == '/')|ternary(_akf, [_home, _akf]|join('/')) }}"

gives

  msg: |-
    path: /root/.ssh/authorized_keys
    keys: ['key1', 'key2', 'key3']

If you change the parameter

shell> sudo sshd -T | grep authorizedkeysfile
authorizedkeysfile /etc/ssh/authorized_keys/%u

the play will get the correct location of the authorized keys file

  msg: |-
    path: /etc/ssh/authorized_keys/root
    keys: ['key1', 'key2', 'key3']
mangohost

Post an answer

Most people don’t grasp that asking a lot of questions unlocks learning and improves interpersonal bonding. In Alison’s studies, for example, though people could accurately recall how many questions had been asked in their conversations, they didn’t intuit the link between questions and liking. Across four studies, in which participants were engaged in conversations themselves or read transcripts of others’ conversations, people tended not to realize that question asking would influence—or had influenced—the level of amity between the conversationalists.