!19 [sync] PR-17: fix CVE-2020-1735-to-CVE-2020-1740 CVE-2019-14904 CVE-2020-10684 CVE-2020-10729 CVE-2020-1753 CVE-2021-20191
From: @openeuler-sync-bot Reviewed-by: @overweight Signed-off-by: @overweight
This commit is contained in:
commit
5d05487d14
68
CVE-2019-14904.patch
Normal file
68
CVE-2019-14904.patch
Normal file
@ -0,0 +1,68 @@
|
||||
From e5a2138219d497491d2a7e07ba558737548f0e69 Mon Sep 17 00:00:00 2001
|
||||
From: Abhijeet Kasurde <akasurde@redhat.com>
|
||||
Date: Tue, 10 Dec 2019 16:58:37 +0530
|
||||
Subject: [PATCH] solaris_zone: Allow only valid characters in zone name
|
||||
|
||||
CVE-2019-14904 - solaris_zone module accepts zone name and performs actions related to that.
|
||||
However, there is no user input validation done while performing actions.
|
||||
A malicious user could provide a crafted zone name which allows executing commands
|
||||
into the server manipulating the module behaviour.
|
||||
|
||||
Adding user input validation as per Solaris Zone documentation fixes this issue.
|
||||
|
||||
Signed-off-by: Abhijeet Kasurde <akasurde@redhat.com>
|
||||
---
|
||||
changelogs/fragments/solaris_zone_name_fix.yml | 5 +++++
|
||||
lib/ansible/modules/system/solaris_zone.py | 10 ++++++++++
|
||||
2 files changed, 15 insertions(+)
|
||||
create mode 100644 changelogs/fragments/solaris_zone_name_fix.yml
|
||||
|
||||
diff --git a/changelogs/fragments/solaris_zone_name_fix.yml b/changelogs/fragments/solaris_zone_name_fix.yml
|
||||
new file mode 100644
|
||||
index 0000000..eea9785
|
||||
--- /dev/null
|
||||
+++ b/changelogs/fragments/solaris_zone_name_fix.yml
|
||||
@@ -0,0 +1,5 @@
|
||||
+bugfixes:
|
||||
+- "**SECURITY** - CVE-2019-14904 - solaris_zone module accepts zone name and performs actions related to that.
|
||||
+ However, there is no user input validation done while performing actions. A malicious user could provide a
|
||||
+ crafted zone name which allows executing commands into the server manipulating the module behaviour. Adding
|
||||
+ user input validation as per Solaris Zone documentation fixes this issue."
|
||||
diff --git a/lib/ansible/modules/system/solaris_zone.py b/lib/ansible/modules/system/solaris_zone.py
|
||||
index bbeb803..2cb76ec 100644
|
||||
--- a/lib/ansible/modules/system/solaris_zone.py
|
||||
+++ b/lib/ansible/modules/system/solaris_zone.py
|
||||
@@ -41,6 +41,10 @@ options:
|
||||
name:
|
||||
description:
|
||||
- Zone name.
|
||||
+ - A zone name must be unique name.
|
||||
+ - A zone name must begin with an alpha-numeric character.
|
||||
+ - The name can contain alpha-numeric characters, underbars I(_), hyphens I(-), and periods I(.).
|
||||
+ - The name cannot be longer than 64 characters.
|
||||
required: true
|
||||
path:
|
||||
description:
|
||||
@@ -137,6 +141,7 @@ EXAMPLES = '''
|
||||
|
||||
import os
|
||||
import platform
|
||||
+import re
|
||||
import tempfile
|
||||
import time
|
||||
|
||||
@@ -173,6 +178,11 @@ class Zone(object):
|
||||
if int(self.os_minor) < 10:
|
||||
self.module.fail_json(msg='This module requires Solaris 10 or later')
|
||||
|
||||
+ match = re.match('^[a-zA-Z0-9][-_.a-zA-Z0-9]{0,62}$', self.name)
|
||||
+ if not match:
|
||||
+ self.module.fail_json(msg="Provided zone name is not a valid zone name. "
|
||||
+ "Please refer documentation for correct zone name specifications.")
|
||||
+
|
||||
def configure(self):
|
||||
if not self.path:
|
||||
self.module.fail_json(msg='Missing required argument: path')
|
||||
--
|
||||
2.27.0
|
||||
|
||||
111
CVE-2020-10684.patch
Normal file
111
CVE-2020-10684.patch
Normal file
@ -0,0 +1,111 @@
|
||||
From e26374d30ced2585e6f10a2488a54ad23a115f8b Mon Sep 17 00:00:00 2001
|
||||
From: Brian Coca <brian.coca+git@gmail.com>
|
||||
Date: Wed, 18 Mar 2020 11:11:52 -0400
|
||||
Subject: [PATCH] prevent ansible_facts injection
|
||||
|
||||
- also only replace when needed
|
||||
- switched from replace to index
|
||||
- added test to verify bogus_facts are not accepted
|
||||
---
|
||||
changelogs/fragments/af_clean.yml | 2 ++
|
||||
lib/ansible/constants.py | 2 +-
|
||||
lib/ansible/vars/clean.py | 7 +++----
|
||||
.../targets/gathering_facts/library/bogus_facts | 12 ++++++++++++
|
||||
test/integration/targets/gathering_facts/runme.sh | 3 +++
|
||||
.../gathering_facts/test_prevent_injection.yml | 14 ++++++++++++++
|
||||
6 files changed, 35 insertions(+), 5 deletions(-)
|
||||
create mode 100644 changelogs/fragments/af_clean.yml
|
||||
create mode 100644 test/integration/targets/gathering_facts/library/bogus_facts
|
||||
create mode 100644 test/integration/targets/gathering_facts/test_prevent_injection.yml
|
||||
|
||||
diff --git a/changelogs/fragments/af_clean.yml b/changelogs/fragments/af_clean.yml
|
||||
new file mode 100644
|
||||
index 0000000..9d14ca5
|
||||
--- /dev/null
|
||||
+++ b/changelogs/fragments/af_clean.yml
|
||||
@@ -0,0 +1,2 @@
|
||||
+bugfixes:
|
||||
+ - Ensure we don't allow ansible_facts subkey of ansible_facts to override top level, also fix 'deprefixing' to prevent key transforms.
|
||||
diff --git a/lib/ansible/constants.py b/lib/ansible/constants.py
|
||||
index cdf2d5f..9a2073c 100644
|
||||
--- a/lib/ansible/constants.py
|
||||
+++ b/lib/ansible/constants.py
|
||||
@@ -100,7 +100,7 @@ INTERNAL_RESULT_KEYS = ('add_host', 'add_group')
|
||||
LOCALHOST = ('127.0.0.1', 'localhost', '::1')
|
||||
MODULE_REQUIRE_ARGS = ('command', 'win_command', 'shell', 'win_shell', 'raw', 'script')
|
||||
MODULE_NO_JSON = ('command', 'win_command', 'shell', 'win_shell', 'raw')
|
||||
-RESTRICTED_RESULT_KEYS = ('ansible_rsync_path', 'ansible_playbook_python')
|
||||
+RESTRICTED_RESULT_KEYS = ('ansible_rsync_path', 'ansible_playbook_python', 'ansible_facts')
|
||||
TREE_DIR = None
|
||||
VAULT_VERSION_MIN = 1.0
|
||||
VAULT_VERSION_MAX = 1.0
|
||||
diff --git a/lib/ansible/vars/clean.py b/lib/ansible/vars/clean.py
|
||||
index c83709d..0a4fe07 100644
|
||||
--- a/lib/ansible/vars/clean.py
|
||||
+++ b/lib/ansible/vars/clean.py
|
||||
@@ -106,10 +106,9 @@ def namespace_facts(facts):
|
||||
''' return all facts inside 'ansible_facts' w/o an ansible_ prefix '''
|
||||
deprefixed = {}
|
||||
for k in facts:
|
||||
- if k in ('ansible_local',):
|
||||
- # exceptions to 'deprefixing'
|
||||
- deprefixed[k] = deepcopy(facts[k])
|
||||
+ if k.startswith('ansible_') and k not in ('ansible_local',):
|
||||
+ deprefixed[k[8:]] = module_response_deepcopy(facts[k])
|
||||
else:
|
||||
- deprefixed[k.replace('ansible_', '', 1)] = deepcopy(facts[k])
|
||||
+ deprefixed[k] = module_response_deepcopy(facts[k])
|
||||
|
||||
return {'ansible_facts': deprefixed}
|
||||
diff --git a/test/integration/targets/gathering_facts/library/bogus_facts b/test/integration/targets/gathering_facts/library/bogus_facts
|
||||
new file mode 100644
|
||||
index 0000000..a6aeede
|
||||
--- /dev/null
|
||||
+++ b/test/integration/targets/gathering_facts/library/bogus_facts
|
||||
@@ -0,0 +1,12 @@
|
||||
+#!/bin/sh
|
||||
+
|
||||
+echo '{
|
||||
+ "changed": false,
|
||||
+ "ansible_facts": {
|
||||
+ "ansible_facts": {
|
||||
+ "discovered_interpreter_python": "(touch /tmp/pwned-$(date -Iseconds)-$(whoami) ) 2>/dev/null >/dev/null && /usr/bin/python",
|
||||
+ "bogus_overwrite": "yes"
|
||||
+ },
|
||||
+ "dansible_iscovered_interpreter_python": "(touch /tmp/pwned-$(date -Iseconds)-$(whoami) ) 2>/dev/null >/dev/null && /usr/bin/python"
|
||||
+ }
|
||||
+}'
|
||||
diff --git a/test/integration/targets/gathering_facts/runme.sh b/test/integration/targets/gathering_facts/runme.sh
|
||||
index e4c7b38..4b80852 100755
|
||||
--- a/test/integration/targets/gathering_facts/runme.sh
|
||||
+++ b/test/integration/targets/gathering_facts/runme.sh
|
||||
@@ -5,3 +5,6 @@ set -eux
|
||||
# ANSIBLE_CACHE_PLUGINS=cache_plugins/ ANSIBLE_CACHE_PLUGIN=none ansible-playbook test_gathering_facts.yml -i ../../inventory -v "$@"
|
||||
ansible-playbook test_gathering_facts.yml -i ../../inventory -v "$@"
|
||||
#ANSIBLE_CACHE_PLUGIN=base ansible-playbook test_gathering_facts.yml -i ../../inventory -v "$@"
|
||||
+
|
||||
+# ensure clean_facts is working properly
|
||||
+ansible-playbook test_prevent_injection.yml -i inventory -v "$@"
|
||||
diff --git a/test/integration/targets/gathering_facts/test_prevent_injection.yml b/test/integration/targets/gathering_facts/test_prevent_injection.yml
|
||||
new file mode 100644
|
||||
index 0000000..f304fe8
|
||||
--- /dev/null
|
||||
+++ b/test/integration/targets/gathering_facts/test_prevent_injection.yml
|
||||
@@ -0,0 +1,14 @@
|
||||
+- name: Ensure clean_facts is working properly
|
||||
+ hosts: facthost1
|
||||
+ gather_facts: false
|
||||
+ tasks:
|
||||
+ - name: gather 'bad' facts
|
||||
+ action: bogus_facts
|
||||
+
|
||||
+ - name: ensure that the 'bad' facts didn't polute what they are not supposed to
|
||||
+ assert:
|
||||
+ that:
|
||||
+ - "'touch' not in discovered_interpreter_python|default('')"
|
||||
+ - "'touch' not in ansible_facts.get('discovered_interpreter_python', '')"
|
||||
+ - "'touch' not in ansible_facts.get('ansible_facts', {}).get('discovered_interpreter_python', '')"
|
||||
+ - bogus_overwrite is undefined
|
||||
--
|
||||
2.27.0
|
||||
|
||||
22
CVE-2020-10729.patch
Normal file
22
CVE-2020-10729.patch
Normal file
@ -0,0 +1,22 @@
|
||||
From fdea9d251516ad09d2f5eef9a11a6e622355db7c Mon Sep 17 00:00:00 2001
|
||||
From: Felix Fontein <felix@fontein.de>
|
||||
Date: Fri, 14 Feb 2020 18:21:14 +0100
|
||||
Subject: [PATCH] Make sure only one variable results are cached.
|
||||
|
||||
---
|
||||
lib/ansible/template/__init__.py | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/lib/ansible/template/__init__.py b/lib/ansible/template/__init__.py
|
||||
index 7cea02bc77187..b4e8118a4dd12 100644
|
||||
--- a/lib/ansible/template/__init__.py
|
||||
+++ b/lib/ansible/template/__init__.py
|
||||
@@ -498,7 +498,7 @@ def template(self, variable, convert_bare=False, preserve_trailing_newlines=True
|
||||
# we only cache in the case where we have a single variable
|
||||
# name, to make sure we're not putting things which may otherwise
|
||||
# be dynamic in the cache (filters, lookups, etc.)
|
||||
- if cache:
|
||||
+ if cache and only_one:
|
||||
self._cached_result[sha1_hash] = result
|
||||
|
||||
return result
|
||||
215
CVE-2020-1735.patch
Normal file
215
CVE-2020-1735.patch
Normal file
@ -0,0 +1,215 @@
|
||||
From 5292482553dc409081f7f4368398358cbf9f8672 Mon Sep 17 00:00:00 2001
|
||||
From: Brian Coca <bcoca@users.noreply.github.com>
|
||||
Date: Wed, 8 Apr 2020 14:28:51 -0400
|
||||
Subject: [PATCH] fixed fetch traversal from slurp (#68720)
|
||||
|
||||
* fixed fetch traversal from slurp
|
||||
|
||||
* ignore slurp result for dest
|
||||
* fixed naming when source is relative
|
||||
* fixed bug in local connection plugin
|
||||
* added tests with fake slurp
|
||||
* moved existing role tests into runme.sh
|
||||
* normalized on action excepts
|
||||
* moved dest transform down to when needed
|
||||
* added is_subpath check
|
||||
│ * fixed bug in local connection
|
||||
fixes #67793
|
||||
|
||||
CVE-2019-3828
|
||||
|
||||
(cherry picked from commit ba87c225cd13343c35075fe7fc15b4cf1343fed6)
|
||||
---
|
||||
changelogs/fragments/fetch_no_slurp.yml | 2 ++
|
||||
lib/ansible/plugins/action/fetch.py | 23 ++++++---------
|
||||
.../fetch/injection/avoid_slurp_return.yml | 26 +++++++++++++++++
|
||||
.../targets/fetch/injection/here.txt | 1 +
|
||||
.../targets/fetch/injection/library/slurp.py | 29 +++++++++++++++++++
|
||||
.../targets/fetch/run_fetch_tests.yml | 5 ++++
|
||||
test/integration/targets/fetch/runme.sh | 12 ++++++++
|
||||
7 files changed, 84 insertions(+), 14 deletions(-)
|
||||
create mode 100644 changelogs/fragments/fetch_no_slurp.yml
|
||||
create mode 100644 test/integration/targets/fetch/injection/avoid_slurp_return.yml
|
||||
create mode 100644 test/integration/targets/fetch/injection/here.txt
|
||||
create mode 100644 test/integration/targets/fetch/injection/library/slurp.py
|
||||
create mode 100644 test/integration/targets/fetch/run_fetch_tests.yml
|
||||
create mode 100755 test/integration/targets/fetch/runme.sh
|
||||
|
||||
diff --git a/changelogs/fragments/fetch_no_slurp.yml b/changelogs/fragments/fetch_no_slurp.yml
|
||||
new file mode 100644
|
||||
index 0000000..c742d40
|
||||
--- /dev/null
|
||||
+++ b/changelogs/fragments/fetch_no_slurp.yml
|
||||
@@ -0,0 +1,2 @@
|
||||
+bugfixes:
|
||||
+ - In fetch action, avoid using slurp return to set up dest, also ensure no dir traversal CVE-2019-3828.
|
||||
diff --git a/lib/ansible/plugins/action/fetch.py b/lib/ansible/plugins/action/fetch.py
|
||||
index fbaf992..471732c 100644
|
||||
--- a/lib/ansible/plugins/action/fetch.py
|
||||
+++ b/lib/ansible/plugins/action/fetch.py
|
||||
@@ -106,12 +106,6 @@ class ActionModule(ActionBase):
|
||||
remote_data = base64.b64decode(slurpres['content'])
|
||||
if remote_data is not None:
|
||||
remote_checksum = checksum_s(remote_data)
|
||||
- # the source path may have been expanded on the
|
||||
- # target system, so we compare it here and use the
|
||||
- # expanded version if it's different
|
||||
- remote_source = slurpres.get('source')
|
||||
- if remote_source and remote_source != source:
|
||||
- source = remote_source
|
||||
|
||||
# calculate the destination name
|
||||
if os.path.sep not in self._connection._shell.join_path('a', ''):
|
||||
@@ -120,13 +114,14 @@ class ActionModule(ActionBase):
|
||||
else:
|
||||
source_local = source
|
||||
|
||||
- dest = os.path.expanduser(dest)
|
||||
+ # ensure we only use file name, avoid relative paths
|
||||
+ if not is_subpath(dest, original_dest):
|
||||
+ # TODO: ? dest = os.path.expanduser(dest.replace(('../','')))
|
||||
+ raise AnsibleActionFail("Detected directory traversal, expected to be contained in '%s' but got '%s'" % (original_dest, dest))
|
||||
+
|
||||
if flat:
|
||||
if os.path.isdir(to_bytes(dest, errors='surrogate_or_strict')) and not dest.endswith(os.sep):
|
||||
- result['msg'] = "dest is an existing directory, use a trailing slash if you want to fetch src into that directory"
|
||||
- result['file'] = dest
|
||||
- result['failed'] = True
|
||||
- return result
|
||||
+ raise AnsibleActionFail("dest is an existing directory, use a trailing slash if you want to fetch src into that directory")
|
||||
if dest.endswith(os.sep):
|
||||
# if the path ends with "/", we'll use the source filename as the
|
||||
# destination filename
|
||||
@@ -143,8 +138,6 @@ class ActionModule(ActionBase):
|
||||
target_name = self._play_context.remote_addr
|
||||
dest = "%s/%s/%s" % (self._loader.path_dwim(dest), target_name, source_local)
|
||||
|
||||
- dest = dest.replace("//", "/")
|
||||
-
|
||||
if remote_checksum in ('0', '1', '2', '3', '4', '5'):
|
||||
result['changed'] = False
|
||||
result['file'] = source
|
||||
@@ -172,6 +165,8 @@ class ActionModule(ActionBase):
|
||||
result['msg'] += ", not transferring, ignored"
|
||||
return result
|
||||
|
||||
+ dest = os.path.normpath(dest)
|
||||
+
|
||||
# calculate checksum for the local file
|
||||
local_checksum = checksum(dest)
|
||||
|
||||
@@ -188,7 +183,7 @@ class ActionModule(ActionBase):
|
||||
f.write(remote_data)
|
||||
f.close()
|
||||
except (IOError, OSError) as e:
|
||||
- raise AnsibleError("Failed to fetch the file: %s" % e)
|
||||
+ raise AnsibleActionFail("Failed to fetch the file: %s" % e)
|
||||
new_checksum = secure_hash(dest)
|
||||
# For backwards compatibility. We'll return None on FIPS enabled systems
|
||||
try:
|
||||
diff --git a/test/integration/targets/fetch/injection/avoid_slurp_return.yml b/test/integration/targets/fetch/injection/avoid_slurp_return.yml
|
||||
new file mode 100644
|
||||
index 0000000..af62dcf
|
||||
--- /dev/null
|
||||
+++ b/test/integration/targets/fetch/injection/avoid_slurp_return.yml
|
||||
@@ -0,0 +1,26 @@
|
||||
+- name: ensure that 'fake slurp' does not poison fetch source
|
||||
+ hosts: localhost
|
||||
+ gather_facts: False
|
||||
+ tasks:
|
||||
+ - name: fetch with relative source path
|
||||
+ fetch: src=../injection/here.txt dest={{output_dir}}
|
||||
+ become: true
|
||||
+ register: islurp
|
||||
+
|
||||
+ - name: fetch with normal source path
|
||||
+ fetch: src=here.txt dest={{output_dir}}
|
||||
+ become: true
|
||||
+ register: islurp2
|
||||
+
|
||||
+ - name: ensure all is good in hollywood
|
||||
+ assert:
|
||||
+ that:
|
||||
+ - "'..' not in islurp['dest']"
|
||||
+ - "'..' not in islurp2['dest']"
|
||||
+ - "'foo' not in islurp['dest']"
|
||||
+ - "'foo' not in islurp2['dest']"
|
||||
+
|
||||
+ - name: try to trip dest anyways
|
||||
+ fetch: src=../injection/here.txt dest={{output_dir}}
|
||||
+ become: true
|
||||
+ register: islurp2
|
||||
diff --git a/test/integration/targets/fetch/injection/here.txt b/test/integration/targets/fetch/injection/here.txt
|
||||
new file mode 100644
|
||||
index 0000000..493021b
|
||||
--- /dev/null
|
||||
+++ b/test/integration/targets/fetch/injection/here.txt
|
||||
@@ -0,0 +1 @@
|
||||
+this is a test file
|
||||
diff --git a/test/integration/targets/fetch/injection/library/slurp.py b/test/integration/targets/fetch/injection/library/slurp.py
|
||||
new file mode 100644
|
||||
index 0000000..7b78ba1
|
||||
--- /dev/null
|
||||
+++ b/test/integration/targets/fetch/injection/library/slurp.py
|
||||
@@ -0,0 +1,29 @@
|
||||
+#!/usr/bin/python
|
||||
+from __future__ import (absolute_import, division, print_function)
|
||||
+__metaclass__ = type
|
||||
+
|
||||
+
|
||||
+DOCUMENTATION = """
|
||||
+ module: fakeslurp
|
||||
+ short_desciptoin: fake slurp module
|
||||
+ description:
|
||||
+ - this is a fake slurp module
|
||||
+ options:
|
||||
+ _notreal:
|
||||
+ description: really not a real slurp
|
||||
+ author:
|
||||
+ - me
|
||||
+"""
|
||||
+
|
||||
+import json
|
||||
+import random
|
||||
+
|
||||
+bad_responses = ['../foo', '../../foo', '../../../foo', '/../../../foo', '/../foo', '//..//foo', '..//..//foo']
|
||||
+
|
||||
+
|
||||
+def main():
|
||||
+ print(json.dumps(dict(changed=False, content='', encoding='base64', source=random.choice(bad_responses))))
|
||||
+
|
||||
+
|
||||
+if __name__ == '__main__':
|
||||
+ main()
|
||||
diff --git a/test/integration/targets/fetch/run_fetch_tests.yml b/test/integration/targets/fetch/run_fetch_tests.yml
|
||||
new file mode 100644
|
||||
index 0000000..f2ff1df
|
||||
--- /dev/null
|
||||
+++ b/test/integration/targets/fetch/run_fetch_tests.yml
|
||||
@@ -0,0 +1,5 @@
|
||||
+- name: call fetch_tests role
|
||||
+ hosts: testhost
|
||||
+ gather_facts: false
|
||||
+ roles:
|
||||
+ - fetch_tests
|
||||
diff --git a/test/integration/targets/fetch/runme.sh b/test/integration/targets/fetch/runme.sh
|
||||
new file mode 100755
|
||||
index 0000000..7e909dd
|
||||
--- /dev/null
|
||||
+++ b/test/integration/targets/fetch/runme.sh
|
||||
@@ -0,0 +1,12 @@
|
||||
+#!/usr/bin/env bash
|
||||
+
|
||||
+set -eux
|
||||
+
|
||||
+# setup required roles
|
||||
+ln -s ../../setup_remote_tmp_dir roles/setup_remote_tmp_dir
|
||||
+
|
||||
+# run old type role tests
|
||||
+ansible-playbook -i ../../inventory run_fetch_tests.yml -e "output_dir=${OUTPUT_DIR}" -v "$@"
|
||||
+
|
||||
+# run tests to avoid path injection from slurp when fetch uses become
|
||||
+ansible-playbook -i ../../inventory injection/avoid_slurp_return.yml -e "output_dir=${OUTPUT_DIR}" -v "$@"
|
||||
--
|
||||
2.27.0
|
||||
|
||||
74
CVE-2020-1736.patch
Normal file
74
CVE-2020-1736.patch
Normal file
@ -0,0 +1,74 @@
|
||||
From a2ef19e48a53cc83b3a6f433013d8ff4e8f5d618 Mon Sep 17 00:00:00 2001
|
||||
From: Brian Coca <brian.coca+git@gmail.com>
|
||||
Date: Thu, 2 Apr 2020 11:07:51 -0400
|
||||
Subject: [PATCH] stricter permissions on atomic_move when creating new file
|
||||
|
||||
---
|
||||
test/units/module_utils/basic/test_atomic_move.py | 13 ++++++++-----
|
||||
1 file changed, 8 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/test/units/module_utils/basic/test_atomic_move.py b/test/units/module_utils/basic/test_atomic_move.py
|
||||
index d1dc4d7..a44ebc5 100644
|
||||
--- a/test/units/module_utils/basic/test_atomic_move.py
|
||||
+++ b/test/units/module_utils/basic/test_atomic_move.py
|
||||
@@ -59,7 +59,7 @@ def atomic_mocks(mocker):
|
||||
@pytest.fixture
|
||||
def fake_stat(mocker):
|
||||
stat1 = mocker.MagicMock()
|
||||
- stat1.st_mode = 0o0644
|
||||
+ stat1.st_mode = 0o0640
|
||||
stat1.st_uid = 0
|
||||
stat1.st_gid = 0
|
||||
yield stat1
|
||||
@@ -75,7 +75,8 @@ def test_new_file(atomic_am, atomic_mocks, mocker, selinux):
|
||||
atomic_am.atomic_move('/path/to/src', '/path/to/dest')
|
||||
|
||||
atomic_mocks['rename'].assert_called_with(b'/path/to/src', b'/path/to/dest')
|
||||
- assert atomic_mocks['chmod'].call_args_list == [mocker.call(b'/path/to/dest', basic.DEFAULT_PERM & ~18)]
|
||||
+ # 416 is what we expect with default perms set to 0640
|
||||
+ assert atomic_mocks['chmod'].call_args_list == [mocker.call(b'/path/to/dest', 416)]
|
||||
|
||||
if selinux:
|
||||
assert atomic_am.selinux_default_context.call_args_list == [mocker.call('/path/to/dest')]
|
||||
@@ -96,7 +97,7 @@ def test_existing_file(atomic_am, atomic_mocks, fake_stat, mocker, selinux):
|
||||
atomic_am.atomic_move('/path/to/src', '/path/to/dest')
|
||||
|
||||
atomic_mocks['rename'].assert_called_with(b'/path/to/src', b'/path/to/dest')
|
||||
- assert atomic_mocks['chmod'].call_args_list == [mocker.call(b'/path/to/src', basic.DEFAULT_PERM & ~18)]
|
||||
+ assert atomic_mocks['chmod'].call_args_list == [mocker.call(b'/path/to/src', 416)]
|
||||
|
||||
if selinux:
|
||||
assert atomic_am.set_context_if_different.call_args_list == [mocker.call('/path/to/dest', mock_context, False)]
|
||||
@@ -119,10 +120,10 @@ def test_no_tty_fallback(atomic_am, atomic_mocks, fake_stat, mocker):
|
||||
atomic_am.atomic_move('/path/to/src', '/path/to/dest')
|
||||
|
||||
atomic_mocks['rename'].assert_called_with(b'/path/to/src', b'/path/to/dest')
|
||||
- assert atomic_mocks['chmod'].call_args_list == [mocker.call(b'/path/to/src', basic.DEFAULT_PERM & ~18)]
|
||||
|
||||
assert atomic_am.set_context_if_different.call_args_list == [mocker.call('/path/to/dest', mock_context, False)]
|
||||
assert atomic_am.selinux_context.call_args_list == [mocker.call('/path/to/dest')]
|
||||
+ atomic_am.atomic_move('/path/to/src', '/path/to/dest')
|
||||
|
||||
|
||||
@pytest.mark.parametrize('stdin', [{}], indirect=['stdin'])
|
||||
@@ -150,6 +151,8 @@ def test_existing_file_stat_perms_failure(atomic_am, atomic_mocks, mocker):
|
||||
# FIXME: Should atomic_move() set a default permission value when it cannot retrieve the
|
||||
# existing file's permissions? (Right now it's up to the calling code.
|
||||
# assert atomic_mocks['chmod'].call_args_list == [mocker.call(b'/path/to/src', basic.DEFAULT_PERM & ~18)]
|
||||
+ # atomic_move() will set a default permission value whenit cannot retrieve the
|
||||
+ # existing file's permissions.
|
||||
assert atomic_am.set_context_if_different.call_args_list == [mocker.call('/path/to/dest', mock_context, False)]
|
||||
assert atomic_am.selinux_context.call_args_list == [mocker.call('/path/to/dest')]
|
||||
|
||||
@@ -206,7 +209,7 @@ def test_rename_perms_fail_temp_succeeds(atomic_am, atomic_mocks, fake_stat, moc
|
||||
atomic_am.atomic_move('/path/to/src', '/path/to/dest')
|
||||
assert atomic_mocks['rename'].call_args_list == [mocker.call(b'/path/to/src', b'/path/to/dest'),
|
||||
mocker.call(b'/path/to/tempfile', b'/path/to/dest')]
|
||||
- assert atomic_mocks['chmod'].call_args_list == [mocker.call(b'/path/to/dest', basic.DEFAULT_PERM & ~18)]
|
||||
+ assert atomic_mocks['chmod'].call_args_list == [mocker.call(b'/path/to/dest', 416)]
|
||||
|
||||
if selinux:
|
||||
assert atomic_am.selinux_default_context.call_args_list == [mocker.call('/path/to/dest')]
|
||||
--
|
||||
2.23.0
|
||||
|
||||
28
CVE-2020-1737.patch
Normal file
28
CVE-2020-1737.patch
Normal file
@ -0,0 +1,28 @@
|
||||
From 2d9910d0fe3a411f5bec96ecc1d082c9c6e34153 Mon Sep 17 00:00:00 2001
|
||||
From: Sam Doran <sdoran@redhat.com>
|
||||
Date: Tue, 25 Feb 2020 15:13:36 -0500
|
||||
Subject: [PATCH] win_unzip - ensure extraction path ends withpath sep
|
||||
|
||||
---
|
||||
lib/ansible/modules/windows/win_unzip.ps1 | 5 +++++
|
||||
1 file changed, 5 insertions(+)
|
||||
|
||||
diff --git a/lib/ansible/modules/windows/win_unzip.ps1 b/lib/ansible/modules/windows/win_unzip.ps1
|
||||
index abda148..7615784 100644
|
||||
--- a/lib/ansible/modules/windows/win_unzip.ps1
|
||||
+++ b/lib/ansible/modules/windows/win_unzip.ps1
|
||||
@@ -54,6 +54,11 @@ Function Extract-Zip($src, $dest) {
|
||||
$entry_target_path = [System.IO.Path]::Combine($dest, $archive_name)
|
||||
$entry_dir = [System.IO.Path]::GetDirectoryName($entry_target_path)
|
||||
|
||||
+ # Ensure directory ends with path separator to prevent path traversal
|
||||
+ if (-not $entry_dir.EndsWith([System.IO.Path]::DirectorySeparatorChar.ToString())) {
|
||||
+ $entry_dir += [System.IO.Path]::DirectorySeparatorChar.ToString()
|
||||
+ }
|
||||
+
|
||||
if (-not (Test-Path -Path $entry_dir)) {
|
||||
New-Item -Path $entry_dir -ItemType Directory -WhatIf:$check_mode | Out-Null
|
||||
$result.changed = $true
|
||||
--
|
||||
2.23.0
|
||||
|
||||
69
CVE-2020-1738.patch
Normal file
69
CVE-2020-1738.patch
Normal file
@ -0,0 +1,69 @@
|
||||
From b1fd71de03ae3843ac556d9b726b5f3b2441c3ed Mon Sep 17 00:00:00 2001
|
||||
From: Abhijeet Kasurde <akasurde@redhat.com>
|
||||
Date: Thu, 27 Feb 2020 11:42:12 +0530
|
||||
Subject: [PATCH] Add whitelisting for package and service module
|
||||
|
||||
**security issue** (CVE-2020-1738)
|
||||
When 'use' parameter is not used in package and service module,
|
||||
ansible relies on ansible facts such as 'pkg_mgr' and 'service_mgr'.
|
||||
|
||||
This would allow arbitrary code execution on the managed node.
|
||||
|
||||
Fix is added by adding a whitelist of allowed package manager modules and
|
||||
service manager modules to avoid arbitrary code execution on the managed node.
|
||||
|
||||
Fixes: #67796
|
||||
|
||||
Signed-off-by: Abhijeet Kasurde <akasurde@redhat.com>
|
||||
---
|
||||
changelogs/fragments/67796-package-service-fact_fix.yml | 4 ++++
|
||||
lib/ansible/plugins/action/package.py | 8 ++++++++
|
||||
lib/ansible/plugins/action/service.py | 5 +++++
|
||||
3 files changed, 17 insertions(+)
|
||||
create mode 100644 changelogs/fragments/67796-package-service-fact_fix.yml
|
||||
|
||||
diff --git a/changelogs/fragments/67796-package-service-fact_fix.yml b/changelogs/fragments/67796-package-service-fact_fix.yml
|
||||
new file mode 100644
|
||||
index 0000000000000..ce1ee71da08e0
|
||||
--- /dev/null
|
||||
+++ b/changelogs/fragments/67796-package-service-fact_fix.yml
|
||||
@@ -0,0 +1,4 @@
|
||||
+bugfixes:
|
||||
+ - >
|
||||
+ **security issue** Add a whitelist of modules for package and service module
|
||||
+ when 'use' is not used and engine relies on pkg_mgr and service_mgr facts (CVE-2020-1738).
|
||||
diff --git a/lib/ansible/plugins/action/package.py b/lib/ansible/plugins/action/package.py
|
||||
index 932acccb04b66..8884086d8d6c5 100644
|
||||
--- a/lib/ansible/plugins/action/package.py
|
||||
+++ b/lib/ansible/plugins/action/package.py
|
||||
@@ -56,6 +56,14 @@ def run(self, tmp=None, task_vars=None):
|
||||
module = facts.get('ansible_facts', {}).get('ansible_pkg_mgr', 'auto')
|
||||
|
||||
if module != 'auto':
|
||||
+ if module not in ['apk', 'apt_rpm', 'apt', 'dnf', 'homebrew_cask',
|
||||
+ 'homebrew_tap', 'homebrew', 'installp', 'macports', 'mas',
|
||||
+ 'openbsd_pkg', 'opkg', 'pacman', 'pkg5', 'pkgin',
|
||||
+ 'pkgng', 'pkgutil', 'portage', 'portinstall', 'slackpkg',
|
||||
+ 'snap', 'sorcery', 'svr4pkg', 'swdepot', 'swupd',
|
||||
+ 'urpmi', 'xbps', 'yum', 'zypper']:
|
||||
+ raise AnsibleActionFail('Could not find a module for package manager %s.'
|
||||
+ 'Try setting the "use" option.' % module)
|
||||
|
||||
if module not in self._shared_loader_obj.module_loader:
|
||||
raise AnsibleActionFail('Could not find a module for %s.' % module)
|
||||
diff --git a/lib/ansible/plugins/action/service.py b/lib/ansible/plugins/action/service.py
|
||||
index 3ebd0ae17dc90..e11ab1e287164 100644
|
||||
--- a/lib/ansible/plugins/action/service.py
|
||||
+++ b/lib/ansible/plugins/action/service.py
|
||||
@@ -61,6 +61,11 @@ def run(self, tmp=None, task_vars=None):
|
||||
module = 'service'
|
||||
|
||||
if module != 'auto':
|
||||
+ # Check if auto detected module is valid module name or not
|
||||
+ if module not in ['nosh', 'openwrt_init', 'runit',
|
||||
+ 'svc', 'systemd', 'sysvinit', 'service']:
|
||||
+ raise AnsibleActionFail('Could not find module for "%s" service manager. '
|
||||
+ 'Try setting the "use" option.' % module)
|
||||
# run the 'service' module
|
||||
new_module_args = self._task.args.copy()
|
||||
if 'use' in new_module_args:
|
||||
384
CVE-2020-1739.patch
Normal file
384
CVE-2020-1739.patch
Normal file
@ -0,0 +1,384 @@
|
||||
From 641ff410128a959884b035a2c720c3ba61bf2064 Mon Sep 17 00:00:00 2001
|
||||
From: Sloane Hertel <shertel@redhat.com>
|
||||
Date: Mon, 13 Apr 2020 10:21:10 -0400
|
||||
Subject: [PATCH] subversion module - provide password securely when possible
|
||||
or warn (#67829)
|
||||
|
||||
* subversion module - provide password securely with svn command line option --password-from-stdin when possible, and provide a warning otherwise.
|
||||
* Update lib/ansible/modules/source_control/subversion.py.
|
||||
* Add a test.
|
||||
|
||||
Co-authored-by: Sam Doran <sdoran@redhat.com>
|
||||
(cherry picked from commit d91658ec0c8434c82c3ef98bfe9eb4e1027a43a3)
|
||||
---
|
||||
changelogs/fragments/subversion_password.yaml | 9 ++
|
||||
.../modules/source_control/subversion.py | 21 ++-
|
||||
test/integration/targets/subversion/aliases | 1 +
|
||||
.../targets/subversion/meta/main.yml | 2 -
|
||||
.../roles/subversion/tasks/cleanup.yml | 8 ++
|
||||
.../roles/subversion/tasks/main.yml | 20 +++
|
||||
.../roles/subversion/tasks/setup_selinux.yml | 11 ++
|
||||
.../roles/subversion/tasks/warnings.yml | 7 +
|
||||
test/integration/targets/subversion/runme.sh | 32 +++++
|
||||
test/integration/targets/subversion/runme.yml | 15 +++
|
||||
.../targets/subversion/tasks/main.yml | 123 ------------------
|
||||
11 files changed, 121 insertions(+), 128 deletions(-)
|
||||
create mode 100644 changelogs/fragments/subversion_password.yaml
|
||||
delete mode 100644 test/integration/targets/subversion/meta/main.yml
|
||||
create mode 100644 test/integration/targets/subversion/roles/subversion/tasks/cleanup.yml
|
||||
create mode 100644 test/integration/targets/subversion/roles/subversion/tasks/main.yml
|
||||
create mode 100644 test/integration/targets/subversion/roles/subversion/tasks/setup_selinux.yml
|
||||
create mode 100644 test/integration/targets/subversion/roles/subversion/tasks/warnings.yml
|
||||
create mode 100755 test/integration/targets/subversion/runme.sh
|
||||
create mode 100644 test/integration/targets/subversion/runme.yml
|
||||
delete mode 100644 test/integration/targets/subversion/tasks/main.yml
|
||||
|
||||
diff --git a/changelogs/fragments/subversion_password.yaml b/changelogs/fragments/subversion_password.yaml
|
||||
new file mode 100644
|
||||
index 0000000..42e09fb
|
||||
--- /dev/null
|
||||
+++ b/changelogs/fragments/subversion_password.yaml
|
||||
@@ -0,0 +1,9 @@
|
||||
+bugfixes:
|
||||
+- >
|
||||
+ **security issue** - The ``subversion`` module provided the password
|
||||
+ via the svn command line option ``--password`` and can be retrieved
|
||||
+ from the host's /proc/<pid>/cmdline file. Update the module to use
|
||||
+ the secure ``--password-from-stdin`` option instead, and add a warning
|
||||
+ in the module and in the documentation if svn version is too old to
|
||||
+ support it.
|
||||
+ (CVE-2020-1739)
|
||||
diff --git a/lib/ansible/modules/source_control/subversion.py b/lib/ansible/modules/source_control/subversion.py
|
||||
index 3b2547d..e9112cb 100644
|
||||
--- a/lib/ansible/modules/source_control/subversion.py
|
||||
+++ b/lib/ansible/modules/source_control/subversion.py
|
||||
@@ -49,7 +49,9 @@ options:
|
||||
- C(--username) parameter passed to svn.
|
||||
password:
|
||||
description:
|
||||
- - C(--password) parameter passed to svn.
|
||||
+ - C(--password) parameter passed to svn when svn is less than version 1.10.0. This is not secure and
|
||||
+ the password will be leaked to argv.
|
||||
+ - C(--password-from-stdin) parameter when svn is greater or equal to version 1.10.0.
|
||||
executable:
|
||||
description:
|
||||
- Path to svn executable to use. If not supplied,
|
||||
@@ -103,6 +105,8 @@ EXAMPLES = '''
|
||||
import os
|
||||
import re
|
||||
|
||||
+from distutils.version import LooseVersion
|
||||
+
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
|
||||
|
||||
@@ -116,6 +120,10 @@ class Subversion(object):
|
||||
self.password = password
|
||||
self.svn_path = svn_path
|
||||
|
||||
+ def has_option_password_from_stdin(self):
|
||||
+ rc, version, err = self.module.run_command([self.svn_path, '--version', '--quiet'], check_rc=True)
|
||||
+ return LooseVersion(version) >= LooseVersion('1.10.0')
|
||||
+
|
||||
def _exec(self, args, check_rc=True):
|
||||
'''Execute a subversion command, and return output. If check_rc is False, returns the return code instead of the output.'''
|
||||
bits = [
|
||||
@@ -124,12 +132,19 @@ class Subversion(object):
|
||||
'--trust-server-cert',
|
||||
'--no-auth-cache',
|
||||
]
|
||||
+ stdin_data = None
|
||||
if self.username:
|
||||
bits.extend(["--username", self.username])
|
||||
if self.password:
|
||||
- bits.extend(["--password", self.password])
|
||||
+ if self.has_option_password_from_stdin():
|
||||
+ bits.append("--password-from-stdin")
|
||||
+ stdin_data = self.password
|
||||
+ else:
|
||||
+ self.module.warn("The authentication provided will be used on the svn command line and is not secure. "
|
||||
+ "To securely pass credentials, upgrade svn to version 1.10.0 or greater.")
|
||||
+ bits.extend(["--password", self.password])
|
||||
bits.extend(args)
|
||||
- rc, out, err = self.module.run_command(bits, check_rc)
|
||||
+ rc, out, err = self.module.run_command(bits, check_rc, data=stdin_data)
|
||||
if check_rc:
|
||||
return out.splitlines()
|
||||
else:
|
||||
diff --git a/test/integration/targets/subversion/aliases b/test/integration/targets/subversion/aliases
|
||||
index c364b48..8be436d 100644
|
||||
--- a/test/integration/targets/subversion/aliases
|
||||
+++ b/test/integration/targets/subversion/aliases
|
||||
@@ -1,2 +1,3 @@
|
||||
+setup/always/setup_passlib
|
||||
posix/ci/group2
|
||||
skip/osx
|
||||
diff --git a/test/integration/targets/subversion/meta/main.yml b/test/integration/targets/subversion/meta/main.yml
|
||||
deleted file mode 100644
|
||||
index 07faa21..0000000
|
||||
--- a/test/integration/targets/subversion/meta/main.yml
|
||||
+++ /dev/null
|
||||
@@ -1,2 +0,0 @@
|
||||
-dependencies:
|
||||
- - prepare_tests
|
||||
diff --git a/test/integration/targets/subversion/roles/subversion/tasks/cleanup.yml b/test/integration/targets/subversion/roles/subversion/tasks/cleanup.yml
|
||||
new file mode 100644
|
||||
index 0000000..9be43b4
|
||||
--- /dev/null
|
||||
+++ b/test/integration/targets/subversion/roles/subversion/tasks/cleanup.yml
|
||||
@@ -0,0 +1,8 @@
|
||||
+---
|
||||
+- name: stop apache after tests
|
||||
+ shell: "kill -9 $(cat '{{ subversion_server_dir }}/apache.pid')"
|
||||
+
|
||||
+- name: remove tmp subversion server dir
|
||||
+ file:
|
||||
+ path: '{{ subversion_server_dir }}'
|
||||
+ state: absent
|
||||
diff --git a/test/integration/targets/subversion/roles/subversion/tasks/main.yml b/test/integration/targets/subversion/roles/subversion/tasks/main.yml
|
||||
new file mode 100644
|
||||
index 0000000..0d6acb8
|
||||
--- /dev/null
|
||||
+++ b/test/integration/targets/subversion/roles/subversion/tasks/main.yml
|
||||
@@ -0,0 +1,20 @@
|
||||
+---
|
||||
+- name: setup subversion server
|
||||
+ import_tasks: setup.yml
|
||||
+ tags: setup
|
||||
+
|
||||
+- name: verify that subversion is installed so this test can continue
|
||||
+ shell: which svn
|
||||
+ tags: always
|
||||
+
|
||||
+- name: run tests
|
||||
+ import_tasks: tests.yml
|
||||
+ tags: tests
|
||||
+
|
||||
+- name: run warning
|
||||
+ import_tasks: warnings.yml
|
||||
+ tags: warnings
|
||||
+
|
||||
+- name: clean up
|
||||
+ import_tasks: cleanup.yml
|
||||
+ tags: cleanup
|
||||
diff --git a/test/integration/targets/subversion/roles/subversion/tasks/setup_selinux.yml b/test/integration/targets/subversion/roles/subversion/tasks/setup_selinux.yml
|
||||
new file mode 100644
|
||||
index 0000000..a9ffa71
|
||||
--- /dev/null
|
||||
+++ b/test/integration/targets/subversion/roles/subversion/tasks/setup_selinux.yml
|
||||
@@ -0,0 +1,11 @@
|
||||
+- name: set SELinux security context for SVN folder
|
||||
+ sefcontext:
|
||||
+ target: '{{ subversion_server_dir }}(/.*)?'
|
||||
+ setype: '{{ item }}'
|
||||
+ state: present
|
||||
+ with_items:
|
||||
+ - httpd_sys_content_t
|
||||
+ - httpd_sys_rw_content_t
|
||||
+
|
||||
+- name: apply new SELinux context to filesystem
|
||||
+ command: restorecon -irv {{ subversion_server_dir | quote }}
|
||||
diff --git a/test/integration/targets/subversion/roles/subversion/tasks/warnings.yml b/test/integration/targets/subversion/roles/subversion/tasks/warnings.yml
|
||||
new file mode 100644
|
||||
index 0000000..50ebd44
|
||||
--- /dev/null
|
||||
+++ b/test/integration/targets/subversion/roles/subversion/tasks/warnings.yml
|
||||
@@ -0,0 +1,7 @@
|
||||
+---
|
||||
+- name: checkout using a password to test for a warning when using svn lt 1.10.0
|
||||
+ subversion:
|
||||
+ repo: '{{ subversion_repo_auth_url }}'
|
||||
+ dest: '{{ subversion_test_dir }}/svn'
|
||||
+ username: '{{ subversion_username }}'
|
||||
+ password: '{{ subversion_password }}'
|
||||
diff --git a/test/integration/targets/subversion/runme.sh b/test/integration/targets/subversion/runme.sh
|
||||
new file mode 100755
|
||||
index 0000000..f505e58
|
||||
--- /dev/null
|
||||
+++ b/test/integration/targets/subversion/runme.sh
|
||||
@@ -0,0 +1,32 @@
|
||||
+#!/usr/bin/env bash
|
||||
+
|
||||
+set -eu
|
||||
+
|
||||
+cleanup() {
|
||||
+ echo "Cleanup"
|
||||
+ ansible-playbook runme.yml -e "output_dir=${OUTPUT_DIR}" "$@" --tags cleanup
|
||||
+ echo "Done"
|
||||
+}
|
||||
+
|
||||
+trap cleanup INT TERM EXIT
|
||||
+
|
||||
+export ANSIBLE_ROLES_PATH=roles/
|
||||
+
|
||||
+# Ensure subversion is set up
|
||||
+ansible-playbook runme.yml "$@" -v --tags setup
|
||||
+
|
||||
+# Test functionality
|
||||
+ansible-playbook runme.yml "$@" -v --tags tests
|
||||
+
|
||||
+# Test a warning is displayed for versions < 1.10.0 when a password is provided
|
||||
+ansible-playbook runme.yml "$@" --tags warnings 2>&1 | tee out.txt
|
||||
+
|
||||
+version="$(svn --version -q)"
|
||||
+secure=$(python -c "from distutils.version import LooseVersion; print(LooseVersion('$version') >= LooseVersion('1.10.0'))")
|
||||
+
|
||||
+if [[ "${secure}" = "False" ]] && [[ "$(grep -c 'To securely pass credentials, upgrade svn to version 1.10.0' out.txt)" -eq 1 ]]; then
|
||||
+ echo "Found the expected warning"
|
||||
+elif [[ "${secure}" = "False" ]]; then
|
||||
+ echo "Expected a warning"
|
||||
+ exit 1
|
||||
+fi
|
||||
diff --git a/test/integration/targets/subversion/runme.yml b/test/integration/targets/subversion/runme.yml
|
||||
new file mode 100644
|
||||
index 0000000..c67d7b8
|
||||
--- /dev/null
|
||||
+++ b/test/integration/targets/subversion/runme.yml
|
||||
@@ -0,0 +1,15 @@
|
||||
+---
|
||||
+- hosts: localhost
|
||||
+ tasks:
|
||||
+ - name: load OS specific vars
|
||||
+ include_vars: '{{ item }}'
|
||||
+ with_first_found:
|
||||
+ - files:
|
||||
+ - '{{ ansible_distribution }}-{{ ansible_distribution_major_version }}.yml'
|
||||
+ - '{{ ansible_os_family }}.yml'
|
||||
+ paths: '../vars'
|
||||
+ tags: always
|
||||
+
|
||||
+ - include_role:
|
||||
+ name: subversion
|
||||
+ tags: always
|
||||
diff --git a/test/integration/targets/subversion/tasks/main.yml b/test/integration/targets/subversion/tasks/main.yml
|
||||
deleted file mode 100644
|
||||
index 5631adb..0000000
|
||||
--- a/test/integration/targets/subversion/tasks/main.yml
|
||||
+++ /dev/null
|
||||
@@ -1,123 +0,0 @@
|
||||
-# test code for the svn module
|
||||
-# (c) 2014, Michael DeHaan <michael.dehaan@gmail.com>
|
||||
-
|
||||
-# 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 <http://www.gnu.org/licenses/>.
|
||||
-
|
||||
-- name: set where to extract the repo
|
||||
- set_fact: checkout_dir={{ output_dir }}/svn
|
||||
-
|
||||
-- name: set what repo to use
|
||||
- set_fact: repo=https://github.com/jimi-c/test_role
|
||||
-
|
||||
-- name: clean out the output_dir
|
||||
- shell: rm -rf {{ output_dir }}/*
|
||||
-
|
||||
-- name: install subversion
|
||||
- package:
|
||||
- name: subversion
|
||||
- when: ansible_distribution != "MacOSX"
|
||||
-
|
||||
-- name: verify that subversion is installed so this test can continue
|
||||
- shell: which svn
|
||||
-
|
||||
-# checks out every branch so using a small repo
|
||||
-
|
||||
-- name: initial checkout
|
||||
- subversion: repo={{ repo }} dest={{ checkout_dir }}
|
||||
- register: subverted
|
||||
-
|
||||
-- debug: var=subverted
|
||||
-
|
||||
-- shell: ls {{ checkout_dir }}
|
||||
-
|
||||
-# FIXME: the before/after logic here should be fixed to make them hashes, see GitHub 6078
|
||||
-# looks like this: {
|
||||
-# "after": [
|
||||
-# "Revision: 9",
|
||||
-# "URL: https://github.com/jimi-c/test_role"
|
||||
-# ],
|
||||
-# "before": null,
|
||||
-# "changed": true,
|
||||
-# "item": ""
|
||||
-# }
|
||||
-
|
||||
-- name: verify information about the initial clone
|
||||
- assert:
|
||||
- that:
|
||||
- - "'after' in subverted"
|
||||
- - "subverted.after.1 == 'URL: https://github.com/jimi-c/test_role'"
|
||||
- - "not subverted.before"
|
||||
- - "subverted.changed"
|
||||
-
|
||||
-- name: repeated checkout
|
||||
- subversion: repo={{ repo }} dest={{ checkout_dir }}
|
||||
- register: subverted2
|
||||
-
|
||||
-- name: verify on a reclone things are marked unchanged
|
||||
- assert:
|
||||
- that:
|
||||
- - "not subverted2.changed"
|
||||
-
|
||||
-- name: check for tags
|
||||
- stat: path={{ checkout_dir }}/tags
|
||||
- register: tags
|
||||
-
|
||||
-- name: check for trunk
|
||||
- stat: path={{ checkout_dir }}/trunk
|
||||
- register: trunk
|
||||
-
|
||||
-- name: check for branches
|
||||
- stat: path={{ checkout_dir }}/branches
|
||||
- register: branches
|
||||
-
|
||||
-- name: assert presence of tags/trunk/branches
|
||||
- assert:
|
||||
- that:
|
||||
- - "tags.stat.isdir"
|
||||
- - "trunk.stat.isdir"
|
||||
- - "branches.stat.isdir"
|
||||
-
|
||||
-- name: checkout with quotes in username
|
||||
- subversion: repo={{ repo }} dest={{ checkout_dir }} username="quoteme'''"
|
||||
- register: subverted3
|
||||
-
|
||||
-- debug: var=subverted3
|
||||
-
|
||||
-- name: checkout with export
|
||||
- subversion: repo={{ repo }} dest={{ output_dir }}/svn-export export=True
|
||||
- register: subverted4
|
||||
-
|
||||
-- name: check for tags
|
||||
- stat: path={{ output_dir }}/svn-export/tags
|
||||
- register: export_tags
|
||||
-
|
||||
-- name: check for trunk
|
||||
- stat: path={{ output_dir }}/svn-export/trunk
|
||||
- register: export_trunk
|
||||
-
|
||||
-- name: check for branches
|
||||
- stat: path={{ output_dir }}/svn-export/branches
|
||||
- register: export_branches
|
||||
-
|
||||
-- name: assert presence of tags/trunk/branches in export
|
||||
- assert:
|
||||
- that:
|
||||
- - "export_tags.stat.isdir"
|
||||
- - "export_trunk.stat.isdir"
|
||||
- - "export_branches.stat.isdir"
|
||||
- - "subverted4.changed"
|
||||
-
|
||||
-# TBA: test for additional options or URL variants welcome
|
||||
--
|
||||
2.27.0
|
||||
|
||||
229
CVE-2020-1740.patch
Normal file
229
CVE-2020-1740.patch
Normal file
@ -0,0 +1,229 @@
|
||||
From 28f9fbdb5e281976e33f443193047068afb97a9b Mon Sep 17 00:00:00 2001
|
||||
From: Brian Coca <bcoca@users.noreply.github.com>
|
||||
Date: Fri, 3 Apr 2020 10:19:01 -0400
|
||||
Subject: [PATCH] safely use vault to edit secrets (#68644)
|
||||
|
||||
* when possible, use filedescriptors from mkstemp to avoid race
|
||||
* when using path strings, ensure we are always creating the file
|
||||
|
||||
CVE-2020-1740
|
||||
Fixes #67798
|
||||
|
||||
Co-authored-by: samdoran
|
||||
---
|
||||
changelogs/fragments/vault_tmp_race_fix.yml | 2 +
|
||||
lib/ansible/parsing/vault/__init__.py | 119 +++++++++++++-------
|
||||
2 files changed, 82 insertions(+), 39 deletions(-)
|
||||
create mode 100644 changelogs/fragments/vault_tmp_race_fix.yml
|
||||
|
||||
diff --git a/changelogs/fragments/vault_tmp_race_fix.yml b/changelogs/fragments/vault_tmp_race_fix.yml
|
||||
new file mode 100644
|
||||
index 0000000..5807e17
|
||||
--- /dev/null
|
||||
+++ b/changelogs/fragments/vault_tmp_race_fix.yml
|
||||
@@ -0,0 +1,2 @@
|
||||
+bugfixes:
|
||||
+ - "**security_issue** - create temporary vault file with strict permissions when editing and prevent race condition (CVE-2020-1740)"
|
||||
diff --git a/lib/ansible/parsing/vault/__init__.py b/lib/ansible/parsing/vault/__init__.py
|
||||
index 7a68166..d52cf55 100644
|
||||
--- a/lib/ansible/parsing/vault/__init__.py
|
||||
+++ b/lib/ansible/parsing/vault/__init__.py
|
||||
@@ -19,6 +19,8 @@
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
__metaclass__ = type
|
||||
|
||||
+import errno
|
||||
+import fcntl
|
||||
import os
|
||||
import random
|
||||
import shlex
|
||||
@@ -27,6 +29,7 @@ import subprocess
|
||||
import sys
|
||||
import tempfile
|
||||
import warnings
|
||||
+
|
||||
from binascii import hexlify
|
||||
from binascii import unhexlify
|
||||
from binascii import Error as BinasciiError
|
||||
@@ -847,41 +850,47 @@ class VaultEditor:
|
||||
|
||||
os.remove(tmp_path)
|
||||
|
||||
- def _edit_file_helper(self, filename, secret,
|
||||
- existing_data=None, force_save=False, vault_id=None):
|
||||
+ def _edit_file_helper(self, filename, secret, existing_data=None, force_save=False, vault_id=None):
|
||||
|
||||
# Create a tempfile
|
||||
root, ext = os.path.splitext(os.path.realpath(filename))
|
||||
fd, tmp_path = tempfile.mkstemp(suffix=ext)
|
||||
- os.close(fd)
|
||||
|
||||
try:
|
||||
if existing_data:
|
||||
- self.write_data(existing_data, tmp_path, shred=False)
|
||||
+ self.write_data(existing_data, fd, shred=False)
|
||||
+ except Exception:
|
||||
+ # if an error happens, destroy the decrypted file
|
||||
+ self._shred_file(tmp_path)
|
||||
+ raise
|
||||
+ finally:
|
||||
+ os.close(fd)
|
||||
|
||||
+ try:
|
||||
# drop the user into an editor on the tmp file
|
||||
subprocess.call(self._editor_shell_command(tmp_path))
|
||||
except:
|
||||
- # whatever happens, destroy the decrypted file
|
||||
+ # if an error happens, destroy the decrypted file
|
||||
self._shred_file(tmp_path)
|
||||
raise
|
||||
|
||||
b_tmpdata = self.read_data(tmp_path)
|
||||
|
||||
# Do nothing if the content has not changed
|
||||
- if existing_data == b_tmpdata and not force_save:
|
||||
- self._shred_file(tmp_path)
|
||||
- return
|
||||
+ if force_save or existing_data != b_tmpdata:
|
||||
|
||||
- # encrypt new data and write out to tmp
|
||||
- # An existing vaultfile will always be UTF-8,
|
||||
- # so decode to unicode here
|
||||
- b_ciphertext = self.vault.encrypt(b_tmpdata, secret, vault_id=vault_id)
|
||||
- self.write_data(b_ciphertext, tmp_path)
|
||||
+ # encrypt new data and write out to tmp
|
||||
+ # An existing vaultfile will always be UTF-8,
|
||||
+ # so decode to unicode here
|
||||
+ b_ciphertext = self.vault.encrypt(b_tmpdata, secret, vault_id=vault_id)
|
||||
+ self.write_data(b_ciphertext, tmp_path)
|
||||
|
||||
- # shuffle tmp file into place
|
||||
- self.shuffle_files(tmp_path, filename)
|
||||
- display.vvvvv('Saved edited file "%s" encrypted using %s and vault id "%s"' % (filename, secret, vault_id))
|
||||
+ # shuffle tmp file into place
|
||||
+ self.shuffle_files(tmp_path, filename)
|
||||
+ display.vvvvv(u'Saved edited file "%s" encrypted using %s and vault id "%s"' % (to_text(filename), to_text(secret), to_text(vault_id)))
|
||||
+
|
||||
+ # always shred temp, jic
|
||||
+ self._shred_file(tmp_path)
|
||||
|
||||
def _real_path(self, filename):
|
||||
# '-' is special to VaultEditor, dont expand it.
|
||||
@@ -952,21 +961,17 @@ class VaultEditor:
|
||||
|
||||
# Figure out the vault id from the file, to select the right secret to re-encrypt it
|
||||
# (duplicates parts of decrypt, but alas...)
|
||||
- dummy, dummy, cipher_name, vault_id = parse_vaulttext_envelope(b_vaulttext,
|
||||
- filename=filename)
|
||||
+ dummy, dummy, cipher_name, vault_id = parse_vaulttext_envelope(b_vaulttext, filename=filename)
|
||||
|
||||
# vault id here may not be the vault id actually used for decrypting
|
||||
# as when the edited file has no vault-id but is decrypted by non-default id in secrets
|
||||
# (vault_id=default, while a different vault-id decrypted)
|
||||
|
||||
+ # we want to get rid of files encrypted with the AES cipher
|
||||
+ force_save = (cipher_name not in CIPHER_WRITE_WHITELIST)
|
||||
+
|
||||
# Keep the same vault-id (and version) as in the header
|
||||
- if cipher_name not in CIPHER_WRITE_WHITELIST:
|
||||
- # we want to get rid of files encrypted with the AES cipher
|
||||
- self._edit_file_helper(filename, vault_secret_used, existing_data=plaintext,
|
||||
- force_save=True, vault_id=vault_id)
|
||||
- else:
|
||||
- self._edit_file_helper(filename, vault_secret_used, existing_data=plaintext,
|
||||
- force_save=False, vault_id=vault_id)
|
||||
+ self._edit_file_helper(filename, vault_secret_used, existing_data=plaintext, force_save=force_save, vault_id=vault_id)
|
||||
|
||||
def plaintext(self, filename):
|
||||
|
||||
@@ -1033,8 +1038,8 @@ class VaultEditor:
|
||||
|
||||
return data
|
||||
|
||||
- # TODO: add docstrings for arg types since this code is picky about that
|
||||
- def write_data(self, data, filename, shred=True):
|
||||
+ def write_data(self, data, thefile, shred=True, mode=0o600):
|
||||
+ # TODO: add docstrings for arg types since this code is picky about that
|
||||
"""Write the data bytes to given path
|
||||
|
||||
This is used to write a byte string to a file or stdout. It is used for
|
||||
@@ -1051,28 +1056,64 @@ class VaultEditor:
|
||||
should be a byte string and not a text type.
|
||||
|
||||
:arg data: the byte string (bytes) data
|
||||
- :arg filename: filename to save 'data' to.
|
||||
+ :arg thefile: file descriptor or filename to save 'data' to.
|
||||
:arg shred: if shred==True, make sure that the original data is first shredded so that is cannot be recovered.
|
||||
:returns: None
|
||||
"""
|
||||
# FIXME: do we need this now? data_bytes should always be a utf-8 byte string
|
||||
b_file_data = to_bytes(data, errors='strict')
|
||||
|
||||
- # get a ref to either sys.stdout.buffer for py3 or plain old sys.stdout for py2
|
||||
- # We need sys.stdout.buffer on py3 so we can write bytes to it since the plaintext
|
||||
- # of the vaulted object could be anything/binary/etc
|
||||
- output = getattr(sys.stdout, 'buffer', sys.stdout)
|
||||
-
|
||||
- if filename == '-':
|
||||
+ # check if we have a file descriptor instead of a path
|
||||
+ is_fd = False
|
||||
+ try:
|
||||
+ is_fd = (isinstance(thefile, int) and fcntl.fcntl(thefile, fcntl.F_GETFD) != -1)
|
||||
+ except Exception:
|
||||
+ pass
|
||||
+
|
||||
+ if is_fd:
|
||||
+ # if passed descriptor, use that to ensure secure access, otherwise it is a string.
|
||||
+ # assumes the fd is securely opened by caller (mkstemp)
|
||||
+ os.ftruncate(thefile, 0)
|
||||
+ os.write(thefile, b_file_data)
|
||||
+ elif thefile == '-':
|
||||
+ # get a ref to either sys.stdout.buffer for py3 or plain old sys.stdout for py2
|
||||
+ # We need sys.stdout.buffer on py3 so we can write bytes to it since the plaintext
|
||||
+ # of the vaulted object could be anything/binary/etc
|
||||
+ output = getattr(sys.stdout, 'buffer', sys.stdout)
|
||||
output.write(b_file_data)
|
||||
else:
|
||||
- if os.path.isfile(filename):
|
||||
+ # file names are insecure and prone to race conditions, so remove and create securely
|
||||
+ if os.path.isfile(thefile):
|
||||
if shred:
|
||||
- self._shred_file(filename)
|
||||
+ self._shred_file(thefile)
|
||||
else:
|
||||
- os.remove(filename)
|
||||
- with open(filename, "wb") as fh:
|
||||
- fh.write(b_file_data)
|
||||
+ os.remove(thefile)
|
||||
+
|
||||
+ # when setting new umask, we get previous as return
|
||||
+ current_umask = os.umask(0o077)
|
||||
+ try:
|
||||
+ try:
|
||||
+ # create file with secure permissions
|
||||
+ fd = os.open(thefile, os.O_CREAT | os.O_EXCL | os.O_RDWR | os.O_TRUNC, mode)
|
||||
+ except OSError as ose:
|
||||
+ # Want to catch FileExistsError, which doesn't exist in Python 2, so catch OSError
|
||||
+ # and compare the error number to get equivalent behavior in Python 2/3
|
||||
+ if ose.errno == errno.EEXIST:
|
||||
+ raise AnsibleError('Vault file got recreated while we were operating on it: %s' % to_native(ose))
|
||||
+
|
||||
+ raise AnsibleError('Problem creating temporary vault file: %s' % to_native(ose))
|
||||
+
|
||||
+ try:
|
||||
+ # now write to the file and ensure ours is only data in it
|
||||
+ os.ftruncate(fd, 0)
|
||||
+ os.write(fd, b_file_data)
|
||||
+ except OSError as e:
|
||||
+ raise AnsibleError('Unable to write to temporary vault file: %s' % to_native(e))
|
||||
+ finally:
|
||||
+ # Make sure the file descriptor is always closed and reset umask
|
||||
+ os.close(fd)
|
||||
+ finally:
|
||||
+ os.umask(current_umask)
|
||||
|
||||
def shuffle_files(self, src, dest):
|
||||
prev = None
|
||||
--
|
||||
2.27.0
|
||||
|
||||
39
CVE-2020-1753.patch
Normal file
39
CVE-2020-1753.patch
Normal file
@ -0,0 +1,39 @@
|
||||
From b75d6b7cc9c50184976589937c750cf3b265c08c Mon Sep 17 00:00:00 2001
|
||||
From: Brian Coca <bcoca@users.noreply.github.com>
|
||||
Date: Wed, 11 Mar 2020 11:50:48 -0400
|
||||
Subject: [PATCH] warn about disclosure when using certain options
|
||||
|
||||
---
|
||||
lib/ansible/plugins/connection/kubectl.py | 5 +++++
|
||||
1 file changed, 5 insertions(+)
|
||||
|
||||
diff --git a/lib/ansible/plugins/connection/kubectl.py b/lib/ansible/plugins/connection/kubectl.py
|
||||
index d8a0fcf..03f5487 100644
|
||||
--- a/lib/ansible/plugins/connection/kubectl.py
|
||||
+++ b/lib/ansible/plugins/connection/kubectl.py
|
||||
@@ -65,6 +65,7 @@
|
||||
kubectl_extra_args:
|
||||
description:
|
||||
- Extra arguments to pass to the kubectl command line.
|
||||
+ - Please be aware that this passes information directly on the command line and it could expose sensitive data.
|
||||
default: ''
|
||||
vars:
|
||||
- name: ansible_kubectl_extra_args
|
||||
@@ -109,6 +110,8 @@
|
||||
kubectl_password:
|
||||
description:
|
||||
- Provide a password for authenticating with the API.
|
||||
+ - Please be aware that this passes information directly on the command line and it could expose sensitive data.
|
||||
+ We recommend using the file based authentication options instead.
|
||||
default: ''
|
||||
vars:
|
||||
- name: ansible_kubectl_password
|
||||
@@ -117,6 +120,8 @@
|
||||
kubectl_token:
|
||||
description:
|
||||
- API authentication bearer token.
|
||||
+ - Please be aware that this passes information directly on the command line and it could expose sensitive data.
|
||||
+ We recommend using the file based authentication options instead.
|
||||
vars:
|
||||
- name: ansible_kubectl_token
|
||||
- name: ansible_kubectl_api_key
|
||||
68
CVE-2021-20191.patch
Normal file
68
CVE-2021-20191.patch
Normal file
@ -0,0 +1,68 @@
|
||||
From 881fde464fd8065021fd2792708e6e44ede37523 Mon Sep 17 00:00:00 2001
|
||||
From: NilashishC <nilashishchakraborty8@gmail.com>
|
||||
Date: Sun, 17 Jan 2021 17:47:09 +0530
|
||||
Subject: [PATCH] Enable no_log for sensitive parameters in argspec
|
||||
|
||||
Signed-off-by: NilashishC <nilashishchakraborty8@gmail.com>
|
||||
---
|
||||
lib/ansible/modules/network/nxos/nxos_aaa_server.py | 2 +-
|
||||
lib/ansible/modules/network/nxos/nxos_pim_interface.py | 2 +-
|
||||
lib/ansible/modules/network/nxos/nxos_snmp_user.py | 2 +-
|
||||
lib/ansible/modules/network/nxos/nxos_vrrp.py | 2 +-
|
||||
4 files changed, 4 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/lib/ansible/modules/network/nxos/nxos_aaa_server.py b/lib/ansible/modules/network/nxos/nxos_aaa_server.py
|
||||
index 6d705a4..7f421d0 100644
|
||||
--- a/lib/ansible/modules/network/nxos/nxos_aaa_server.py
|
||||
+++ b/lib/ansible/modules/network/nxos/nxos_aaa_server.py
|
||||
@@ -241,7 +241,7 @@ def default_aaa_server(existing, params, server_type):
|
||||
def main():
|
||||
argument_spec = dict(
|
||||
server_type=dict(type='str', choices=['radius', 'tacacs'], required=True),
|
||||
- global_key=dict(type='str'),
|
||||
+ global_key=dict(type="str", no_log=True),
|
||||
encrypt_type=dict(type='str', choices=['0', '7']),
|
||||
deadtime=dict(type='str'),
|
||||
server_timeout=dict(type='str'),
|
||||
diff --git a/lib/ansible/modules/network/nxos/nxos_pim_interface.py b/lib/ansible/modules/network/nxos/nxos_pim_interface.py
|
||||
index fd2b17c..1b9bf0d 100644
|
||||
--- a/lib/ansible/modules/network/nxos/nxos_pim_interface.py
|
||||
+++ b/lib/ansible/modules/network/nxos/nxos_pim_interface.py
|
||||
@@ -458,7 +458,7 @@ def main():
|
||||
interface=dict(required=True),
|
||||
sparse=dict(type='bool', default=False),
|
||||
dr_prio=dict(type='str'),
|
||||
- hello_auth_key=dict(type='str'),
|
||||
+ hello_auth_key=dict(type="str", no_log=True),
|
||||
hello_interval=dict(type='int'),
|
||||
jp_policy_out=dict(type='str'),
|
||||
jp_policy_in=dict(type='str'),
|
||||
diff --git a/lib/ansible/modules/network/nxos/nxos_snmp_user.py b/lib/ansible/modules/network/nxos/nxos_snmp_user.py
|
||||
index 4264197..a9fcc43 100644
|
||||
--- a/lib/ansible/modules/network/nxos/nxos_snmp_user.py
|
||||
+++ b/lib/ansible/modules/network/nxos/nxos_snmp_user.py
|
||||
@@ -245,7 +245,7 @@ def main():
|
||||
argument_spec = dict(
|
||||
user=dict(required=True, type='str'),
|
||||
group=dict(type='str'),
|
||||
- pwd=dict(type='str'),
|
||||
+ pwd=dict(type="str", no_log=True),
|
||||
privacy=dict(type='str'),
|
||||
authentication=dict(choices=['md5', 'sha']),
|
||||
encrypt=dict(type='bool'),
|
||||
diff --git a/lib/ansible/modules/network/nxos/nxos_vrrp.py b/lib/ansible/modules/network/nxos/nxos_vrrp.py
|
||||
index b53386e..96593f7 100644
|
||||
--- a/lib/ansible/modules/network/nxos/nxos_vrrp.py
|
||||
+++ b/lib/ansible/modules/network/nxos/nxos_vrrp.py
|
||||
@@ -319,7 +319,7 @@ def main():
|
||||
admin_state=dict(required=False, type='str',
|
||||
choices=['shutdown', 'no shutdown'],
|
||||
default='no shutdown'),
|
||||
- authentication=dict(required=False, type='str'),
|
||||
+ authentication=dict(required=False, type="str", no_log=True),
|
||||
state=dict(choices=['absent', 'present'], required=False, default='present')
|
||||
)
|
||||
argument_spec.update(nxos_argument_spec)
|
||||
--
|
||||
2.27.0
|
||||
|
||||
28
ansible.spec
28
ansible.spec
@ -3,12 +3,23 @@
|
||||
Name: ansible
|
||||
Summary: SSH-based configuration management, deployment, and task execution system
|
||||
Version: 2.5.5
|
||||
Release: 1
|
||||
Release: 2
|
||||
License: Python-2.0 and MIT and GPL+
|
||||
Url: http://ansible.com
|
||||
Source0: https://releases.ansible.com/ansible/%{name}-%{version}.tar.gz
|
||||
Patch0: 0001-Changes-to-support-building-docs-with-old-jinja2.patch
|
||||
Patch100: ansible-newer-jinja.patch
|
||||
Patch101: CVE-2019-14904.patch
|
||||
Patch102: CVE-2020-10684.patch
|
||||
Patch103: CVE-2020-10729.patch
|
||||
Patch104: CVE-2020-1735.patch
|
||||
Patch105: CVE-2020-1736.patch
|
||||
Patch106: CVE-2020-1737.patch
|
||||
Patch107: CVE-2020-1738.patch
|
||||
Patch108: CVE-2020-1739.patch
|
||||
Patch109: CVE-2020-1740.patch
|
||||
Patch110: CVE-2020-1753.patch
|
||||
Patch111: CVE-2021-20191.patch
|
||||
BuildArch: noarch
|
||||
Provides: ansible-fireball = %{version}-%{release}
|
||||
Obsoletes: ansible-fireball < 1.2.4
|
||||
@ -63,6 +74,18 @@ This package installs extensive documentation for ansible
|
||||
%setup -q
|
||||
%patch0 -p1
|
||||
%patch100 -p1
|
||||
%patch101 -p1
|
||||
%patch102 -p1
|
||||
%patch103 -p1
|
||||
%patch104 -p1
|
||||
%patch105 -p1
|
||||
%patch106 -p1
|
||||
%patch107 -p1
|
||||
%patch108 -p1
|
||||
%patch109 -p1
|
||||
%patch110 -p1
|
||||
%patch111 -p1
|
||||
|
||||
%if 0%{?with_python3}
|
||||
rm -rf %{py3dir}
|
||||
cp -a . %{py3dir}
|
||||
@ -123,5 +146,8 @@ cp -pr docs/docsite/rst .
|
||||
%endif
|
||||
|
||||
%changelog
|
||||
* Fri Sep 17 2021 yaoxin <yaoxin30@huawei.com> - 2.5.5-2
|
||||
- Fix CVE-2019-14904 CVE-2020-10684 CVE-2020-10729 CVE-2020-1735-to-CVE-2020-1740 CVE-2020-1753 CVE-2021-20191
|
||||
|
||||
* Tue Jan 12 2021 yanan li <liyanan32@huawei.com> - 2.5.5-1
|
||||
- Package init
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user