2
votes

Question:

Using Ansible, how can I set multiple public-key files (.pub) to be deployed in a user's authorized_keys file instead of using a single file containing a list of public ssh-keys?


Scenario and requirements:

  • I have multiple public ssh-keys stored as .pub files on a central location
  • I want to create new users from a vars file
  • each user shall have (none/one specific/multiple) public ssh-keys from the selection of .pub files deployed to their respective authorized_keys file
  • the list of deployed .pub files can change due to:
    • content of .pub file has changed due to eg. compromised private key
    • user in vars file shall have additional public key files assigned
  • I don't want to go through a "list" file for each user to replace a key

Currently deployed:

vars-file (vars/users.yml):

users:
  - username: "bob"
    sshkey: "{{ lookup('file', 'files/ssh_keys/bob.keys') }}"
    ...
  - username: "alice"
    sshkey: "{{ lookup('file', 'files/ssh_keys/alice.keys') }}"
    ...

contents of bob.keys:

ssh-rsa admin-ssh-key= admin
ssh-rsa support-a-ssh-key= support-a
ssh-rsa bobs-ssh-key= hi im bob

contents of alice.keys:

ssh-rsa admin-ssh-key= admin
ssh-rsa alice-ssh-key= hi im alice
ssh-rsa accounting-clerk-ssh-key= checking your progress

ansible role main.yml file:

 - name: Add SSH keys
  authorized_key:
    user: "{{ item.username }}"
    state: "{{ item.sshkeystate }}"
    key: "{{ item.sshkey }}"
    exclusive: yes
  with_items: "{{ users }}"
  tags: [add ssh keys]

Problem Scenario:

  • support-a's ssh key got compromised and all users having that public key in their authorized_keys file need to be replaced with the new public key
  • I need to (sed) through all keys files and replace the compromised public key with the new one

I tried:

vars-file:

users:
  - username: "bob"
  sshkey:
    - "{{ lookup('file', 'files/ssh_keys/admin.pub') }}"
    - "{{ lookup('file', 'files/ssh_keys/support_a.pub') }}"
    - "{{ lookup('file', 'files/ssh_keys/bob.pub') }}"
  ...
  - username: "alice"
  sshkey:
    - "{{ lookup('file', 'files/ssh_keys/admin.pub') }}"
    - "{{ lookup('file', 'files/ssh_keys/alice.pub') }}"
    - "{{ lookup('file', 'files/ssh_keys/accounting_clerk.pub') }}"

However, I'm getting this error when executing the ansible role: "msg": "invalid key specified: ['ssh-rsa admin-ssh-key= admin', 'ssh-rsa support-a-ssh-key= support-a', 'ssh-rsa bobs-ssh-key= hi im bob']"

I also tried something along the lines of this ( https://stackoverflow.com/a/54079374 ) solution but I guess the scenario and requirements are a bit different and there is nothing to selectattr() in my scenario (I think).


Can anyone point me to how to solve this or am I going in a completely wrong direction? Cheers.

1

1 Answers

1
votes

As best I can tell, the only part that differs in your playbook from the one you linked to is the "\n".join() part, which folds the list into one text block. As ansible correctly points out, you are providing a list[str] to an attribute that expects str

I don't believe in your circumstance you need to use selectattr or any filtering, because you want all the keys all the time. Thus:

- name: Add SSH keys
  authorized_key:
    user: "{{ item.username }}"
    state: "{{ item.sshkeystate }}"
    key: '{{ item.sshkey | join("\n") }}'
    exclusive: yes
  with_items: "{{ users }}"
  tags: [add ssh keys]