2

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/root@backup.pub') }}"

  - name: nagios@host
    key : "{{ lookup('file', '../group_vars/pubkeys/root@nagios.pub') }}"

2 Answers 2

1

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 }}"
3
  • 1
    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.
    – Nstevens
    Mar 2, 2022 at 14:14
  • This doc is outdated Oct 9, 2022 at 22:02
  • Thanks for notifying @MohammedNoureldin, I updated the URL. Feel free to suggest edits yourself when you encounter outdated URLs to fix them. Oct 10, 2022 at 5:23
0

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']

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.