Fix information disclosure caused by unreachable nodes
Currently we can leak secrets if we encounter unreachable nodes combined with a task using with_items and no_log. In this case the item variables are written to both the job-output.json and job-output.txt. Upstream Ansible has the same issue [1]. The text log can be fixed by defining the v2_runner_on_unreachable callback the same as v2_runner_on_failed. The json log can be fixed the same way as the upstream Ansible issue. [1] https://bugzilla.redhat.com/show_bug.cgi?id=1588855 Change-Id: Ie5dd2a6b11e8e276da65fe470f364107f3dd07ef
This commit is contained in:
parent
896df11638
commit
ffe7278c08
28
tests/fixtures/config/ansible-no-log/git/org_project/playbooks/no-log-unreachable.yaml
vendored
Normal file
28
tests/fixtures/config/ansible-no-log/git/org_project/playbooks/no-log-unreachable.yaml
vendored
Normal file
@ -0,0 +1,28 @@
|
||||
- hosts: localhost
|
||||
gather_facts: no
|
||||
tasks:
|
||||
- name: Add a fake host
|
||||
add_host:
|
||||
hostname: fake
|
||||
ansible_host: notexisting.example.notexisting
|
||||
|
||||
- hosts: fake
|
||||
gather_facts: no
|
||||
tasks:
|
||||
- name: Run a lineinfile task
|
||||
vars:
|
||||
logins:
|
||||
- machine: foo
|
||||
login: bar
|
||||
password: my-very-secret-password-1
|
||||
- machine: two
|
||||
login: three
|
||||
password: my-very-secret-password-2
|
||||
lineinfile:
|
||||
path: /tmp/.netrc
|
||||
mode: 0600
|
||||
create: true
|
||||
insertafter: EOF
|
||||
line: "machine {{ item.machine }} login {{ item.login }} password {{ item.password }}"
|
||||
with_items: "{{ logins }}"
|
||||
no_log: true
|
26
tests/fixtures/config/ansible-no-log/git/org_project/zuul.yaml
vendored
Normal file
26
tests/fixtures/config/ansible-no-log/git/org_project/zuul.yaml
vendored
Normal file
@ -0,0 +1,26 @@
|
||||
- pipeline:
|
||||
name: check
|
||||
manager: independent
|
||||
post-review: true
|
||||
trigger:
|
||||
gerrit:
|
||||
- event: patchset-created
|
||||
success:
|
||||
gerrit:
|
||||
Verified: 1
|
||||
failure:
|
||||
gerrit:
|
||||
Verified: -1
|
||||
|
||||
- job:
|
||||
name: base
|
||||
parent: null
|
||||
|
||||
- job:
|
||||
name: no-log-unreachable
|
||||
run: playbooks/no-log-unreachable.yaml
|
||||
|
||||
- project:
|
||||
check:
|
||||
jobs:
|
||||
- no-log-unreachable
|
6
tests/fixtures/config/ansible-no-log/main.yaml
vendored
Normal file
6
tests/fixtures/config/ansible-no-log/main.yaml
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
- tenant:
|
||||
name: tenant-one
|
||||
source:
|
||||
gerrit:
|
||||
config-projects:
|
||||
- org/project
|
@ -3844,3 +3844,30 @@ class TestPlugins(AnsibleZuulTestCase):
|
||||
roles="roles: [{zuul: 'org/project2'}]")
|
||||
self._run_job('filter-plugin-shared-bare-role',
|
||||
roles="roles: [{zuul: 'org/project3', name: 'shared'}]")
|
||||
|
||||
|
||||
class TestNoLog(AnsibleZuulTestCase):
|
||||
tenant_config_file = 'config/ansible-no-log/main.yaml'
|
||||
|
||||
def _get_file(self, build, path):
|
||||
p = os.path.join(build.jobdir.root, path)
|
||||
with open(p) as f:
|
||||
return f.read()
|
||||
|
||||
def test_no_log_unreachable(self):
|
||||
# Output extra ansible info so we might see errors.
|
||||
self.executor_server.verbose = True
|
||||
self.executor_server.keep_jobdir = True
|
||||
|
||||
A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
|
||||
|
||||
self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
|
||||
self.waitUntilSettled()
|
||||
|
||||
json_log = self._get_file(self.history[0], 'work/logs/job-output.json')
|
||||
text_log = self._get_file(self.history[0], 'work/logs/job-output.txt')
|
||||
|
||||
self.assertNotIn('my-very-secret-password-1', json_log)
|
||||
self.assertNotIn('my-very-secret-password-2', json_log)
|
||||
self.assertNotIn('my-very-secret-password-1', text_log)
|
||||
self.assertNotIn('my-very-secret-password-2', text_log)
|
||||
|
@ -137,7 +137,7 @@ class CallbackModule(CallbackBase):
|
||||
|
||||
def v2_runner_on_ok(self, result, **kwargs):
|
||||
host = result._host
|
||||
if result._result.get('_ansible_no_log', False):
|
||||
if result._result.get('_ansible_no_log', False) or result._task.no_log:
|
||||
self.results[-1]['tasks'][-1]['hosts'][host.name] = dict(
|
||||
censored="the output has been hidden due to the fact that"
|
||||
" 'no_log: true' was specified for this result")
|
||||
|
@ -606,3 +606,5 @@ class CallbackModule(default.CallbackModule):
|
||||
delegated_host=delegated_vars['ansible_host'])
|
||||
else:
|
||||
return result._host.get_name()
|
||||
|
||||
v2_runner_on_unreachable = v2_runner_on_failed
|
||||
|
Loading…
Reference in New Issue
Block a user