Skip to content

Instantly share code, notes, and snippets.

@damncabbage
Last active January 29, 2017 20:45
Show Gist options
  • Save damncabbage/12af8915e12fbf71b897 to your computer and use it in GitHub Desktop.
Save damncabbage/12af8915e12fbf71b897 to your computer and use it in GitHub Desktop.
A file-decryption filter using Ansible Vault's decryption mechanism and an arbitrary password.
# Place in <your-playbook-root>/filter_plugins/decrypt_with.py
from ansible import errors
from ansible.utils.vault import VaultLib
def decrypt_with(data, password):
vault = VaultLib(password=password)
if data is None:
raise errors.AnsibleFilterError("data is missing; cannot decrypt")
elif len(data) == 0:
raise errors.AnsibleFilterError("data is empty; nothing to decrypt")
else:
if vault.is_encrypted(data):
return vault.decrypt(data)
else:
raise errors.AnsibleFilterError("data is not encrypted: %s" % data[:10])
class FilterModule(object):
def filters(self):
return {"decrypt_with": decrypt_with}
#!/usr/bin/env python
# Chuck this in scripts/encrypt_file.py or something
from ansible.utils.vault import VaultLib
from getpass import getpass
import sys
import os
def usage():
return """Usage: scripts/encrypt_file.py file_names [to_encrypt [in_place.txt ...]]"""
def die(message):
print message
sys.exit(1)
def fetch_password():
# TODO: something something optional sys.stdin
return getpass("With password: ")
if __name__ == "__main__":
sources = sys.argv[1:]
if len(sources) == 0:
die(usage())
for source in sources:
if not os.path.exists(source):
die("%s does not exist" % source)
password = fetch_password()
if len(password) == 0:
die("No password provided")
vault = VaultLib(password=password)
for source in sources:
target = source + ".enc"
open(target, 'w').write(vault.encrypt(open(source, 'r').read()))
print "%s => %s" % (source, target)
print "Done."
---
# ...
- name: "Some Files"
copy:
dest: "/tmp/keys/{{ item }}.key"
content: "{{ lookup('file', 'keys/' + item + '.key.enc') | decrypt_with(vaulted_key_password) }}"
with_items:
- "example_one"
- "example_two"
# ...
# Note the "copy:" hash, instead of the usual Ansible key=value pairs.
# See https://twitter.com/damncabbage/status/511701541808799744

Usage

1. Set up decrypt_with.py to <your-playbook-path>/filter_plugins/ (making the directory if it doesn't exist), and copy encrypt_file.py to a new <your-playbook-path>/scripts/ directory. Make the latter executable with chmod a+x scripts/encrypt_file.py.

2. Use http://docs.ansible.com/playbooks_vault.html to set up a playbook with some secret variables (I use vaulted_... as a naming convention), including a key:

$ ansible-vault create staging.yml
---
- include: site.yml # Your main playbook
  vars:
    vaulted_key_password: "somereallylongexamplekeyhere"

3. Encrypt a file with scripts/encrypt_file.py:

$ scripts/encrypt_file.py files/example/keys/secret_file.key
With password: 
$ ls files/example/keys/secret_file*
files/example/keys/secret_file.key
files/example/keys/secret_file.key.enc

4. Then decrypt it on the fly in a playbook:

---
# ...

- name: "Some Files"
  copy:
    dest: "/tmp/keys/{{ item }}.key"
    content: "{{ lookup('file', 'example/keys/' + item + '.key.enc') | decrypt_with(vaulted_key_password) }}"
  with_items:
  - "secret_file"
  - "other_secret_file"

# ...
# Note the "copy:" hash, instead of the usual Ansible key=value pairs.
# See https://twitter.com/damncabbage/status/511701541808799744
@damncabbage
Copy link
Author

A more fleshed-out write-up of the copy: hash comment above: ansible/ansible#9067

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment