Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[2.8] CVE-2020-1746 - Remove the params module option from ldap_attr and ldap_entry #68715

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
8 changes: 8 additions & 0 deletions changelogs/fragments/ldap-params-removal.yml
@@ -0,0 +1,8 @@
removed_features:
- "ldap_attr, ldap_entry - The ``params`` option has been removed in
Ansible-2.10 as it circumvents Ansible's option handling. Setting
``bind_pw`` with the ``params`` option was disallowed in Ansible-2.7, 2.8,
and 2.9 as it was insecure. For information about this policy, see the
discussion at:
https://meetbot.fedoraproject.org/ansible-meeting/2017-09-28/ansible_dev_meeting.2017-09-28-15.00.log.html
This fixes CVE-2020-1746"
14 changes: 14 additions & 0 deletions docs/docsite/rst/porting_guides/porting_guide_2.7.rst
Expand Up @@ -103,6 +103,15 @@ hashing algorithm being used with this filter.
Deprecated
==========

Expedited Deprecation: Removal of the params module option in ``ldap_attr`` and ``ldap_entry``
----------------------------------------------------------------------------------------------

The ``params`` module option in ``ldap_attr`` and ``ldap_entry`` are deprecated on a short cycle (to
be removed in Ansible-2.10) due to circumventing Ansible's normal option handling. In particular,
if the ``bind_pw`` option is set with ``params``, the value of the option could end up being placed
in a logfile or displayed on stdout.


Expedited Deprecation: Use of ``__file__`` in ``AnsibleModule``
---------------------------------------------------------------

Expand Down Expand Up @@ -192,6 +201,11 @@ The following modules will be removed in Ansible 2.11. Please update your playbo
Noteworthy module changes
-------------------------

* **Security Issue** Setting ``bind_pw`` with the ``params`` option for the ``ldap_entry`` and
``ldap_attr`` modules has been disallowed. If ``bind_pw`` was set with ``params``, the value
could have ended up in a logfile or displayed on stdout. Set ``bind_pw`` directly, with the
modules' options instead.

* Check mode is now supported in the ``command`` and ``shell`` modules. However, only when ``creates`` or ``removes`` is
specified. If either of these are specified, the module will check for existence of the file and report the correct
changed status, if they are not included the module will skip like it had done previously.
Expand Down
9 changes: 9 additions & 0 deletions docs/docsite/rst/porting_guides/porting_guide_2.8.rst
Expand Up @@ -321,6 +321,11 @@ By default in Ansible 2.7, or with ``AGNOSTIC_BECOME_PROMPT=False`` in Ansible 2
Deprecated
==========

* The ``params`` module option in ``ldap_attr`` and ``ldap_entry`` are deprecated on a short cycle
(to be removed in Ansible-2.10) due to circumventing Ansible's normal option handling. In
particular, if the ``bind_pw`` option is set with ``params``, the value of the option could end up
being placed in a logfile or displayed on stdout.

* Setting the async directory using ``ANSIBLE_ASYNC_DIR`` as an task/play environment key is deprecated and will be
removed in Ansible 2.12. You can achieve the same result by setting ``ansible_async_dir`` as a variable like::

Expand Down Expand Up @@ -403,6 +408,10 @@ The following modules will be removed in Ansible 2.12. Please update your playbo
Noteworthy module changes
-------------------------

* **Security Issue** Setting ``bind_pw`` with the ``params`` option for the ``ldap_entry`` and
``ldap_attr`` modules has been disallowed. If ``bind_pw`` was set with ``params``, the value
could have ended up in a logfile or displayed on stdout. Set ``bind_pw`` directly, with the
modules' options instead.
* The ``foreman`` and ``katello`` modules have been deprecated in favor of a set of modules that are broken out per entity with better idempotency in mind.
* The ``foreman`` and ``katello`` modules replacement is officially part of the Foreman Community and supported there.
* The ``tower_credential`` module originally required the ``ssh_key_data`` to be the path to a ssh_key_file.
Expand Down
39 changes: 29 additions & 10 deletions lib/ansible/modules/net_tools/ldap/ldap_attr.py
Expand Up @@ -35,6 +35,9 @@
rules. This should work out in most cases, but it is theoretically
possible to see spurious changes when target and actual values are
semantically identical but lexically distinct.
- "The I(params) parameter is deprecated in Ansible-2.7 due to circumventing Ansible's parameter
handling. The I(params) parameter started disallowing setting the I(bind_pw) parameter in Ansible-2.7
as it was insecure to set the parameter that way."
version_added: '2.3'
author:
- Jiri Tyr (@jtyr)
Expand Down Expand Up @@ -62,10 +65,6 @@
a list of strings (see examples).
type: raw
required: true
params:
description:
- Additional module parameters.
type: dict
extends_documentation_fragment:
- ldap.documentation
'''
Expand Down Expand Up @@ -133,13 +132,15 @@
# server_uri: ldap://localhost/
# bind_dn: cn=admin,dc=example,dc=com
# bind_pw: password
#
# In the example below, 'args' is a task keyword, passed at the same level as the module
- name: Get rid of an unneeded attribute
ldap_attr:
dn: uid=jdoe,ou=people,dc=example,dc=com
name: shadowExpire
values: []
state: exact
params: "{{ ldap_auth }}"
args: "{{ ldap_auth }}"
'''

RETURN = r'''
Expand All @@ -151,6 +152,7 @@
'''

import traceback
from distutils.version import LooseVersion

from ansible.module_utils.basic import AnsibleModule, missing_required_lib
from ansible.module_utils._text import to_native, to_bytes
Expand Down Expand Up @@ -250,11 +252,28 @@ def main():
module.fail_json(msg=missing_required_lib('python-ldap'),
exception=LDAP_IMP_ERR)

# Update module parameters with user's parameters if defined
if 'params' in module.params and isinstance(module.params['params'], dict):
module.params.update(module.params['params'])
# Remove the params
module.params.pop('params', None)
# For Ansible-2.9.x and below, allow the params module parameter with a warning
if LooseVersion(module.ansible_version) < LooseVersion('2.10'):
if module.params['params']:
module.deprecate("The `params` option to ldap_attr will be removed in Ansible 2.10"
" since it circumvents Ansible's option handling", version='2.10')

# However, the bind_pw parameter contains a password so it **must** go through the normal
# argument parsing even though removing it breaks backwards compat.
if 'bind_pw' in module.params['params']:
module.fail_json(msg="Using `bind_pw` with the `params` option has been disallowed since"
" it is insecure. Use the `bind_pw` option directly. The `params`"
" option will be removed in Ansible-2.10")

# Update module parameters with user's parameters if defined
module.params.update(module.params['params'])
# Remove params itself
module.params.pop('params', None)
else:
# For Ansible 2.10 and above
if module.params['params']:
module.fail_json(msg="The `params` option to ldap_attr was removed in Ansible-2.10 since"
" it circumvents Ansible's option handling")

# Instantiate the LdapAttr object
ldap = LdapAttr(module)
Expand Down
47 changes: 30 additions & 17 deletions lib/ansible/modules/net_tools/ldap/ldap_entry.py
Expand Up @@ -32,6 +32,9 @@
rule allowing root to modify the server configuration. If you need to use
a simple bind to access your server, pass the credentials in I(bind_dn)
and I(bind_pw).
- "The I(params) parameter is deprecated in Ansible-2.7 due to circumventing Ansible's parameter
handling. The I(params) parameter started disallowing setting the I(bind_pw) parameter in Ansible-2.7
as it was insecure to set the parameter that way."
version_added: '2.3'
author:
- Jiri Tyr (@jtyr)
Expand All @@ -48,11 +51,6 @@
- If I(state=present), value or list of values to use when creating
the entry. It can either be a string or an actual list of
strings.
params:
description:
- List of options which allows to overwrite any of the task or the
I(attributes) options. To remove an option, set the value of the option
to C(null).
state:
description:
- The target state of the entry.
Expand Down Expand Up @@ -94,11 +92,13 @@
# server_uri: ldap://localhost/
# bind_dn: cn=admin,dc=example,dc=com
# bind_pw: password
#
# In the example below, 'args' is a task keyword, passed at the same level as the module
- name: Get rid of an old entry
ldap_entry:
dn: ou=stuff,dc=example,dc=com
state: absent
params: "{{ ldap_auth }}"
args: "{{ ldap_auth }}"
"""


Expand All @@ -107,6 +107,7 @@
"""

import traceback
from distutils.version import LooseVersion

from ansible.module_utils.basic import AnsibleModule, missing_required_lib
from ansible.module_utils.six import string_types
Expand Down Expand Up @@ -204,6 +205,29 @@ def main():
module.fail_json(msg=missing_required_lib('python-ldap'),
exception=LDAP_IMP_ERR)

# For Ansible-2.9.x and below, allow the params module parameter with a warning
if LooseVersion(module.ansible_version) < LooseVersion('2.10'):
if module.params['params']:
module.deprecate("The `params` option to ldap_attr will be removed in Ansible 2.10"
" since it circumvents Ansible's option handling", version='2.10')

# However, the bind_pw parameter contains a password so it **must** go through the normal
# argument parsing even though removing it breaks backwards compat.
if 'bind_pw' in module.params['params']:
module.fail_json(msg="Using `bind_pw` with the `params` option has been disallowed since"
" it is insecure. Use the `bind_pw` option directly. The `params`"
" option will be removed in Ansible-2.10")

# Update module parameters with user's parameters if defined
module.params.update(module.params['params'])
# Remove params itself
module.params.pop('params', None)
else:
# For Ansible 2.10 and above
if module.params['params']:
module.fail_json(msg="The `params` option to ldap_attr was removed in Ansible-2.10 since"
" it circumvents Ansible's option handling")

state = module.params['state']

# Check if objectClass is present when needed
Expand All @@ -217,17 +241,6 @@ def main():
isinstance(module.params['objectClass'], list))):
module.fail_json(msg="objectClass must be either a string or a list.")

# Update module parameters with user's parameters if defined
if 'params' in module.params and isinstance(module.params['params'], dict):
for key, val in module.params['params'].items():
if key in module.argument_spec:
module.params[key] = val
else:
module.params['attributes'][key] = val

# Remove the params
module.params.pop('params', None)

# Instantiate the LdapEntry object
ldap = LdapEntry(module)

Expand Down
2 changes: 2 additions & 0 deletions test/sanity/validate-modules/ignore.txt
Expand Up @@ -417,6 +417,8 @@ lib/ansible/modules/monitoring/sensu_handler.py E326
lib/ansible/modules/monitoring/zabbix/zabbix_maintenance.py E317
lib/ansible/modules/net_tools/basics/uri.py E323
lib/ansible/modules/net_tools/basics/uri.py E326
lib/ansible/modules/net_tools/ldap/ldap_attr.py E322
lib/ansible/modules/net_tools/ldap/ldap_entry.py E322
lib/ansible/modules/network/a10/a10_server_axapi3.py E326
lib/ansible/modules/network/a10/a10_virtual_server.py E324
lib/ansible/modules/network/aci/aci_epg_to_domain.py E325
Expand Down