diff options
Diffstat (limited to 'v1/bin/ansible-vault')
-rwxr-xr-x | v1/bin/ansible-vault | 241 |
1 files changed, 241 insertions, 0 deletions
diff --git a/v1/bin/ansible-vault b/v1/bin/ansible-vault new file mode 100755 index 0000000000..22cfc0e148 --- /dev/null +++ b/v1/bin/ansible-vault @@ -0,0 +1,241 @@ +#!/usr/bin/env python + +# (c) 2014, James Tanner <tanner.jc@gmail.com> +# +# Ansible is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Ansible is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Ansible. If not, see <http://www.gnu.org/licenses/>. +# +# ansible-vault is a script that encrypts/decrypts YAML files. See +# http://docs.ansible.com/playbooks_vault.html for more details. + +__requires__ = ['ansible'] +try: + import pkg_resources +except Exception: + # Use pkg_resources to find the correct versions of libraries and set + # sys.path appropriately when there are multiversion installs. But we + # have code that better expresses the errors in the places where the code + # is actually used (the deps are optional for many code paths) so we don't + # want to fail here. + pass + +import os +import sys +import traceback + +import ansible.constants as C + +from ansible import utils +from ansible import errors +from ansible.utils.vault import VaultEditor + +from optparse import OptionParser + +#------------------------------------------------------------------------------------- +# Utility functions for parsing actions/options +#------------------------------------------------------------------------------------- + +VALID_ACTIONS = ("create", "decrypt", "edit", "encrypt", "rekey", "view") + +def build_option_parser(action): + """ + Builds an option parser object based on the action + the user wants to execute. + """ + + usage = "usage: %%prog [%s] [--help] [options] file_name" % "|".join(VALID_ACTIONS) + epilog = "\nSee '%s <command> --help' for more information on a specific command.\n\n" % os.path.basename(sys.argv[0]) + OptionParser.format_epilog = lambda self, formatter: self.epilog + parser = OptionParser(usage=usage, epilog=epilog) + + if not action: + parser.print_help() + sys.exit() + + # options for all actions + #parser.add_option('-c', '--cipher', dest='cipher', default="AES256", help="cipher to use") + parser.add_option('--debug', dest='debug', action="store_true", help="debug") + parser.add_option('--vault-password-file', dest='password_file', + help="vault password file", default=C.DEFAULT_VAULT_PASSWORD_FILE) + + # options specific to actions + if action == "create": + parser.set_usage("usage: %prog create [options] file_name") + elif action == "decrypt": + parser.set_usage("usage: %prog decrypt [options] file_name") + elif action == "edit": + parser.set_usage("usage: %prog edit [options] file_name") + elif action == "view": + parser.set_usage("usage: %prog view [options] file_name") + elif action == "encrypt": + parser.set_usage("usage: %prog encrypt [options] file_name") + elif action == "rekey": + parser.set_usage("usage: %prog rekey [options] file_name") + + # done, return the parser + return parser + +def get_action(args): + """ + Get the action the user wants to execute from the + sys argv list. + """ + for i in range(0,len(args)): + arg = args[i] + if arg in VALID_ACTIONS: + del args[i] + return arg + return None + +def get_opt(options, k, defval=""): + """ + Returns an option from an Optparse values instance. + """ + try: + data = getattr(options, k) + except: + return defval + if k == "roles_path": + if os.pathsep in data: + data = data.split(os.pathsep)[0] + return data + +#------------------------------------------------------------------------------------- +# Command functions +#------------------------------------------------------------------------------------- + +def execute_create(args, options, parser): + if len(args) > 1: + raise errors.AnsibleError("'create' does not accept more than one filename") + + if not options.password_file: + password, new_password = utils.ask_vault_passwords(ask_vault_pass=True, confirm_vault=True) + else: + password = utils.read_vault_file(options.password_file) + + cipher = 'AES256' + if hasattr(options, 'cipher'): + cipher = options.cipher + + this_editor = VaultEditor(cipher, password, args[0]) + this_editor.create_file() + +def execute_decrypt(args, options, parser): + + if not options.password_file: + password, new_password = utils.ask_vault_passwords(ask_vault_pass=True) + else: + password = utils.read_vault_file(options.password_file) + + cipher = 'AES256' + if hasattr(options, 'cipher'): + cipher = options.cipher + + for f in args: + this_editor = VaultEditor(cipher, password, f) + this_editor.decrypt_file() + + print "Decryption successful" + +def execute_edit(args, options, parser): + + if len(args) > 1: + raise errors.AnsibleError("edit does not accept more than one filename") + + if not options.password_file: + password, new_password = utils.ask_vault_passwords(ask_vault_pass=True) + else: + password = utils.read_vault_file(options.password_file) + + cipher = None + + for f in args: + this_editor = VaultEditor(cipher, password, f) + this_editor.edit_file() + +def execute_view(args, options, parser): + + if len(args) > 1: + raise errors.AnsibleError("view does not accept more than one filename") + + if not options.password_file: + password, new_password = utils.ask_vault_passwords(ask_vault_pass=True) + else: + password = utils.read_vault_file(options.password_file) + + cipher = None + + for f in args: + this_editor = VaultEditor(cipher, password, f) + this_editor.view_file() + +def execute_encrypt(args, options, parser): + + if not options.password_file: + password, new_password = utils.ask_vault_passwords(ask_vault_pass=True, confirm_vault=True) + else: + password = utils.read_vault_file(options.password_file) + + cipher = 'AES256' + if hasattr(options, 'cipher'): + cipher = options.cipher + + for f in args: + this_editor = VaultEditor(cipher, password, f) + this_editor.encrypt_file() + + print "Encryption successful" + +def execute_rekey(args, options, parser): + + if not options.password_file: + password, __ = utils.ask_vault_passwords(ask_vault_pass=True) + else: + password = utils.read_vault_file(options.password_file) + + __, new_password = utils.ask_vault_passwords(ask_vault_pass=False, ask_new_vault_pass=True, confirm_new=True) + + cipher = None + for f in args: + this_editor = VaultEditor(cipher, password, f) + this_editor.rekey_file(new_password) + + print "Rekey successful" + +#------------------------------------------------------------------------------------- +# MAIN +#------------------------------------------------------------------------------------- + +def main(): + + action = get_action(sys.argv) + parser = build_option_parser(action) + (options, args) = parser.parse_args() + + if not len(args): + raise errors.AnsibleError( + "The '%s' command requires a filename as the first argument" % action + ) + + # execute the desired action + try: + fn = globals()["execute_%s" % action] + fn(args, options, parser) + except Exception, err: + if options.debug: + print traceback.format_exc() + print "ERROR:",err + sys.exit(1) + +if __name__ == "__main__": + main() |