Ansible Ssh Private Key in Source Control?

Ansible Ssh Private Key in Source Control?

I have been developing an Ansible playbook for a couple of weeks, therefore, my experience with such technology is relatively short. Part of my strategy includes using a custom ansible_ssh_user for provisioning hosts throughout the inventory, however, such user will need its own SSH key pair, which would involve some sort of a plan for holding/storing its correspondent private key. On a production environment, this playbook would be cloned/pulled and run inside a certain playbook node whose role is to provision the rest of the infrastructure.

At first, I was thinking to just put that private key inside the playbook git repository, but I am having second thoughts about it nonetheless, mostly because of somewhat obvious security reasons and common sense around it, hence the reason I need to consult you about this matter.

With this set on the table, here are the follow-up questions:

  • In an Ansible-based development environment, is it sane/reasonable to hold a private SSH key in source control?
  • Would this practice be advised only for development environments whereas another local git branch inside the playbook node would be then used to hold the actual production SSH private key?
  • Would it be better to address this case scenario via Ansible Vault instead?, I have not ever used this before, but regardless of that I cannot yet tell whether this would be a proper case for using it.
  • In your experience, what would be your approach around this in a production environment?, what would it be considered as the best practice in this particular scenario?

2 Answers

It's a bad idea to store any kind of plaintext secret in revision control, SSH private keys included. Instead, use ansible-vault to store the private key.

ansible-vault can operate on any file type. Just encrypt the file with

ansible-vault encrypt /path/to/local/private_key

then install the key:

- name: Install a private SSH key
  vars:
    source_key: /path/to/local/private_key
    dest_key: /path/to/remote/private_key
  tasks:
  - name: Ensure .ssh directory exists.
    file: 
      dest: "{{ dest_key | dirname }}"
      mode: 0700 
      owner: user 
      state: directory
  - name: Install ssh key
    copy: 
      src: "{{ source_key }}" 
      dest: "{{ dest_key }}"
      mode: 0600
      owner: user

Earlier versions of ansible-vault would only operate on variables defined in var files, so you had to do something like this:

ssh_key: |
  -----BEGIN RSA PRIVATE KEY-----
  ...
  -----END RSA PRIVATE KEY-----
key_file: /home/user/.ssh/id_rsa

Encrypt with ansible-vault:

ansible-vault encrypt /path/to/var_file

And install the key:

- name: Ensure .ssh directory exists.
  file: 
    dest: "{{ key_file | dirname }}"
    mode: 0700 
    owner: user 
    state: directory

- name: Install ssh key
  copy: 
    content: "{{ ssh_key }}" 
    dest: "{{ key_file }}"
    mode: 0600
    owner: user

Thanks to all those below who improved the answer with their comments.

0

Since you are provisioning from scratch, you should generate the private/public key pair on the playbook node and then distribute the public key via the authorized_keys module. This would eliminate the need to store a secret anywhere except on the host where it is needed. Here is a playbook to achieve this, which would be executed on the playbook node:

---
- hosts: 127.0.0.1
  sudo: yes
  gather_facts: no
  tasks:

  - name: create ansible_ssh_user locally
    user: name=ansible_ssh_user generate_ssh_key=yes ssh_key_bits=2048 ssh_key_file=.ssh/id_rsa

  - name: copy the generated public key to an accessible location for the next play
    shell: cp ~ansible_ssh_user/.ssh/id_rsa.pub /tmp/ansible_ssh_user.pub

- hosts: all
  sudo: yes
  gather_facts: no
  tasks:

  - name: create ansible_ssh_user
    user: name=ansible_ssh_user groups=group1,group2

  - name: Add RSA public key to the remote host
    authorized_key: user=ansible_ssh_user key="{{ lookup('file', '/tmp/ansible_ssh_user.pub') }}"

- hosts: 127.0.0.1
  sudo: yes
  gather_facts: no
  tasks:

  - name: remove public key from /tmp
    shell: rm /tmp/ansible_ssh_user.pub
...
3

Your Answer

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

David Miller
Author

David Miller

David Miller brings 15 years of experience in global economics, personal finance strategy, and market dynamics. He specializes in turning complex economic trends into actionable insights for everyday readers.