copy - redact 'content' from invocation in check mode (#71033)

* sanitize copy module invocation secrets in check mode
This commit is contained in:
Sloane Hertel 2020-08-03 11:41:45 -04:00 committed by GitHub
parent 9850915bd6
commit 991714b9d1
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 98 additions and 2 deletions

View file

@ -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)

View file

@ -209,6 +209,8 @@ class ActionModule(ActionBase):
# NOTE: adding invocation arguments here needs to be kept in sync with # NOTE: adding invocation arguments here needs to be kept in sync with
# any no_log specified in the argument_spec in the module. # any no_log specified in the argument_spec in the module.
# This is not automatic. # 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 'invocation' not in result:
if self._play_context.no_log: if self._play_context.no_log:
result['invocation'] = "CENSORED: no_log is set" result['invocation'] = "CENSORED: no_log is set"
@ -218,8 +220,11 @@ class ActionModule(ActionBase):
result['invocation'] = self._task.args.copy() result['invocation'] = self._task.args.copy()
result['invocation']['module_args'] = self._task.args.copy() result['invocation']['module_args'] = self._task.args.copy()
if isinstance(result['invocation'], dict) and 'content' in result['invocation']: if isinstance(result['invocation'], dict):
result['invocation']['content'] = 'CENSORED: content is a no_log parameter' 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 return result

View file

@ -77,6 +77,8 @@
- import_tasks: selinux.yml - import_tasks: selinux.yml
when: ansible_os_family == 'RedHat' and ansible_selinux.get('mode') == 'enforcing' when: ansible_os_family == 'RedHat' and ansible_selinux.get('mode') == 'enforcing'
- import_tasks: no_log.yml
- import_tasks: check_mode.yml - import_tasks: check_mode.yml
# https://github.com/ansible/ansible/issues/57618 # https://github.com/ansible/ansible/issues/57618

View file

@ -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 }}"