From e99395f0c00a3c2efb6e6b1a1ef275c2518d600d Mon Sep 17 00:00:00 2001 From: Abhijit Menon-Sen Date: Wed, 26 Aug 2015 21:25:50 +0530 Subject: [PATCH 1/7] Don't create a VaultLib in each method; do it in __init__ instead --- lib/ansible/parsing/vault/__init__.py | 28 ++++++++++----------------- 1 file changed, 10 insertions(+), 18 deletions(-) diff --git a/lib/ansible/parsing/vault/__init__.py b/lib/ansible/parsing/vault/__init__.py index c9d4372e7b5..db0cd643565 100644 --- a/lib/ansible/parsing/vault/__init__.py +++ b/lib/ansible/parsing/vault/__init__.py @@ -227,7 +227,7 @@ class VaultLib: class VaultEditor: def __init__(self, password): - self.password = password + self.vault = VaultLib(password) def _edit_file_helper(self, filename, existing_data=None, force_save=False): # make sure the umask is set to a sane value @@ -248,11 +248,8 @@ class VaultEditor: os.remove(tmp_path) return - # create new vault - this_vault = VaultLib(self.password) - # encrypt new data and write out to tmp - enc_data = this_vault.encrypt(tmpdata) + enc_data = self.vault.encrypt(tmpdata) self.write_data(enc_data, tmp_path) # shuffle tmp file into place @@ -280,9 +277,8 @@ class VaultEditor: raise AnsibleError("%s does not exist" % filename) tmpdata = self.read_data(filename) - this_vault = VaultLib(self.password) - if this_vault.is_encrypted(tmpdata): - dec_data = this_vault.decrypt(tmpdata) + if self.vault.is_encrypted(tmpdata): + dec_data = self.vault.decrypt(tmpdata) if dec_data is None: raise AnsibleError("Decryption failed") else: @@ -296,11 +292,10 @@ class VaultEditor: # decrypt to tmpfile tmpdata = self.read_data(filename) - this_vault = VaultLib(self.password) - dec_data = this_vault.decrypt(tmpdata) + dec_data = self.vault.decrypt(tmpdata) # let the user edit the data and save - if this_vault.cipher_name not in CIPHER_WRITE_WHITELIST: + if self.vault.cipher_name not in CIPHER_WRITE_WHITELIST: # we want to get rid of files encrypted with the AES cipher self._edit_file_helper(filename, existing_data=dec_data, force_save=True) else: @@ -312,8 +307,7 @@ class VaultEditor: # decrypt to tmpfile tmpdata = self.read_data(filename) - this_vault = VaultLib(self.password) - dec_data = this_vault.decrypt(tmpdata) + dec_data = self.vault.decrypt(tmpdata) _, tmp_path = tempfile.mkstemp() self.write_data(dec_data, tmp_path) @@ -329,9 +323,8 @@ class VaultEditor: raise AnsibleError("%s does not exist" % filename) tmpdata = self.read_data(filename) - this_vault = VaultLib(self.password) - if not this_vault.is_encrypted(tmpdata): - enc_data = this_vault.encrypt(tmpdata) + if not self.vault.is_encrypted(tmpdata): + enc_data = self.vault.encrypt(tmpdata) self.write_data(enc_data, filename) else: raise AnsibleError("%s is already encrypted" % filename) @@ -342,8 +335,7 @@ class VaultEditor: # decrypt tmpdata = self.read_data(filename) - this_vault = VaultLib(self.password) - dec_data = this_vault.decrypt(tmpdata) + dec_data = self.vault.decrypt(tmpdata) # create new vault new_vault = VaultLib(new_password) From 8fc8bf9439f8530639c3e14ed6745c3625034049 Mon Sep 17 00:00:00 2001 From: Abhijit Menon-Sen Date: Wed, 26 Aug 2015 22:19:54 +0530 Subject: [PATCH 2/7] Simplify VaultEditor methods We don't need to keep creating VaultLibs everywhere, and we don't need to keep checking for errors because VaultLib does it already. --- lib/ansible/parsing/vault/__init__.py | 97 +++++++++++---------------- 1 file changed, 41 insertions(+), 56 deletions(-) diff --git a/lib/ansible/parsing/vault/__init__.py b/lib/ansible/parsing/vault/__init__.py index db0cd643565..e8636cad111 100644 --- a/lib/ansible/parsing/vault/__init__.py +++ b/lib/ansible/parsing/vault/__init__.py @@ -130,7 +130,7 @@ class VaultLib: b_data = to_bytes(data, errors='strict', encoding='utf-8') if self.is_encrypted(b_data): - raise AnsibleError("data is already encrypted") + raise AnsibleError("input is already encrypted") if not self.cipher_name or self.cipher_name not in CIPHER_WRITE_WHITELIST: self.cipher_name = u"AES256" @@ -162,7 +162,7 @@ class VaultLib: raise AnsibleError("A vault password must be specified to decrypt data") if not self.is_encrypted(b_data): - raise AnsibleError("data is not encrypted") + raise AnsibleError("input is not encrypted") # clean out header b_data = self._split_header(b_data) @@ -258,97 +258,82 @@ class VaultEditor: # and restore umask os.umask(old_umask) - def create_file(self, filename): - """ create a new encrypted file """ + def encrypt_file(self, filename): check_prereqs() - if os.path.isfile(filename): - raise AnsibleError("%s exists, please use 'edit' instead" % filename) - - # Let the user specify contents and save file - self._edit_file_helper(filename) + plaintext = self.read_data(filename) + ciphertext = self.vault.encrypt(plaintext) + self.write_data(ciphertext, filename) def decrypt_file(self, filename): check_prereqs() - if not os.path.isfile(filename): - raise AnsibleError("%s does not exist" % filename) + ciphertext = self.read_data(filename) + plaintext = self.vault.decrypt(ciphertext) + self.write_data(plaintext, filename) - tmpdata = self.read_data(filename) - if self.vault.is_encrypted(tmpdata): - dec_data = self.vault.decrypt(tmpdata) - if dec_data is None: - raise AnsibleError("Decryption failed") - else: - self.write_data(dec_data, filename) - else: - raise AnsibleError("%s is not encrypted" % filename) + def create_file(self, filename): + """ create a new encrypted file """ + + check_prereqs() + + # FIXME: If we can raise an error here, we can probably just make it + # behave like edit instead. + if os.path.isfile(filename): + raise AnsibleError("%s exists, please use 'edit' instead" % filename) + + self._edit_file_helper(filename) def edit_file(self, filename): check_prereqs() - # decrypt to tmpfile - tmpdata = self.read_data(filename) - dec_data = self.vault.decrypt(tmpdata) + ciphertext = self.read_data(filename) + plaintext = self.vault.decrypt(ciphertext) - # let the user edit the data and save if self.vault.cipher_name not in CIPHER_WRITE_WHITELIST: # we want to get rid of files encrypted with the AES cipher - self._edit_file_helper(filename, existing_data=dec_data, force_save=True) + self._edit_file_helper(filename, existing_data=plaintext, force_save=True) else: - self._edit_file_helper(filename, existing_data=dec_data, force_save=False) + self._edit_file_helper(filename, existing_data=plaintext, force_save=False) def view_file(self, filename): check_prereqs() - # decrypt to tmpfile - tmpdata = self.read_data(filename) - dec_data = self.vault.decrypt(tmpdata) + # FIXME: Why write this to a temporary file at all? It would be safer + # to feed it to the PAGER on stdin. _, tmp_path = tempfile.mkstemp() - self.write_data(dec_data, tmp_path) + ciphertext = self.read_data(filename) + plaintext = self.vault.decrypt(ciphertext) + self.write_data(plaintext, tmp_path) # drop the user into pager on the tmp file call(self._pager_shell_command(tmp_path)) os.remove(tmp_path) - def encrypt_file(self, filename): - - check_prereqs() - - if not os.path.isfile(filename): - raise AnsibleError("%s does not exist" % filename) - - tmpdata = self.read_data(filename) - if not self.vault.is_encrypted(tmpdata): - enc_data = self.vault.encrypt(tmpdata) - self.write_data(enc_data, filename) - else: - raise AnsibleError("%s is already encrypted" % filename) - def rekey_file(self, filename, new_password): check_prereqs() - # decrypt - tmpdata = self.read_data(filename) - dec_data = self.vault.decrypt(tmpdata) + ciphertext = self.read_data(filename) + plaintext = self.vault.decrypt(ciphertext) - # create new vault new_vault = VaultLib(new_password) - - # re-encrypt data and re-write file - enc_data = new_vault.encrypt(dec_data) - self.write_data(enc_data, filename) + new_ciphertext = new_vault.encrypt(plaintext) + self.write_data(new_ciphertext, filename) def read_data(self, filename): - f = open(filename, "rb") - tmpdata = f.read() - f.close() - return tmpdata + try: + f = open(filename, "rb") + data = f.read() + f.close() + except Exception as e: + raise AnsibleError(str(e)) + + return data def write_data(self, data, filename): if os.path.isfile(filename): From 32b38d4e29f5e6c20e21ea22e7c2a330b72d4a32 Mon Sep 17 00:00:00 2001 From: Abhijit Menon-Sen Date: Wed, 26 Aug 2015 22:36:07 +0530 Subject: [PATCH 3/7] Fix add_option indentation for consistency before adding another option --- lib/ansible/cli/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/ansible/cli/__init__.py b/lib/ansible/cli/__init__.py index 9c9fa82458c..0106b80cf62 100644 --- a/lib/ansible/cli/__init__.py +++ b/lib/ansible/cli/__init__.py @@ -260,8 +260,8 @@ class CLI(object): dest='vault_password_file', help="vault password file", action="callback", callback=CLI.expand_tilde, type=str) parser.add_option('--new-vault-password-file', - dest='new_vault_password_file', help="new vault password file for rekey", action="callback", - callback=CLI.expand_tilde, type=str) + dest='new_vault_password_file', help="new vault password file for rekey", action="callback", + callback=CLI.expand_tilde, type=str) if subset_opts: From e7eebb6954bdd6e8d684c8062fe2a6d79c6f213a Mon Sep 17 00:00:00 2001 From: Abhijit Menon-Sen Date: Wed, 26 Aug 2015 22:51:20 +0530 Subject: [PATCH 4/7] Implement cat-like filtering behaviour for encrypt/decrypt MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This allows the following invocations: # Interactive use, like gpg ansible-vault encrypt --output x # Non-interactive, for scripting echo plaintext|ansible-vault encrypt --output x # Separate input and output files ansible-vault encrypt input.yml --output output.yml # Existing usage (in-place encryption) unchanged ansible-vault encrypt inout.yml …and the analogous cases for ansible-vault decrypt as well. In all cases, the input and output files can be '-' to read from stdin or write to stdout. This permits sensitive data to be encrypted and decrypted without ever hitting disk. --- lib/ansible/cli/__init__.py | 2 ++ lib/ansible/cli/vault.py | 40 +++++++++++++++++---------- lib/ansible/parsing/vault/__init__.py | 23 +++++++++------ 3 files changed, 43 insertions(+), 22 deletions(-) diff --git a/lib/ansible/cli/__init__.py b/lib/ansible/cli/__init__.py index 0106b80cf62..3b9be157604 100644 --- a/lib/ansible/cli/__init__.py +++ b/lib/ansible/cli/__init__.py @@ -262,6 +262,8 @@ class CLI(object): parser.add_option('--new-vault-password-file', dest='new_vault_password_file', help="new vault password file for rekey", action="callback", callback=CLI.expand_tilde, type=str) + parser.add_option('--output', default=None, dest='output_file', + help='output file name for encrypt or decrypt; use - for stdout') if subset_opts: diff --git a/lib/ansible/cli/vault.py b/lib/ansible/cli/vault.py index bae7377750b..246a29e1e46 100644 --- a/lib/ansible/cli/vault.py +++ b/lib/ansible/cli/vault.py @@ -63,7 +63,19 @@ class VaultCLI(CLI): self.options, self.args = self.parser.parse_args() self.display.verbosity = self.options.verbosity - if len(self.args) == 0: + if self.options.output_file: + if self.action not in ['encrypt','decrypt']: + raise AnsibleOptionsError("The --output option can be used only with ansible-vault encrypt/decrypt") + + # This restriction should remain in place until it's possible to + # load multiple YAML records from a single file, or it's too easy + # to create an encrypted file that can't be read back in. But in + # the meanwhile, "cat a b c|ansible-vault encrypt --output x" is + # a workaround. + if len(self.args) > 1: + raise AnsibleOptionsError("At most one input file may be used with the --output option") + + elif len(self.args) == 0: raise AnsibleOptionsError("Vault requires at least one filename as a parameter") def run(self): @@ -87,20 +99,27 @@ class VaultCLI(CLI): self.execute() - def execute_create(self): + def execute_encrypt(self): - if len(self.args) > 1: - raise AnsibleOptionsError("ansible-vault create can take only one filename argument") + for f in self.args or ['-']: + self.editor.encrypt_file(f, output_file=self.options.output_file) - self.editor.create_file(self.args[0]) + self.display.display("Encryption successful", stderr=True) def execute_decrypt(self): - for f in self.args: - self.editor.decrypt_file(f) + for f in self.args or ['-']: + self.editor.decrypt_file(f, output_file=self.options.output_file) self.display.display("Decryption successful", stderr=True) + def execute_create(self): + + if len(self.args) > 1: + raise AnsibleOptionsError("ansible-vault create can take only one filename argument") + + self.editor.create_file(self.args[0]) + def execute_edit(self): for f in self.args: self.editor.edit_file(f) @@ -110,13 +129,6 @@ class VaultCLI(CLI): for f in self.args: self.editor.view_file(f) - def execute_encrypt(self): - - for f in self.args: - self.editor.encrypt_file(f) - - self.display.display("Encryption successful", stderr=True) - def execute_rekey(self): for f in self.args: if not (os.path.isfile(f)): diff --git a/lib/ansible/parsing/vault/__init__.py b/lib/ansible/parsing/vault/__init__.py index e8636cad111..e7c60611e8f 100644 --- a/lib/ansible/parsing/vault/__init__.py +++ b/lib/ansible/parsing/vault/__init__.py @@ -20,6 +20,7 @@ __metaclass__ = type import os import shlex import shutil +import sys import tempfile from io import BytesIO from subprocess import call @@ -258,21 +259,21 @@ class VaultEditor: # and restore umask os.umask(old_umask) - def encrypt_file(self, filename): + def encrypt_file(self, filename, output_file=None): check_prereqs() plaintext = self.read_data(filename) ciphertext = self.vault.encrypt(plaintext) - self.write_data(ciphertext, filename) + self.write_data(ciphertext, output_file or filename) - def decrypt_file(self, filename): + def decrypt_file(self, filename, output_file=None): check_prereqs() ciphertext = self.read_data(filename) plaintext = self.vault.decrypt(ciphertext) - self.write_data(plaintext, filename) + self.write_data(plaintext, output_file or filename) def create_file(self, filename): """ create a new encrypted file """ @@ -327,7 +328,10 @@ class VaultEditor: def read_data(self, filename): try: - f = open(filename, "rb") + if filename == '-': + f = sys.stdin + else: + f = open(filename, "rb") data = f.read() f.close() except Exception as e: @@ -336,9 +340,12 @@ class VaultEditor: return data def write_data(self, data, filename): - if os.path.isfile(filename): - os.remove(filename) - f = open(filename, "wb") + if filename == '-': + f = sys.stdout + else: + if os.path.isfile(filename): + os.remove(filename) + f = open(filename, "wb") f.write(to_bytes(data, errors='strict')) f.close() From b6de6e69a6dbae8e401786978f9c530270191537 Mon Sep 17 00:00:00 2001 From: Abhijit Menon-Sen Date: Thu, 27 Aug 2015 06:29:02 +0530 Subject: [PATCH 5/7] Also support output to stdout with no arguments This allows "cat plaintext|ansible-vault encrypt > ciphertext". --- lib/ansible/cli/vault.py | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/lib/ansible/cli/vault.py b/lib/ansible/cli/vault.py index 246a29e1e46..086579c3337 100644 --- a/lib/ansible/cli/vault.py +++ b/lib/ansible/cli/vault.py @@ -63,21 +63,22 @@ class VaultCLI(CLI): self.options, self.args = self.parser.parse_args() self.display.verbosity = self.options.verbosity - if self.options.output_file: - if self.action not in ['encrypt','decrypt']: - raise AnsibleOptionsError("The --output option can be used only with ansible-vault encrypt/decrypt") + can_output = ['encrypt', 'decrypt'] + if self.action not in can_output: + if self.options.output_file: + raise AnsibleOptionsError("The --output option can be used only with ansible-vault %s" % '/'.join(can_output)) + if len(self.args) == 0: + raise AnsibleOptionsError("Vault requires at least one filename as a parameter") + else: # This restriction should remain in place until it's possible to # load multiple YAML records from a single file, or it's too easy # to create an encrypted file that can't be read back in. But in # the meanwhile, "cat a b c|ansible-vault encrypt --output x" is # a workaround. - if len(self.args) > 1: + if self.options.output_file and len(self.args) > 1: raise AnsibleOptionsError("At most one input file may be used with the --output option") - elif len(self.args) == 0: - raise AnsibleOptionsError("Vault requires at least one filename as a parameter") - def run(self): super(VaultCLI, self).run() From 090cfc9e03f7e66c50581a67d09efa0d5ed2499b Mon Sep 17 00:00:00 2001 From: Abhijit Menon-Sen Date: Thu, 27 Aug 2015 12:37:42 +0530 Subject: [PATCH 6/7] More helpful prompts from ansible-vault encrypt/decrypt MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Now we issue a "Reading … from stdin" prompt if our input isatty(), as gpg does. We also suppress the "x successful" confirmation message at the end if we're part of a pipeline. (The latter requires that we not close sys.stdout in VaultEditor, and for symmetry we do the same for sys.stdin, though it doesn't matter in that case.) --- lib/ansible/cli/vault.py | 12 ++++++++++-- lib/ansible/parsing/vault/__init__.py | 15 +++++++-------- 2 files changed, 17 insertions(+), 10 deletions(-) diff --git a/lib/ansible/cli/vault.py b/lib/ansible/cli/vault.py index 086579c3337..e9eee78121c 100644 --- a/lib/ansible/cli/vault.py +++ b/lib/ansible/cli/vault.py @@ -102,17 +102,25 @@ class VaultCLI(CLI): def execute_encrypt(self): + if len(self.args) == 0 and sys.stdin.isatty(): + self.display.display("Reading plaintext input from stdin", stderr=True) + for f in self.args or ['-']: self.editor.encrypt_file(f, output_file=self.options.output_file) - self.display.display("Encryption successful", stderr=True) + if sys.stdout.isatty(): + self.display.display("Encryption successful", stderr=True) def execute_decrypt(self): + if len(self.args) == 0 and sys.stdin.isatty(): + self.display.display("Reading ciphertext input from stdin", stderr=True) + for f in self.args or ['-']: self.editor.decrypt_file(f, output_file=self.options.output_file) - self.display.display("Decryption successful", stderr=True) + if sys.stdout.isatty(): + self.display.display("Decryption successful", stderr=True) def execute_create(self): diff --git a/lib/ansible/parsing/vault/__init__.py b/lib/ansible/parsing/vault/__init__.py index e7c60611e8f..7746a2de29c 100644 --- a/lib/ansible/parsing/vault/__init__.py +++ b/lib/ansible/parsing/vault/__init__.py @@ -329,25 +329,24 @@ class VaultEditor: def read_data(self, filename): try: if filename == '-': - f = sys.stdin + data = sys.stdin.read() else: - f = open(filename, "rb") - data = f.read() - f.close() + with open(filename, "rb") as fh: + data = fh.read() except Exception as e: raise AnsibleError(str(e)) return data def write_data(self, data, filename): + bytes = to_bytes(data, errors='strict') if filename == '-': - f = sys.stdout + sys.stdout.write(bytes) else: if os.path.isfile(filename): os.remove(filename) - f = open(filename, "wb") - f.write(to_bytes(data, errors='strict')) - f.close() + with open(filename, "wb") as fh: + fh.write(bytes) def shuffle_files(self, src, dest): # overwrite dest with src From 4afe1cf4229194d87677d9099bd44d004e1fcaf2 Mon Sep 17 00:00:00 2001 From: Abhijit Menon-Sen Date: Thu, 27 Aug 2015 14:35:40 +0530 Subject: [PATCH 7/7] Update ansible-vault manpage to describe new encrypt/decrypt behaviour --- docs/man/man1/ansible-vault.1 | 28 ++++++++++++++++----- docs/man/man1/ansible-vault.1.asciidoc.in | 30 ++++++++++++++++++++--- 2 files changed, 49 insertions(+), 9 deletions(-) diff --git a/docs/man/man1/ansible-vault.1 b/docs/man/man1/ansible-vault.1 index 9cadbdd62dc..e448d031b93 100644 --- a/docs/man/man1/ansible-vault.1 +++ b/docs/man/man1/ansible-vault.1 @@ -1,13 +1,13 @@ '\" t .\" Title: ansible-vault .\" Author: [see the "AUTHOR" section] -.\" Generator: DocBook XSL Stylesheets v1.78.1 -.\" Date: 07/28/2015 +.\" Generator: DocBook XSL Stylesheets v1.76.1 +.\" Date: 08/27/2015 .\" Manual: System administration commands .\" Source: Ansible 2.0.0 .\" Language: English .\" -.TH "ANSIBLE\-VAULT" "1" "07/28/2015" "Ansible 2\&.0\&.0" "System administration commands" +.TH "ANSIBLE\-VAULT" "1" "08/27/2015" "Ansible 2\&.0\&.0" "System administration commands" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- @@ -80,19 +80,35 @@ The \fBedit\fR sub\-command is used to modify a file which was previously encryp This command will decrypt the file to a temporary file and allow you to edit the file, saving it back when done and removing the temporary file\&. .SH "REKEY" .sp -*$ ansible\-vault rekey [options] FILE_1 [FILE_2, \&..., FILE_N] +\fB$ ansible\-vault rekey [options] FILE_1 [FILE_2, \&..., FILE_N]\fR .sp The \fBrekey\fR command is used to change the password on a vault\-encrypted files\&. This command can update multiple files at once, and will prompt for both the old and new passwords before modifying any data\&. .SH "ENCRYPT" .sp -*$ ansible\-vault encrypt [options] FILE_1 [FILE_2, \&..., FILE_N] +\fB$ ansible\-vault encrypt [options] FILE_1 [FILE_2, \&..., FILE_N]\fR .sp The \fBencrypt\fR sub\-command is used to encrypt pre\-existing data files\&. As with the \fBrekey\fR command, you can specify multiple files in one command\&. +.sp +Starting with version 2\&.0, the \fBencrypt\fR command accepts an \fB\-\-output FILENAME\fR option to determine where encrypted output is stored\&. With this option, input is read from the (at most one) filename given on the command line; if no input file is given, input is read from stdin\&. Either the input or the output file may be given as \fI\-\fR for stdin and stdout respectively\&. If neither input nor output file is given, the command acts as a filter, reading plaintext from stdin and writing it to stdout\&. +.sp +Thus any of the following invocations can be used: +.sp +\fB$ ansible\-vault encrypt\fR +.sp +\fB$ ansible\-vault encrypt \-\-output OUTFILE\fR +.sp +\fB$ ansible\-vault encrypt INFILE \-\-output OUTFILE\fR +.sp +\fB$ echo secret|ansible\-vault encrypt \-\-output OUTFILE\fR +.sp +Reading from stdin and writing only encrypted output is a good way to prevent sensitive data from ever hitting disk (either interactively or from a script)\&. .SH "DECRYPT" .sp -*$ ansible\-vault decrypt [options] FILE_1 [FILE_2, \&..., FILE_N] +\fB$ ansible\-vault decrypt [options] FILE_1 [FILE_2, \&..., FILE_N]\fR .sp The \fBdecrypt\fR sub\-command is used to remove all encryption from data files\&. The files will be stored as plain\-text YAML once again, so be sure that you do not run this command on data files with active passwords or other sensitive data\&. In most cases, users will want to use the \fBedit\fR sub\-command to modify the files securely\&. +.sp +As with \fBencrypt\fR, the \fBdecrypt\fR subcommand also accepts the \fB\-\-output FILENAME\fR option to specify where plaintext output is stored, and stdin/stdout is handled as described above\&. .SH "AUTHOR" .sp Ansible was originally written by Michael DeHaan\&. See the AUTHORS file for a complete list of contributors\&. diff --git a/docs/man/man1/ansible-vault.1.asciidoc.in b/docs/man/man1/ansible-vault.1.asciidoc.in index 3785ab9433a..5db71e09e3e 100644 --- a/docs/man/man1/ansible-vault.1.asciidoc.in +++ b/docs/man/man1/ansible-vault.1.asciidoc.in @@ -84,7 +84,7 @@ file, saving it back when done and removing the temporary file. REKEY ----- -*$ ansible-vault rekey [options] FILE_1 [FILE_2, ..., FILE_N] +*$ ansible-vault rekey [options] FILE_1 [FILE_2, ..., FILE_N]* The *rekey* command is used to change the password on a vault-encrypted files. This command can update multiple files at once, and will prompt for both the @@ -93,21 +93,45 @@ old and new passwords before modifying any data. ENCRYPT ------- -*$ ansible-vault encrypt [options] FILE_1 [FILE_2, ..., FILE_N] +*$ ansible-vault encrypt [options] FILE_1 [FILE_2, ..., FILE_N]* The *encrypt* sub-command is used to encrypt pre-existing data files. As with the *rekey* command, you can specify multiple files in one command. +Starting with version 2.0, the *encrypt* command accepts an *--output FILENAME* +option to determine where encrypted output is stored. With this option, input is +read from the (at most one) filename given on the command line; if no input file +is given, input is read from stdin. Either the input or the output file may be +given as '-' for stdin and stdout respectively. If neither input nor output file +is given, the command acts as a filter, reading plaintext from stdin and writing +it to stdout. + +Thus any of the following invocations can be used: + +*$ ansible-vault encrypt* + +*$ ansible-vault encrypt --output OUTFILE* + +*$ ansible-vault encrypt INFILE --output OUTFILE* + +*$ echo secret|ansible-vault encrypt --output OUTFILE* + +Reading from stdin and writing only encrypted output is a good way to prevent +sensitive data from ever hitting disk (either interactively or from a script). + DECRYPT ------- -*$ ansible-vault decrypt [options] FILE_1 [FILE_2, ..., FILE_N] +*$ ansible-vault decrypt [options] FILE_1 [FILE_2, ..., FILE_N]* The *decrypt* sub-command is used to remove all encryption from data files. The files will be stored as plain-text YAML once again, so be sure that you do not run this command on data files with active passwords or other sensitive data. In most cases, users will want to use the *edit* sub-command to modify the files securely. +As with *encrypt*, the *decrypt* subcommand also accepts the *--output FILENAME* +option to specify where plaintext output is stored, and stdin/stdout is handled +as described above. AUTHOR ------