Bootstrap FreeKB - Ansible - Append or remove SSH public certificates from an authorized_keys file
Ansible - Append or remove SSH public certificates from an authorized_keys file

Updated:   |  Ansible articles

If you are not familiar with modules, check out Ansible - Getting Started with Modules.

authorized_key can be used to append or remove SSH public certificates from an authorized_keys file.openssh_keypair is in the ansible.posix collection. You may need to install the ansible.posix collection. Check out my article Install a collection using the ansible-galaxy collection install command


--ask-pass flag

When using the ansible-playbook command, assuming the SSH servie on the target server is configured to accept password authentication and the authorized_keys file on the target server does not already contain the users SSH key, you will have to include the --ask-pass flag to connect to the target server. After the users SSH key has been appended to the authorized_keys file on the target server, if the SSH service on the target server is configured to accept publickey authentication, you should then no longer have to use the --ask-pass flag.

 


Append a certificate

Let's say /home/john.doe/.ssh/id_rsa.pub on localhost (that's the Ansible server) contains the following.

ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCqlNpcovu736RD0kiDno7+VB7rTS0jWJrbFEazgCKCYPtVb9bJ9A0tX42wQqsuzSqJ/+fkRJZcDapwZffuMEPZ4lLTS6vgyHI2o8NJk/lXggizOsHJFZyd7sGnnk/ynso86Rl4XA/dKkvwBS3ROrD3r8O1sPEoRKEgt5vwlwYMslSsL1qa0lL/20TuWx78GKEX0b9PI7ZRRMvC5wWS5CRwmvaL8U6N/FUcJYFPcNIy0dIh2mfhUwqnqfxEqYsddN1id8fUm46SwsGgWOTjMKA/OHi5y7gHvQ5wnNlk4c+/55cytwm9wBW5taDRc0ndPOPmWb/YMtMHY7obA+wV8/57

 

When the user parameter is used, the public certificate will be appended to /home/username/.ssh/authorized_keys on the target server. In this example, the public certificate will be appended to /home/john.doe/.ssh/authorized_keys.

---
- hosts: all
  tasks:
  - name: Append /home/john.doe/.ssh/id_rsa.pub on localhost to /home/john.doe/.ssh/authorized_keys on the target server
    ansible.posix.authorized_key:
      user: john.doe
      key: "ssh-rsa 
AAAAB3NzaC1yc2EAAAADAQABAAABAQCqlNpcovu736RD0kiDno7+VB7rTS0jWJrbFEazgCKCYPtVb9bJ9A0tX42wQqsuzSqJ/+fkRJZcDapwZffuMEPZ4lLTS6vgyHI2o8NJk/lXggizOsHJFZyd7sGnnk/ynso86Rl4XA/dKkvwBS3ROrD3r8O1sPEoRKEgt5vwlwYMslSsL1qa0lL/20TuWx78GKEX0b9PI7ZRRMvC5wWS5CRwmvaL8U6N/FUcJYFPcNIy0dIh2mfhUwqnqfxEqYsddN1id8fUm46SwsGgWOTjMKA/OHi5y7gHvQ5wnNlk4c+/55cytwm9wBW5taDRc0ndPOPmWb/YMtMHY7obA+wV8/57"
...

 

When the path parameter is used, the public certificate will be appended to whatever file is defined in path. In this example, the public certificate will be appended to /etc/ssh/authorized_keys.

- name: Append /home/john.doe/.ssh/id_rsa.pub on the control node to /etc/ssh/authorized_keys on the managed node
  ansible.posix.authorized_key:
    path: /etc/ssh/authorized_keys
    key: "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCqlNpcovu736RD0kiDno7+VB7rTS0jWJrbFEazgCKCYPtVb9bJ9A0tX42wQqsuzSqJ/+fkRJZcDapwZffuMEPZ4lLTS6vgyHI2o8NJk/lXggizOsHJFZyd7sGnnk/ynso86Rl4XA/dKkvwBS3ROrD3r8O1sPEoRKEgt5vwlwYMslSsL1qa0lL/20TuWx78GKEX0b9PI7ZRRMvC5wWS5CRwmvaL8U6N/FUcJYFPcNIy0dIh2mfhUwqnqfxEqYsddN1id8fUm46SwsGgWOTjMKA/OHi5y7gHvQ5wnNlk4c+/55cytwm9wBW5taDRc0ndPOPmWb/YMtMHY7obA+wV8/57"

 

Instead of using the actual public certificate string, the lookup plugin can be used.

- name: Append /home/john.doe/.ssh/id_rsa.pub on the control node to /home/john.doe/.ssh/authorized_keys on the managed node
  ansible.posix.authorized_key:
    user: john.doe
    key: "{{ lookup('file', '/home/john.doe/.ssh/id_rsa.pub') }}"

 

Here is a bit of a more complete example.

  • This almost always requires you to set gather_facts: false as this is typically done before you are able to SSH onto target servers
  • Let's first use the openssh_keypair module to create the public/private keypair on localhost if they do not exist
  • Use the find module to find the SSH public keys on localhost
  • Use slurp and set_fact to create a variable named ssh_key_content that contains the content of the SSH key on localhost
  • Use authorized_key to append the SSH key to the authorized_key file on the target server
---
- hosts: all
  gather_facts: false
  vars:
    type: id_ed25519
  tasks:
  - name: create the public/private key pair on localhost if they do not exist
    community.crypto.openssh_keypair:
      path: /home/{{ lookup('env', 'USER') }}/.ssh/{{ type }}
      regenerate: never
      comment: "{{ lookup('env', 'USER') }}@{{ inventory_hostname }}"
      size: 4096
    delegate_to: localhost
    delegate_facts: true
    register: out

  - name: find SSH public keys on localhost
    ansible.builtin.find:
      paths: /home/{{ lookup('env', 'USER') }}/.ssh
      patterns: (?i).*pub
      use_regex: true
    register: find_results
    delegate_to: localhost
    delegate_facts: true

  - name: set_fact ssh_key
    ansible.builtin.set_fact:
      ssh_key: "{{ item.path }}"
    with_items: "{{ find_results.files }}"

  - name: slurp ssh_key
    ansible.builtin.slurp:
      src: "{{ ssh_key }}"
    register: slurp
    delegate_to: localhost
    delegate_facts: true

  - name: set_fact ssh_key_content
    ansible.builtin.set_fact:
      ssh_key_content: "{{ slurp.content | b64decode | regex_replace('\n$', '') }}"

  - name: append SSH key on localhost (that's the Ansible controller) to /home/{{ remote_user }}/.ssh/authorized_keys on {{ inventory_hostname }}
    ansible.posix.authorized_key:
      user: "{{ remote_user }}"
      key: "{{ ssh_key_content }}"
..

 


Remove a certificate

When the state parameter has a value of absent, the certificate will be removed.

- name: Remove John Doe's public certificate from the authorized_keys file on the managed node
  ansible.posix.authorized_key:
    path: /etc/ssh/authorized_keys
    state: absent
    key: "{{ lookup('file', '/home/john.doe/.ssh/id_rsa.pub') }}"

 


Permission Denied

Let's say the following is returned. Typically, this means you are invoking the playbook as a user that does not have permission to access John Doe's home directory (/home/john.doe). 

[WARNING]: Unable to find '/home/john.doe/.ssh/id_rsa.pub' in expected paths.

 


Register / Debug

The register parameter and debug module can then be used to output the results. In the scenario where id_rsa.pub is successfully appended to the authorized_keys file, something like this should be returned.

TASK [print the 'out' variable]
ok: [server1.example.com => {
    "out": {
        "changed": true,
        "comment": null,
        "exclusive": false,
        "failed": false,
        "follow": false,
        "key": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDD9Kkwp0hH4dfDrhmyy9aXfpAykF5eZR9DvUpSj7p0cJ89Npul7sBhTE5ILV/cZOXnPcQmRNROIGFczv3Io9qHK/V4jNhGM+W+tL9QhiWF4FTqyO8cE8LyExV2WbmeJRTijY7DSXxL69vczYLhSptEFIh5+uHsdjbLN8AhZJ5mJwLcDA32vwav5X5QaSwUja3gIzLwHDfkREef+53l4B8XSQoVcgmxiAcNcIydfzZGmWHT2icwNujDYWLgyu/uu3HkV1E3ACxJuk8pkh3fPWNCuBu1cincd0z270OlbByj2ocobnUtXKDw8DT34Oz1NHMsnIFuG6ho1inp0eQ1yY7v john.doe@ansible.example.com",
        "key_options": null,
        "keyfile": "/home/john.doe/.ssh/authorized_keys",
        "manage_dir": true,
        "path": null,
        "state": "present",
        "user": "john.doe",
        "validate_certs": true
    }
}

 




Did you find this article helpful?

If so, consider buying me a coffee over at Buy Me A Coffee



Comments


Add a Comment


Please enter fa125d in the box below so that we can be sure you are a human.