let user control "auto-de-vault" (#22739)

* added option to toggle off autodevaulting

* fixes per feedbazck
pull/15050/merge
Brian Coca 8 years ago committed by GitHub
parent 29f623571e
commit 7b197d823e

@ -56,6 +56,8 @@ notes:
author:
- Ansible Core Team
- Michael DeHaan
extends_documentation_fragment:
- decrypt
"""
EXAMPLES = '''

@ -96,6 +96,7 @@ options:
author: "Stephen Fromm (@sfromm)"
extends_documentation_fragment:
- files
- decrypt
'''
EXAMPLES = '''

@ -98,6 +98,7 @@ options:
extends_documentation_fragment:
- files
- validate
- decrypt
author:
- "Ansible Core Team"
- "Michael DeHaan"

@ -31,7 +31,7 @@ DOCUMENTATION = '''
module: unarchive
version_added: 1.4
short_description: Unpacks an archive after (optionally) copying it from the local machine.
extends_documentation_fragment: files
extends_documentation_fragment: [files, decrypt]
description:
- The C(unarchive) module unpacks an archive. By default, it will copy the source file from the local system to the target before unpacking.
Set remote_src=yes to unpack an archive which already exists on the target.

@ -372,7 +372,7 @@ class DataLoader:
f.close()
return content_tempfile
def get_real_file(self, file_path):
def get_real_file(self, file_path, decrypt=True):
"""
If the file is vault encrypted return a path to a temporary decrypted file
If the file is not encrypted then the path is returned
@ -392,22 +392,23 @@ class DataLoader:
real_path = self.path_dwim(file_path)
try:
with open(to_bytes(real_path), 'rb') as f:
# Limit how much of the file is read since we do not know
# whether this is a vault file and therefore it could be very
# large.
if is_encrypted_file(f, count=len(b_HEADER)):
# if the file is encrypted and no password was specified,
# the decrypt call would throw an error, but we check first
# since the decrypt function doesn't know the file name
data = f.read()
if not self._b_vault_password:
raise AnsibleParserError("A vault password must be specified to decrypt %s" % file_path)
data = self._vault.decrypt(data, filename=real_path)
# Make a temp file
real_path = self._create_content_tempfile(data)
self._tempfiles.add(real_path)
if decrypt:
with open(to_bytes(real_path), 'rb') as f:
# Limit how much of the file is read since we do not know
# whether this is a vault file and therefore it could be very
# large.
if is_encrypted_file(f, count=len(b_HEADER)):
# if the file is encrypted and no password was specified,
# the decrypt call would throw an error, but we check first
# since the decrypt function doesn't know the file name
data = f.read()
if not self._b_vault_password:
raise AnsibleParserError("A vault password must be specified to decrypt %s" % file_path)
data = self._vault.decrypt(data, filename=real_path)
# Make a temp file
real_path = self._create_content_tempfile(data)
self._tempfiles.add(real_path)
return real_path

@ -36,7 +36,7 @@ class ActionModule(ActionBase):
TRANSFERS_FILES = True
def _assemble_from_fragments(self, src_path, delimiter=None, compiled_regexp=None, ignore_hidden=False):
def _assemble_from_fragments(self, src_path, delimiter=None, compiled_regexp=None, ignore_hidden=False, decrypt=True):
''' assemble a file from a directory of fragments '''
tmpfd, temp_path = tempfile.mkstemp()
@ -51,7 +51,7 @@ class ActionModule(ActionBase):
if not os.path.isfile(fragment) or (ignore_hidden and os.path.basename(fragment).startswith('.')):
continue
fragment_content = open(self._loader.get_real_file(fragment), 'rb').read()
fragment_content = open(self._loader.get_real_file(fragment, decrypt=decrypt), 'rb').read()
# always put a newline between fragments if the previous fragment didn't end with a newline.
if add_newline:
@ -97,6 +97,7 @@ class ActionModule(ActionBase):
regexp = self._task.args.get('regexp', None)
follow = self._task.args.get('follow', False)
ignore_hidden = self._task.args.get('ignore_hidden', False)
decrypt = self._task.args.get('decrypt', True)
if src is None or dest is None:
result['failed'] = True
@ -127,7 +128,7 @@ class ActionModule(ActionBase):
_re = re.compile(regexp)
# Does all work assembling the file
path = self._assemble_from_fragments(src, delimiter, _re, ignore_hidden)
path = self._assemble_from_fragments(src, delimiter, _re, ignore_hidden, decrypt)
path_checksum = checksum_s(path)
dest = self._remote_expand_user(dest)
@ -139,7 +140,7 @@ class ActionModule(ActionBase):
new_module_args = self._task.args.copy()
# clean assemble specific options
for opt in ['remote_src', 'regexp', 'delimiter', 'ignore_hidden']:
for opt in ['remote_src', 'regexp', 'delimiter', 'ignore_hidden', 'decrypt']:
if opt in new_module_args:
del new_module_args[opt]

@ -50,6 +50,7 @@ class ActionModule(ActionBase):
force = boolean(self._task.args.get('force', 'yes'))
remote_src = boolean(self._task.args.get('remote_src', False))
follow = boolean(self._task.args.get('follow', False))
decrypt = boolean(self._task.args.get('decrypt', True))
result['failed'] = True
if (source is None and content is None) or dest is None:
@ -157,7 +158,7 @@ class ActionModule(ActionBase):
# If the local file does not exist, get_real_file() raises AnsibleFileNotFound
try:
source_full = self._loader.get_real_file(source_full)
source_full = self._loader.get_real_file(source_full, decrypt=decrypt)
except AnsibleFileNotFound as e:
result['failed'] = True
result['msg'] = "could not find src=%s, %s" % (source_full, e)
@ -255,8 +256,11 @@ class ActionModule(ActionBase):
original_basename=source_rel,
)
)
if 'content' in new_module_args:
del new_module_args['content']
# remove action plugin only keys
for key in ('content', 'decrypt'):
if key in new_module_args:
del new_module_args[key]
module_return = self._execute_module(module_name='copy',
module_args=new_module_args, task_vars=task_vars,

@ -69,7 +69,7 @@ class ActionModule(ActionBase):
args = ' '.join(parts[1:])
try:
source = self._loader.get_real_file(self._find_needle('files', source))
source = self._loader.get_real_file(self._find_needle('files', source), decrypt=self._task.args.get('decrypt', True))
except AnsibleError as e:
return dict(failed=True, msg=to_native(e))

@ -42,6 +42,7 @@ class ActionModule(ActionBase):
dest = self._task.args.get('dest', None)
remote_src = boolean(self._task.args.get('remote_src', False))
creates = self._task.args.get('creates', None)
decrypt = self._task.args.get('decrypt', True)
# "copy" is deprecated in favor of "remote_src".
if 'copy' in self._task.args:
@ -77,7 +78,7 @@ class ActionModule(ActionBase):
if not remote_src:
try:
source = self._loader.get_real_file(self._find_needle('files', source))
source = self._loader.get_real_file(self._find_needle('files', source), decrypt=decrypt)
except AnsibleError:
result['failed'] = True
result['msg'] = to_native(get_exception())
@ -126,6 +127,11 @@ class ActionModule(ActionBase):
),
)
# remove action plugin only key
for key in ('remote_src', 'decrypt'):
if key in new_module_args:
del new_module_args[key]
# execute the unarchive module now, with the updated args
result.update(self._execute_module(module_args=new_module_args, task_vars=task_vars))
self._remove_tmp_path(tmp)

@ -0,0 +1,31 @@
# (c) 2017, Brian Coca <bcoca@redhat.com>
#
# This file is part of Ansible
#
# 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/>.
class ModuleDocFragment(object):
# Standard files documentation fragment
DOCUMENTATION = """
options:
decrypt:
description:
- This option controls the autodecryption of source files using vault.
required: false
choices: ['Yes', 'No']
default: 'Yes'
version_added: "2.4"
"""
Loading…
Cancel
Save