From 4cecbe81adbc655d7ab734165d3ac539f8ba5981 Mon Sep 17 00:00:00 2001 From: Brian Coca Date: Fri, 29 Jun 2018 19:46:10 -0400 Subject: [PATCH] [stable-2.6] ignore ansible.cfg in world writable cwd (#42070) * ignore ansible.cfg in world writable cwd * also added 'warnings' to config * updated man page template (cherry picked from commit b6f2aad) Co-authored-by: Brian Coca --- changelogs/fragments/wrcwd_ansible.cfg.yml | 2 ++ .../installation_guide/intro_configuration.rst | 4 ++-- docs/templates/man.j2 | 12 ++++++++---- lib/ansible/config/manager.py | 15 ++++++++++++--- lib/ansible/constants.py | 15 ++++++++++++++- 5 files changed, 38 insertions(+), 10 deletions(-) create mode 100644 changelogs/fragments/wrcwd_ansible.cfg.yml diff --git a/changelogs/fragments/wrcwd_ansible.cfg.yml b/changelogs/fragments/wrcwd_ansible.cfg.yml new file mode 100644 index 00000000000..5f0f295f351 --- /dev/null +++ b/changelogs/fragments/wrcwd_ansible.cfg.yml @@ -0,0 +1,2 @@ +bugfixes: + - '**Security Fix** - avoid using ansible.cfg in a world writable dir.' diff --git a/docs/docsite/rst/installation_guide/intro_configuration.rst b/docs/docsite/rst/installation_guide/intro_configuration.rst index a3de6efbd2a..9727b0d52a0 100644 --- a/docs/docsite/rst/installation_guide/intro_configuration.rst +++ b/docs/docsite/rst/installation_guide/intro_configuration.rst @@ -22,7 +22,7 @@ Paths where configuration file is searched are listed in :ref:`reference documen .. _getting_the_latest_configuration: Getting the latest configuration -================================ +-------------------------------- If installing Ansible from a package manager, the latest ansible.cfg file should be present in /etc/ansible, possibly as a ".rpmnew" file (or other) as appropriate in the case of updates. @@ -36,6 +36,7 @@ For more details and a full listing of available configurations go to :ref:`conf For in-depth details, see :ref:`ansible_configuration_settings`. +.. _environmental_configuration: Environmental configuration =========================== @@ -56,4 +57,3 @@ Settings in the command line will override those passed through the configuratio The full list of options available is in :ref:`ansible-playbook` and :ref:`ansible`. - diff --git a/docs/templates/man.j2 b/docs/templates/man.j2 index a9ba2577f5d..85573d25cbc 100644 --- a/docs/templates/man.j2 +++ b/docs/templates/man.j2 @@ -76,17 +76,18 @@ ENVIRONMENT The following environment variables may be specified. {% if inventory %} -ANSIBLE_INVENTORY -- Override the default ansible inventory file +ANSIBLE_INVENTORY -- Override the default ansible inventory sources {% endif %} {% if library %} ANSIBLE_LIBRARY -- Override the default ansible module library path {% endif %} -ANSIBLE_CONFIG -- Override the default ansible config file +ANSIBLE_CONFIG -- Specify override location for the ansible config file Many more are available for most options in ansible.cfg +For a full list check https://docs.ansible.com/. or use the `ansible-config` command. FILES ----- @@ -99,6 +100,9 @@ FILES ~/.ansible.cfg -- User config file, overrides the default config if present +./ansible.cfg -- Local config file (in current working direcotry) assumed to be 'project specific' and overrides the rest if present. + +As mentioned above, the ANSIBLE_CONFIG environment variable will override all others. AUTHOR ------ @@ -109,8 +113,8 @@ Ansible was originally written by Michael DeHaan. COPYRIGHT --------- -Copyright © 2017 Red Hat, Inc | Ansible. -Ansible is released under the terms of the GPLv3 License. +Copyright © 2018 Red Hat, Inc | Ansible. +Ansible is released under the terms of the GPLv3 license. SEE ALSO diff --git a/lib/ansible/config/manager.py b/lib/ansible/config/manager.py index df82b4d854e..48cf2cba3a8 100644 --- a/lib/ansible/config/manager.py +++ b/lib/ansible/config/manager.py @@ -6,6 +6,7 @@ __metaclass__ = type import os import sys +import stat import tempfile from collections import namedtuple @@ -141,7 +142,7 @@ def get_ini_config_value(p, entry): return value -def find_ini_config_file(): +def find_ini_config_file(warnings=None): ''' Load INI Config File order(first found is used): ENV, CWD, HOME, /etc/ansible ''' # FIXME: eventually deprecate ini configs @@ -151,7 +152,14 @@ def find_ini_config_file(): if os.path.isdir(path0): path0 += "/ansible.cfg" try: - path1 = os.getcwd() + "/ansible.cfg" + path1 = os.getcwd() + perms1 = os.stat(path1) + if perms1.st_mode & stat.S_IWOTH: + if warnings is not None: + warnings.add("Ansible is in a world writable directory (%s), ignoring it as an ansible.cfg source." % to_text(path1)) + path1 = None + else: + path1 += "/ansible.cfg" except OSError: path1 = None path2 = unfrackpath("~/.ansible.cfg", follow=False) @@ -170,6 +178,7 @@ class ConfigManager(object): UNABLE = {} DEPRECATED = [] + WARNINGS = set() def __init__(self, conf_file=None, defs_file=None): @@ -195,7 +204,7 @@ class ConfigManager(object): if self._config_file is None: # set config using ini - self._config_file = find_ini_config_file() + self._config_file = find_ini_config_file(self.WARNINGS) # consume configuration if self._config_file: diff --git a/lib/ansible/constants.py b/lib/ansible/constants.py index 6b2e5a15eab..12d34d87462 100644 --- a/lib/ansible/constants.py +++ b/lib/ansible/constants.py @@ -17,6 +17,16 @@ from ansible.module_utils.six import string_types from ansible.config.manager import ConfigManager, ensure_type, get_ini_config_value +def _warning(msg): + ''' display is not guaranteed here, nor it being the full class, but try anyways, fallback to sys.stderr.write ''' + try: + from __main__ import display + display.warning(msg) + except: + import sys + sys.stderr.write(' [WARNING] %s\n' % (msg)) + + def _deprecated(msg, version='2.8'): ''' display is not guaranteed here, nor it being the full class, but try anyways, fallback to sys.stderr.write ''' try: @@ -24,7 +34,7 @@ def _deprecated(msg, version='2.8'): display.deprecated(msg, version=version) except: import sys - sys.stderr.write('[DEPRECATED] %s, to be removed in %s' % (msg, version)) + sys.stderr.write(' [DEPRECATED] %s, to be removed in %s\n' % (msg, version)) def mk_boolean(value): @@ -189,3 +199,6 @@ for setting in config.data.get_settings(): value = ensure_type(value, setting.type) set_constant(setting.name, value) + +for warn in config.WARNINGS: + _warning(warn)