可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
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
回答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
回答2:
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)
回答3:
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.
回答4:
I used a template and a vars_file
to do it:
In your top-level playbook:
vars_files:
- secretvars.yml
In a task:
- name: Private ssl key
template: src=etc-ssl-private-site.key dest=/etc/ssl/private/site.key
In the template (etc-ssl-private-site.key
) all you need is the variable:
{{ private_ssl_key }}
In the encrypted secretvars.yml
(encrypt this with ansible-vault
):
---
private_ssl_key: |
-----BEGIN PRIVATE KEY-----
abcabcabcabcabcabcabcabcabc
-----END PRIVATE KEY-----
回答5:
Update: As of April 2016 my Github PR has been merged and is available in Ansible 2.1 and later. The below was an interim solution until the PR was merged.
Wanting to do the same thing I created an action plugin to implement the feature. This is available via github. The plugin is exactly the copy action plugin as shipped with ansible, but with support for vault decryption.
You can use it like this:
- name: Copy Some Secret File
copyv: src="secret.txt" dest="/tmp/"
if secret.txt is encrypted (and the vault password is supplied) then it will be decrypted and copied.
回答6:
I think, you have a simpler way to do this.
If you use certificate+key in one file in some format (like pkcs12 or just concatenated), you can use generic openssl
(or gpg
, or something else) encryption. It will look like this:
openssl enc -e -aes-256-ctr -in original.pem -out encrypted.aes -k <pass-vault>
After that you can just copy encrypted.aes to remote host and decrypt it in-place:
- name: copy encrypted cert and key
copy: src=encrypted.aes dest=/root/ansible-files/ mode=0600
- name: decrypt cert and key
command: openssl enc -aes-256-ctr -d -in /root/ansible-files/encrypted.aes -out <dest> -k {{ pass-vault }}
If you have separate key file in pem or der format, you can use
openssl rsa -in original.pem -out encrypted.pem -aes256 -passout pass:<pass-vault>
回答7:
Until the 'copy' module has been extended to automatically decrypt vault files, here's a simple workaround:
When stdout is not a tty, ansible-vault view <file>
prints cleartext to stdout without invoking a pager.
In combination with a 'pipe' lookup, this behavior can be used with a vault password file to feed into the copy module's 'content' option:
- name: "install host key"
copy: content="{{ lookup('pipe', 'ansible-vault view ' + src_key_file) }}"
dest={{ dest_key_file }}
回答8:
You can also use local_action to temporairly decrypt your file as part of the playbook:
- name: "temporairly decrypt the twpol.enc"
sudo: False
local_action: shell ansible-vault view --vault-password-file {{ lookup('env', 'ANSIBLE_VAULT_PASS_FILE') }} ./roles/copykey/files/key.enc > ./roles/copykey/files/key.txt
- name: "copy the key to the target machine."
copy: src=key.txt dest=/tmp
- name: "remove decrypted key.txt file"
sudo: False
local_action: rm ./roles/copykey/files/key.txt
回答9:
Ansible 2.5 added the parameter decrypt
to the copy
module.
For example, if you encrypted your file using something like:
$ ansible-vault encrypt vault/encrypted.crt
Now you can use copy + decrypt:
---
- name: upload ssl crt
copy:
src: path/to/encrypted-with-vault.crt
dest: /usr/local/etc/ssl/domain.crt
decrypt: yes
mode: 0600
回答10:
+1 for the copy: content= {{ private_ssl_key }}"
method suggested by @utapyngo above.
If you are doing your key distribution as a role, rather than just in a playbook (and why not, since key distribution is something you might need again later), keep in mind the following:
- You only get one file for your vars, so all the keys (say you have different bundles based on host machines or whatever) have to go together in
<role>/vars/main.yml
- Variables in this
<role>/vars/main.yml
are referenceable without any paths (that's nice!)
- Remember that whenever you want the content of the variable, you need quotes AND curlies, i.e.,
"{{ your_variable_name }}"
- If you want to copy more than one file per task, you need a
with_items:
loop
- If you want to keep your sensitive data that you've gone through so much trouble to encrypt in the first place off the screen, a neat trick is to next your key variables inside a dictionary; that way, in your
with_items
loop you are feeding it the dictionary key rather than the contents of the variable itself.