summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSloane Hertel <shertel@redhat.com>2020-08-07 13:10:43 -0400
committerGitHub <noreply@github.com>2020-08-07 12:10:43 -0500
commit291f94934c8c49eef85e6539087f2dfcd001fe4f (patch)
treed488eda290c3f35bd24420fc76a75d910070682f
parent11738aed97c9aa2151d971d02655fa8689caf26f (diff)
downloadansible-291f94934c8c49eef85e6539087f2dfcd001fe4f.tar.gz
copy - redact 'content' from invocation in check mode (#71033) (#71069)
* sanitize copy module invocation secrets in check mode (cherry picked from commit 991714b9d1e878a4c2fda67ffd829724fa7ac67e)
-rw-r--r--changelogs/fragments/copy-sanitize-check-mode-invocation-args.yaml7
-rw-r--r--lib/ansible/plugins/action/copy.py9
-rw-r--r--test/integration/targets/copy/tasks/main.yml2
-rw-r--r--test/integration/targets/copy/tasks/no_log.yml82
4 files changed, 98 insertions, 2 deletions
diff --git a/changelogs/fragments/copy-sanitize-check-mode-invocation-args.yaml b/changelogs/fragments/copy-sanitize-check-mode-invocation-args.yaml
new file mode 100644
index 0000000000..894a17f4fd
--- /dev/null
+++ b/changelogs/fragments/copy-sanitize-check-mode-invocation-args.yaml
@@ -0,0 +1,7 @@
+security_fixes:
+- >
+ **security issue** - copy - Redact the value of the no_log 'content'
+ parameter in the result's invocation.module_args in check mode.
+ Previously when used with check mode and with '-vvv', the module
+ would not censor the content if a change would be made to the
+ destination path. (CVE-2020-14332)
diff --git a/lib/ansible/plugins/action/copy.py b/lib/ansible/plugins/action/copy.py
index ef14dd3798..3c69826686 100644
--- a/lib/ansible/plugins/action/copy.py
+++ b/lib/ansible/plugins/action/copy.py
@@ -212,6 +212,8 @@ class ActionModule(ActionBase):
# NOTE: adding invocation arguments here needs to be kept in sync with
# any no_log specified in the argument_spec in the module.
# This is not automatic.
+ # NOTE: do not add to this. This should be made a generic function for action plugins.
+ # This should also use the same argspec as the module instead of keeping it in sync.
if 'invocation' not in result:
if self._play_context.no_log:
result['invocation'] = "CENSORED: no_log is set"
@@ -221,8 +223,11 @@ class ActionModule(ActionBase):
result['invocation'] = self._task.args.copy()
result['invocation']['module_args'] = self._task.args.copy()
- if isinstance(result['invocation'], dict) and 'content' in result['invocation']:
- result['invocation']['content'] = 'CENSORED: content is a no_log parameter'
+ if isinstance(result['invocation'], dict):
+ if 'content' in result['invocation']:
+ result['invocation']['content'] = 'CENSORED: content is a no_log parameter'
+ if result['invocation'].get('module_args', {}).get('content') is not None:
+ result['invocation']['module_args']['content'] = 'VALUE_SPECIFIED_IN_NO_LOG_PARAMETER'
return result
diff --git a/test/integration/targets/copy/tasks/main.yml b/test/integration/targets/copy/tasks/main.yml
index 0a90a68047..fa92101051 100644
--- a/test/integration/targets/copy/tasks/main.yml
+++ b/test/integration/targets/copy/tasks/main.yml
@@ -61,6 +61,8 @@
- import_tasks: acls.yml
when: ansible_system == 'Linux'
+ - import_tasks: no_log.yml
+
# https://github.com/ansible/ansible/issues/57618
- name: Test diff contents
copy:
diff --git a/test/integration/targets/copy/tasks/no_log.yml b/test/integration/targets/copy/tasks/no_log.yml
new file mode 100644
index 0000000000..980c31778d
--- /dev/null
+++ b/test/integration/targets/copy/tasks/no_log.yml
@@ -0,0 +1,82 @@
+- block:
+
+ - set_fact:
+ dest: "{{ local_temp_dir }}/test_no_log"
+
+ - name: ensure playbook and dest files don't exist yet
+ file:
+ path: "{{ item }}"
+ state: absent
+ loop:
+ - "{{ local_temp_dir }}/test_no_log.yml"
+ - "{{ dest }}"
+
+ - name: create a playbook to run with command
+ copy:
+ dest: "{{local_temp_dir}}/test_no_log.yml"
+ content: !unsafe |
+ ---
+ - hosts: localhost
+ gather_facts: no
+ tasks:
+ - copy:
+ dest: "{{ dest }}"
+ content: "{{ secret }}"
+
+ - name: copy the secret while using -vvv and check mode
+ command: "ansible-playbook {{local_temp_dir}}/test_no_log.yml -vvv -e secret=SECRET -e dest={{dest}} --check"
+ register: result
+
+ - assert:
+ that:
+ - "'SECRET' not in result.stdout"
+
+ - name: copy the secret while using -vvv
+ command: "ansible-playbook {{local_temp_dir}}/test_no_log.yml -vvv -e secret=SECRET -e dest={{dest}}"
+ register: result
+
+ - assert:
+ that:
+ - "'SECRET' not in result.stdout"
+
+ - name: copy the secret while using -vvv and check mode again
+ command: "ansible-playbook {{local_temp_dir}}/test_no_log.yml -vvv -e secret=SECRET -e dest={{dest}} --check"
+ register: result
+
+ - assert:
+ that:
+ - "'SECRET' not in result.stdout"
+
+ - name: copy the secret while using -vvv again
+ command: "ansible-playbook {{local_temp_dir}}/test_no_log.yml -vvv -e secret=SECRET -e dest={{dest}}"
+ register: result
+
+ - assert:
+ that:
+ - "'SECRET' not in result.stdout"
+
+ - name: copy a new secret while using -vvv and check mode
+ command: "ansible-playbook {{local_temp_dir}}/test_no_log.yml -vvv -e secret=NEWSECRET -e dest={{dest}} --check"
+ register: result
+
+ - assert:
+ that:
+ - "'NEWSECRET' not in result.stdout"
+
+ - name: copy a new secret while using -vvv
+ command: "ansible-playbook {{local_temp_dir}}/test_no_log.yml -vvv -e secret=NEWSECRET -e dest={{dest}}"
+ register: result
+
+ - assert:
+ that:
+ - "'NEWSECRET' not in result.stdout"
+
+ always:
+
+ - name: remove temp test files
+ file:
+ path: "{{ item }}"
+ state: absent
+ loop:
+ - "{{ local_temp_dir }}/test_no_log.yml"
+ - "{{ dest }}"