Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to upload encrypted file using ansible vault?

Does anyone have an example of decrypting and uploading a file using ansible-vault.

I am thinking about keeping my ssl certificates encrypted in source control.

It seems something like the following should work.

---
  - name: upload ssl crt
    copy: src=../../vault/encrypted.crt dest=/usr/local/etc/ssl/domain.crt
like image 652
Aaron Renoir Avatar asked Mar 31 '14 22:03

Aaron Renoir


3 Answers

The copy module now does this seamlessly as of Ansible 2.1.x. Just encrypt your file with Ansible Vault and then issue the copy task on the file.

(For reference, here's the feature that added this: https://github.com/ansible/ansible/pull/15417)

like image 147
jeffmaher Avatar answered Nov 19 '22 11:11

jeffmaher


UPDATE: Deprecated as of 2016, Ansible 2.1

On any Ansible version prior of 2.1:

That's not going to work. What you will get is your encrypted.crt (with Ansible Vault) uploaded literally as domain.crt

What you need to do is make your playbook part of a "Vault" and add a variable that contains your certificate content. Something like this:

---
- name: My cool playbook
  hosts: all

  vars:
    mycert: |
       aasfasdfasfas
       sdafasdfasdfasdfsa
       asfasfasfddasfasdfa


  tasks:
    # Apparently this causes new lines on newer ansible versions
    # - name: Put uncrypted cert in a file
    #   shell: echo '{{ mycert }}' > mydecrypted.pem

    # You can try this as per
    # https://github.com/ansible/ansible/issues/9172
    - copy:
      content: "{{ mycert }}"
      dest: /mydecrypted.pem

    - name: Upload Cert
      copy: src=/home/ubuntu/mydecrypted.pem dest=/home/ubuntu/mydecrypteddest.pem

    - name: Delete decrypted cert
      file: path=/home/ubuntu/mydecrypted.pem state=absent

You can choose to put your mycert variable in a separate variable file using Ansible Vault too.

The copy module has been updated in Ansible 2.1. From the changelog: "copy module can now transparently use a vaulted file as source, if vault passwords were provided it will decrypt and copy on the fly." Noting it here, since some people will inevitably not look past the accepted answer. – JK Laiho

like image 37
Rico Avatar answered Nov 19 '22 13:11

Rico


There is a feature request to support this natively in the copy module. But until that is implemented, here is the workaround (similar to @dave1010's answer, but repeating common parts for completeness):

Create a secrets.yml file encrypted with ansible vault which contains your secrets, for example:

---
private_ssl_key: |
  -----BEGIN PRIVATE KEY-----
  abcabcabcabcabcabcabcabcabc
  -----END PRIVATE KEY-----

private_crt: |
  -----BEGIN CERTIFICATE-----
  abcabcabcabcabcabcabcabcabc
  -----END CERTIFICATE-----

In your playbook, include it:

vars_files:
  - secrets.yml

Then you can use the variables in tasks:

- name: Copy private kay
  copy: content="{{ private_ssl_key }}" dest=/some/path/ssl.key

However, this doesn't work if the file that you are trying to copy is a binary file. In that case, you need to first encode the content with base64:

cat your_secret_file | /usr/bin/base64

Then put the base64 encoded value in your secrets.yml file, e.g.:


crt_b64: |
  ndQbmFQSmxrK2IwOFZnZHNJa0sKICAxdDhFRUdmVzhMM...

Then you can create the remote file in two steps:

- name: Copy certificate (base64 encoded)
  copy: content="{{ crt_b64 }}" dest=/some/path/cert.b64

- name: Decode certificate
  shell: "base64 -d /some/path/cert.b64 > /some/path/cert.txt"
  args:
    creates: /some/path/cert.txt

Note that you could delete the temporary cert.b64 file on the remote host. But then re-running the playbook will re-create it instead of skipping this task. So, I prefer to leave it there.

UPDATE: This feature has been implemented in Ansible 2.1.

copy module can now transparently use a vaulted file as source, if vault passwords were provided it will decrypt and copy on the fly.

like image 21
Yasser Avatar answered Nov 19 '22 13:11

Yasser