diff --git a/.ansible.metadata b/.ansible.metadata index 1f7a337..af53a09 100644 --- a/.ansible.metadata +++ b/.ansible.metadata @@ -1 +1 @@ -bcbdc1511ec85ea1779f24df430bf90987683b8d SOURCES/ansible-2.4.0.0.tar.gz +e325fc5df4191af63d0f3715a9bf8a515fb11b5a SOURCES/ansible-2.4.1.0.tar.gz diff --git a/.gitignore b/.gitignore index d5be5ec..e744527 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1 @@ -SOURCES/ansible-2.4.0.0.tar.gz +SOURCES/ansible-2.4.1.0.tar.gz diff --git a/SOURCES/ansible-newer-jinja.patch b/SOURCES/ansible-newer-jinja.patch index 575c161..c393067 100644 --- a/SOURCES/ansible-newer-jinja.patch +++ b/SOURCES/ansible-newer-jinja.patch @@ -1,7 +1,7 @@ -diff -up ansible-2.3.0.0/requirements.txt.bak ansible-2.3.0.0/requirements.txt ---- ansible-2.3.0.0/requirements.txt.bak 2017-04-12 08:37:59.217167604 -0700 -+++ ansible-2.3.0.0/requirements.txt 2017-04-12 08:38:33.969286602 -0700 -@@ -3,7 +3,7 @@ +diff -Nur ansible-2.4.1.0.orig/requirements.txt ansible-2.4.1.0/requirements.txt +--- ansible-2.4.1.0.orig/requirements.txt 2017-10-25 16:05:04.000000000 -0700 ++++ ansible-2.4.1.0/requirements.txt 2017-10-30 14:41:31.202896847 -0700 +@@ -3,8 +3,8 @@ # packages. Thus, this should be the loosest set possible (only required # packages, not optional ones, and with the widest range of versions that could # be suitable) @@ -9,4 +9,6 @@ diff -up ansible-2.3.0.0/requirements.txt.bak ansible-2.3.0.0/requirements.txt +jinja2 >= 2.6 PyYAML paramiko - pycrypto >= 2.6 +-cryptography ++pycrypto >= 2.6 + setuptools diff --git a/SOURCES/ansible-pr-30875.patch b/SOURCES/ansible-pr-30875.patch deleted file mode 100644 index 7192fe4..0000000 --- a/SOURCES/ansible-pr-30875.patch +++ /dev/null @@ -1,50 +0,0 @@ -diff --git a/lib/ansible/modules/web_infrastructure/jenkins_plugin.py b/lib/ansible/modules/web_infrastructure/jenkins_plugin.py -index 9aba61a..6d2bad6 100644 ---- a/lib/ansible/modules/web_infrastructure/jenkins_plugin.py -+++ b/lib/ansible/modules/web_infrastructure/jenkins_plugin.py -@@ -52,6 +52,8 @@ options: - description: - - Option used to allow the user to overwrite any of the other options. To - remove an option, set the value of the option to C(null). -+ - Changed in 2.5.0, 2.4.1, 2.3.3 to raise an error if C(url_password) is specified in params. -+ Use the actual C(url_password) argument instead. - state: - required: false - choices: [absent, present, pinned, unpinned, enabled, disabled, latest] -@@ -166,20 +168,18 @@ EXAMPLES = ''' - state: absent - - # --# Example of how to use the params --# --# Define a variable and specify all default parameters you want to use across --# all jenkins_plugin calls: -+# Example of how to authenticate - # - # my_jenkins_params: - # url_username: admin --# url_password: p4ssw0rd --# url: http://localhost:8888 - # - - name: Install plugin - jenkins_plugin: - name: build-pipeline-plugin - params: "{{ my_jenkins_params }}" -+ url_password: p4ssw0rd -+ url: http://localhost:8888 -+# Note that url_password **can not** be placed in params as params could end up in a log file - - # - # Example of a Play which handles Jenkins restarts during the state changes -@@ -764,6 +764,11 @@ def main(): - - # Update module parameters by user's parameters if defined - if 'params' in module.params and isinstance(module.params['params'], dict): -+ if 'url_password' in module.params['params']: -+ # The params argument should be removed eventually. Until then, raise an error if -+ # url_password is specified there as it can lead to the password being logged -+ module.fail_json(msg='Do not specify url_password in params as it may get logged') -+ - module.params.update(module.params['params']) - # Remove the params - module.params.pop('params', None) diff --git a/SOURCES/ansible-selinux-issue-30618.patch b/SOURCES/ansible-selinux-issue-30618.patch deleted file mode 100644 index 4110412..0000000 --- a/SOURCES/ansible-selinux-issue-30618.patch +++ /dev/null @@ -1,440 +0,0 @@ -diff --git a/lib/ansible/module_utils/facts/utils.py b/lib/ansible/module_utils/facts/utils.py -index 2446ae6..728934c 100644 ---- a/lib/ansible/module_utils/facts/utils.py -+++ b/lib/ansible/module_utils/facts/utils.py -@@ -36,9 +36,9 @@ def get_file_content(path, default=None, strip=True): - return data - - --def get_file_lines(path): -+def get_file_lines(path, strip=True): - '''get list of lines from file''' -- data = get_file_content(path) -+ data = get_file_content(path, strip=strip) - if data: - ret = data.splitlines() - else: -diff --git a/lib/ansible/modules/system/selinux.py b/lib/ansible/modules/system/selinux.py -index 7cd4011..7d1cb8d 100644 ---- a/lib/ansible/modules/system/selinux.py -+++ b/lib/ansible/modules/system/selinux.py -@@ -8,9 +8,11 @@ from __future__ import absolute_import, division, print_function - __metaclass__ = type - - --ANSIBLE_METADATA = {'metadata_version': '1.1', -- 'status': ['stableinterface'], -- 'supported_by': 'core'} -+ANSIBLE_METADATA = { -+ 'metadata_version': '1.1', -+ 'status': ['stableinterface'], -+ 'supported_by': 'core' -+} - - - DOCUMENTATION = ''' -@@ -59,21 +61,51 @@ EXAMPLES = ''' - state: disabled - ''' - -+RETURN = ''' -+msg: -+ description: Messages that describe changes that were made -+ returned: always -+ type: string -+ sample: Config SELinux state changed from 'disabled' to 'permissive' -+configfile: -+ description: Path to SELinux configuration file -+ returned: always -+ type: string -+ sample: /etc/selinux/config -+policy: -+ description: Name of the SELinux policy -+ returned: always -+ type: string -+ sample: targeted -+state: -+ description: SELinux mode -+ returned: always -+ type: string -+ sample: enforcing -+reboot_required: -+ description: Whether or not an reboot is required for the changes to take effect -+ returned: always -+ type: bool -+ sample: true -+''' -+ - import os - import re -+import tempfile - - try: - import selinux - HAS_SELINUX = True - except ImportError: - HAS_SELINUX = False -+ - from ansible.module_utils.basic import AnsibleModule - from ansible.module_utils.facts.utils import get_file_lines - - - # getter subroutines - def get_config_state(configfile): -- lines = get_file_lines(configfile) -+ lines = get_file_lines(configfile, strip=False) - - for line in lines: - stateline = re.match(r'^SELINUX=.*$', line) -@@ -82,7 +114,7 @@ def get_config_state(configfile): - - - def get_config_policy(configfile): -- lines = get_file_lines(configfile) -+ lines = get_file_lines(configfile, strip=False) - - for line in lines: - stateline = re.match(r'^SELINUXTYPE=.*$', line) -@@ -91,16 +123,19 @@ def get_config_policy(configfile): - - - # setter subroutines --def set_config_state(state, configfile): -+def set_config_state(module, state, configfile): - # SELINUX=permissive - # edit config file with state value - stateline = 'SELINUX=%s' % state -+ lines = get_file_lines(configfile, strip=False) - -- lines = get_file_lines(configfile) -+ tmpfd, tmpfile = tempfile.mkstemp() - -- with open(configfile, "w") as write_file: -+ with open(tmpfile, "w") as write_file: - for line in lines: -- write_file.write(re.sub(r'^SELINUX=.*', stateline, line)) -+ write_file.write(re.sub(r'^SELINUX=.*', stateline, line) + '\n') -+ -+ module.atomic_move(tmpfile, configfile) - - - def set_state(module, state): -@@ -115,15 +150,19 @@ def set_state(module, state): - module.fail_json(msg=msg) - - --def set_config_policy(policy, configfile): -+def set_config_policy(module, policy, configfile): - # edit config file with state value - # SELINUXTYPE=targeted - policyline = 'SELINUXTYPE=%s' % policy -- lines = get_file_lines(configfile) -+ lines = get_file_lines(configfile, strip=False) - -- with open(configfile, "w") as write_file: -+ tmpfd, tmpfile = tempfile.mkstemp() -+ -+ with open(tmpfile, "w") as write_file: - for line in lines: -- write_file.write(re.sub(r'^SELINUXTYPE=.*', policyline, line)) -+ write_file.write(re.sub(r'^SELINUXTYPE=.*', policyline, line) + '\n') -+ -+ module.atomic_move(tmpfile, configfile) - - - def main(): -@@ -148,6 +187,7 @@ def main(): - runtime_enabled = selinux.is_selinux_enabled() - runtime_policy = selinux.selinux_getpolicytype()[1] - runtime_state = 'disabled' -+ reboot_required = False - - if runtime_enabled: - # enabled means 'enforcing' or 'permissive' -@@ -167,7 +207,7 @@ def main(): - # check to see if policy is set if state is not 'disabled' - if state != 'disabled': - if not policy: -- module.fail_json(msg='policy is required if state is not \'disabled\'') -+ module.fail_json(msg='Policy is required if state is not \'disabled\'') - else: - if not policy: - policy = config_policy -@@ -177,14 +217,14 @@ def main(): - if module.check_mode: - module.exit_json(changed=True) - # cannot change runtime policy -- msgs.append('reboot to change the loaded policy') -+ msgs.append('Running SELinux policy changed from \'%s\' to \'%s\'' % (runtime_policy, policy)) - changed = True - - if policy != config_policy: - if module.check_mode: - module.exit_json(changed=True) -- msgs.append('config policy changed from \'%s\' to \'%s\'' % (config_policy, policy)) -- set_config_policy(policy, configfile) -+ set_config_policy(module, policy, configfile) -+ msgs.append('SELinux policy configuration in \'%s\' changed from \'%s\' to \'%s\'' % (configfile, config_policy, policy)) - changed = True - - if state != runtime_state: -@@ -195,26 +235,30 @@ def main(): - if runtime_state != 'permissive': - # Temporarily set state to permissive - set_state(module, 'permissive') -- msgs.append('runtime state temporarily changed from \'%s\' to \'permissive\', state change will take effect next reboot' % (runtime_state)) -+ module.warn('SELinux state temporarily changed from \'%s\' to \'permissive\'. State change will take effect next reboot.' % (runtime_state)) - else: -- msgs.append('state change will take effect next reboot') -+ module.warn('SELinux state change will take effect next reboot') -+ reboot_required = True - else: - set_state(module, state) -- msgs.append('runtime state changed from \'%s\' to \'%s\'' % (runtime_state, state)) -+ msgs.append('SELinux state changed from \'%s\' to \'%s\'' % (runtime_state, state)) -+ -+ # Only report changes if the file is changed. -+ # This prevents the task from reporting changes every time the task is run. -+ changed = True - else: -- msgs.append('state change will take effect next reboot') -- changed = True -+ module.warn("Reboot is required to set SELinux state to %s" % state) -+ reboot_required = True - - if state != config_state: - if module.check_mode: - module.exit_json(changed=True) -- msgs.append('config state changed from \'%s\' to \'%s\'' % (config_state, state)) -- set_config_state(state, configfile) -+ msgs.append('Config SELinux state changed from \'%s\' to \'%s\'' % (config_state, state)) -+ set_config_state(module, state, configfile) - changed = True - -- module.exit_json(changed=changed, msg=', '.join(msgs), configfile=configfile, policy=policy, state=state) -+ module.exit_json(changed=changed, msg=', '.join(msgs), configfile=configfile, policy=policy, state=state, reboot_required=reboot_required) - --################################################# - - if __name__ == '__main__': - main() -diff --git a/test/integration/targets/selinux/aliases b/test/integration/targets/selinux/aliases -new file mode 100644 -index 0000000..53b3251 ---- /dev/null -+++ b/test/integration/targets/selinux/aliases -@@ -0,0 +1,2 @@ -+needs/root -+posix/ci/group2 -diff --git a/test/integration/targets/selinux/tasks/main.yml b/test/integration/targets/selinux/tasks/main.yml -new file mode 100644 -index 0000000..dc3e678 ---- /dev/null -+++ b/test/integration/targets/selinux/tasks/main.yml -@@ -0,0 +1,30 @@ -+# (c) 2017, Sam Doran -+ -+# This file is part of Ansible -+# -+# Ansible is free software: you can redistribute it and/or modify -+# it under the terms of the GNU General Public License as published by -+# the Free Software Foundation, either version 3 of the License, or -+# (at your option) any later version. -+# -+# Ansible is distributed in the hope that it will be useful, -+# but WITHOUT ANY WARRANTY; without even the implied warranty of -+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+# GNU General Public License for more details. -+# -+# You should have received a copy of the GNU General Public License -+# along with Ansible. If not, see . -+ -+- debug: -+ msg: SELinux is disabled -+ when: ansible_selinux is defined and ansible_selinux == False -+ -+- debug: -+ msg: SELinux is {{ ansible_selinux.status }} -+ when: ansible_selinux is defined and ansible_selinux != False -+ -+- include: selinux.yml -+ when: -+ - ansible_selinux is defined -+ - ansible_selinux != False -+ - ansible_selinux.status == 'enabled' -diff --git a/test/integration/targets/selinux/tasks/selinux.yml b/test/integration/targets/selinux/tasks/selinux.yml -new file mode 100644 -index 0000000..ff8b2fa ---- /dev/null -+++ b/test/integration/targets/selinux/tasks/selinux.yml -@@ -0,0 +1,170 @@ -+# (c) 2017, Sam Doran -+ -+# This file is part of Ansible -+# -+# Ansible is free software: you can redistribute it and/or modify -+# it under the terms of the GNU General Public License as published by -+# the Free Software Foundation, either version 3 of the License, or -+# (at your option) any later version. -+# -+# Ansible is distributed in the hope that it will be useful, -+# but WITHOUT ANY WARRANTY; without even the implied warranty of -+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+# GNU General Public License for more details. -+# -+# You should have received a copy of the GNU General Public License -+# along with Ansible. If not, see . -+ -+ -+# First Test -+# ############################################################################## -+# Test changing the state, which requires a reboot -+ -+- name: TEST 1 | Get current SELinux config file contents -+ set_fact: -+ selinux_config_original: "{{ lookup('file', '/etc/sysconfig/selinux').split('\n') }}" -+ before_test_sestatus: "{{ ansible_selinux }}" -+ -+- debug: -+ var: "{{ item }}" -+ verbosity: 1 -+ with_items: -+ - selinux_config_original -+ - before_test_sestatus -+ - ansible_selinux -+ -+- name: TEST 1 | Setup SELinux configuration for tests -+ selinux: -+ state: enforcing -+ policy: targeted -+ -+- name: TEST 1 | Disable SELinux -+ selinux: -+ state: disabled -+ policy: targeted -+ register: _disable_test1 -+ -+- debug: -+ var: _disable_test1 -+ verbosity: 1 -+ -+- name: TEST 1 | Re-gather facts -+ setup: -+ -+- name: TEST 1 | Assert that status was changed, reboot_required is True, a warning was displayed, and SELinux is configured properly -+ assert: -+ that: -+ - _disable_test1 | changed -+ - _disable_test1.reboot_required -+ - (_disable_test1.warnings | length ) >= 1 -+ - ansible_selinux.config_mode == 'disabled' -+ - ansible_selinux.type == 'targeted' -+ -+- debug: -+ var: ansible_selinux -+ verbosity: 1 -+ -+- name: TEST 1 | Disable SELinux again -+ selinux: -+ state: disabled -+ policy: targeted -+ register: _disable_test2 -+ -+- debug: -+ var: _disable_test2 -+ verbosity: 1 -+ -+- name: TEST 1 | Assert that no change is reported, a warnking was dispalyed, and reboot_required is True -+ assert: -+ that: -+ - not _disable_test2 | changed -+ - (_disable_test1.warnings | length ) >= 1 -+ - _disable_test2.reboot_required -+ -+- name: TEST 1 | Get modified config file -+ set_fact: -+ selinux_config_after: "{{ lookup('file', '/etc/sysconfig/selinux').split('\n') }}" -+ -+- debug: -+ var: selinux_config_after -+ verbosity: 1 -+ -+- name: TEST 1 | Ensure SELinux config file is properly formatted -+ assert: -+ that: -+ - selinux_config_original | length == selinux_config_after | length -+ - selinux_config_after[selinux_config_after.index('SELINUX=disabled')] | search("^SELINUX=\w+$") -+ - selinux_config_after[selinux_config_after.index('SELINUXTYPE=targeted')] | search("^SELINUXTYPE=\w+$") -+ -+- name: TEST 1 | Reset SELinux configuration for next test -+ selinux: -+ state: enforcing -+ policy: targeted -+ -+ -+# Second Test -+# ############################################################################## -+# Test changing only the policy, which does not require a reboot -+ -+- name: TEST 2 | Set SELinux policy -+ selinux: -+ state: enforcing -+ policy: mls -+ register: _state_test1 -+ -+- debug: -+ var: _state_test1 -+ verbosity: 1 -+ -+- name: TEST 2 | Re-gather facts -+ setup: -+ -+- debug: -+ var: ansible_selinux -+ tags: debug -+ -+- name: TEST 2 | Assert that status was changed, reboot_required is False, no warnings were displayed, and SELinux is configured properly -+ assert: -+ that: -+ - _state_test1 | changed -+ - not _state_test1.reboot_required -+ - _state_test1.warnings is not defined -+ - ansible_selinux.config_mode == 'enforcing' -+ - ansible_selinux.type == 'mls' -+ -+- name: TEST 2 | Set SELinux policy again -+ selinux: -+ state: enforcing -+ policy: mls -+ register: _state_test2 -+ -+- debug: -+ var: _state_test2 -+ verbosity: 1 -+ -+- name: TEST 2 | Assert that no change was reported, no warnings were dispalyed, and reboot_required is False -+ assert: -+ that: -+ - not _state_test2 | changed -+ - _state_test2.warnings is not defined -+ - not _state_test2.reboot_required -+ -+- name: TEST 2 | Get modified config file -+ set_fact: -+ selinux_config_after: "{{ lookup('file', '/etc/sysconfig/selinux').split('\n') }}" -+ -+- debug: -+ var: selinux_config_after -+ verbosity: 1 -+ -+- name: TEST 2 | Ensure SELinux config file is properly formatted -+ assert: -+ that: -+ - selinux_config_original | length == selinux_config_after | length -+ - selinux_config_after[selinux_config_after.index('SELINUX=enforcing')] | search("^SELINUX=\w+$") -+ - selinux_config_after[selinux_config_after.index('SELINUXTYPE=mls')] | search("^SELINUXTYPE=\w+$") -+ -+- name: TEST 2 | Reset SELinux configuration for next test -+ selinux: -+ state: enforcing -+ policy: targeted diff --git a/SPECS/ansible.spec b/SPECS/ansible.spec index 77a2011..4ee9096 100644 --- a/SPECS/ansible.spec +++ b/SPECS/ansible.spec @@ -9,6 +9,12 @@ BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-buildroot %endif +%if 0%{?fedora} || 0%{?rhel} >= 8 +%global with_docs 1 +%else +%global with_docs 0 +%endif + %if 0%{?fedora} %global with_python3 1 %bcond_without tests @@ -21,8 +27,8 @@ BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-buildroot Name: ansible Summary: SSH-based configuration management, deployment, and task execution system -Version: 2.4.0.0 -Release: 5%{?dist} +Version: 2.4.1.0 +Release: 1%{?dist} Group: Development/Libraries License: GPLv3+ @@ -31,10 +37,6 @@ Source0: http://releases.ansible.com/ansible/%{name}-%{version}.tar.gz # Provides default search paths, among them /usr/share/ansible/roles, # which will be used in other packages Patch0: ansible-rolepath.patch -# Fixes CVE-2017-7550 -Patch1: ansible-pr-30875.patch -# Fixes upstream #30618 - broken selinux module -Patch2: ansible-selinux-issue-30618.patch # Patch to utilize a newer jinja2 package on epel6 # Non-upstreamable as it creates a dependency on a specific version of jinja. @@ -46,14 +48,12 @@ Url: http://ansible.com BuildArch: noarch %if 0%{?rhel} && 0%{?rhel} <= 5 +# On RHEL6 use the python26 stack BuildRequires: python26-devel - Requires: python26-PyYAML Requires: python26-paramiko Requires: python26-jinja2 -Requires: python26-keyczar - -%else +%endif BuildRequires: python2-devel BuildRequires: python-setuptools @@ -116,7 +116,10 @@ Requires: python-httplib2 Requires: python-setuptools Requires: python-six Requires: sshpass + +%if (0%{?fedora} || 0%{?rhel} > 6) # needed for json_query filter +# but avoid on rhel6 due to amazon linux conflicts Requires: python2-jmespath %endif @@ -213,8 +216,6 @@ This package installs extensive documentation for ansible %prep %setup -q %patch0 -p1 -%patch1 -p1 -%patch2 -p1 %if 0%{?rhel} == 6 %patch100 -p1 @@ -229,7 +230,7 @@ cp -a . %{py3dir} %{__python2} setup.py build # Build docs # EPEL6/7 don't have a recent enough sphinx to build the docs -%if 0%{?fedora} || 0%{?rhel} >= 8 +%if %with_docs make webdocs %endif @@ -245,8 +246,15 @@ pushd %{py3dir} popd for i in $RPM_BUILD_ROOT/%{_bindir}/ansible* ; do - mv $i $i-%{python3_version} - ln -s %{_bindir}/$(basename $i)-%{python3_version} $i-3 + if [ $(basename $i) = "ansible-connection" -o $(basename $i) = "ansible" ] ; then + mv $i $i-%{python3_version} + ln -s %{_bindir}/$(basename $i)-%{python3_version} $i-3 + else + # The ansible commands are themselves symlinks to /usr/bin/ansible. + # Need to change them to point to the python3 version + ln -s %{_bindir}/ansible-3 $i-%{python3_version} + ln -s %{_bindir}/$(basename $i)-%{python3_version} $i-3 + fi done %endif # with_python3 @@ -266,7 +274,7 @@ mkdir -p $RPM_BUILD_ROOT/%{_mandir}/man1 cp -v docs/man/man1/*.1 $RPM_BUILD_ROOT/%{_mandir}/man1/ cp -pr docs/docsite/rst . -%if 0%{?fedora} || 0%{?rhel} >= 8 +%if %with_docs cp -pr docs/docsite/_build/html . %endif @@ -328,11 +336,15 @@ rm -rf $RPM_BUILD_ROOT %files -n ansible-doc %doc rst -%if 0%{?fedora} || 0%{?rhel} >= 8 +%if %with_docs %doc html %endif %changelog +* Tue Nov 7 2017 Pavel Cahyna - 2.4.1.0-1 +- Sync with Fedora version 2.4.1.0-2, brings Ansible 2.4.1.0. +- Drop upstream patches. + * Tue Oct 3 2017 Pavel Cahyna - 2.4.0.0-5 - Backport a fix for the selinux module. Upstream github issue 30618