Skip to content

Commit

Permalink
Connection error messages are unsafe: wrap them (ansible#37329)
Browse files Browse the repository at this point in the history
* Check that connection error msg are not unsafe

* Connection error messages are unsafe: wrap them

For example, in case of error, docker connection plugin returns exception
message containing Go template. These messages weren't tagged as unsafe
and were consequently rendered:

The conditional check 'result is failed' failed. The error was:
{
  'msg': u'Docker version check ([\'/usr/bin/docker\', \'version\', \'--format\', "\'{{.Server.Version}}\'"]) failed: Got permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock: Get http://%2Fvar%2Frun%2Fdocker.sock/v1.35/version: dial unix /var/run/docker.sock: connect: permission denied\n',
  'failed': True
}:
template error while templating string: unexpected '.'.
String: Docker version check (['/usr/bin/docker', 'version', '--format', "'{{.Server.Version}}'"]) failed: Got permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock: Get http://%2Fvar%2Frun%2Fdocker.sock/v1.35/version: dial unix /var/run/docker.sock: connect: permission denied

(cherry picked from commit 4378542)
  • Loading branch information
pilou- authored and abadger committed Mar 14, 2018
1 parent 0a2db12 commit 106487e
Show file tree
Hide file tree
Showing 6 changed files with 74 additions and 1 deletion.
2 changes: 1 addition & 1 deletion lib/ansible/executor/task_executor.py
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ def _clean_res(res, errors='surrogate_or_strict'):
display.debug("done dumping result, returning")
return res
except AnsibleError as e:
return dict(failed=True, msg=to_text(e, nonstring='simplerepr'))
return dict(failed=True, msg=wrap_var(to_text(e, nonstring='simplerepr')))
except Exception as e:
return dict(failed=True, msg='Unexpected failure during module execution.', exception=to_text(traceback.format_exc()), stdout='')
finally:
Expand Down
1 change: 1 addition & 0 deletions test/integration/targets/connection/aliases
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
posix/ci/group2
2 changes: 2 additions & 0 deletions test/integration/targets/connection/inventory
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[local]
testhost
19 changes: 19 additions & 0 deletions test/integration/targets/connection/play.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
- hosts: testhost
gather_facts: false
tasks:
- name: "use a connection plugin raising an exception, exception message contains Jinja template."
connection: dummy
command: /bin/true # command won't be executed
register: result
ignore_errors: True

- name: "check that Jinja template embedded in exception message isn't rendered"
debug:
msg: 'ok'
when: result is failed
register: debug_task

- assert:
that:
- result is failed
- debug_task is success
46 changes: 46 additions & 0 deletions test/integration/targets/connection/plugin/dummy.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type

DOCUMENTATION = """
author:
- John Doe
connection: dummy
short_description: defective connection plugin
description:
- defective connection plugin
version_added: "2.0"
options: {}
"""
import ansible.constants as C
from ansible.errors import AnsibleError
from ansible.plugins.connection import ConnectionBase


class Connection(ConnectionBase):

transport = 'dummy'
has_pipelining = True
become_methods = frozenset(C.BECOME_METHODS)

def __init__(self, play_context, new_stdin, *args, **kwargs):
super(Connection, self).__init__(play_context, new_stdin, *args, **kwargs)

raise AnsibleError('an error with {{ some Jinja }}')

def transport(self):
pass

def _connect(self):
pass

def exec_command(self, cmd, in_data=None, sudoable=True):
pass

def put_file(self, in_path, out_path):
pass

def fetch_file(self, in_path, out_path):
pass

def close(self):
pass
5 changes: 5 additions & 0 deletions test/integration/targets/connection/runme.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#!/usr/bin/env bash

set -o nounset -o errexit -o xtrace

ANSIBLE_CONNECTION_PLUGINS="$(pwd)/plugin" ansible-playbook -i inventory "$(pwd)/play.yml" -v "$@"

0 comments on commit 106487e

Please sign in to comment.