diff --git a/.fence-agents.metadata b/.fence-agents.metadata index c2e8725..c8b17a9 100644 --- a/.fence-agents.metadata +++ b/.fence-agents.metadata @@ -4,7 +4,7 @@ f14647a4d37a9a254c4e711b95a7654fc418e41e SOURCES/aliyun-python-sdk-vpc-3.0.2.tar 54edb660de002b23fc12f4c0cadb2cc4ac04a398 SOURCES/fasteners-0.9.0.tar.gz e2561df8e7ff9113dab118a651371dd88dab0142 SOURCES/fence-agents-4.2.1.tar.gz d6180c4c8ec815872ae4c79d031a38906a5989df SOURCES/google-api-python-client-1.6.3.tar.gz -26696e1a5d79ea6cd7cf3462540695f105d2259e SOURCES/httplib2-0.9.1.tar.gz +c5d22ce6660999633154927684eb9b799123e569 SOURCES/httplib2-0.18.1.tar.gz 9214a01aad373e3f0637ff444f07f7aa48801540 SOURCES/keyring-5.0.zip bdce685cd0586e03f75aa1963751373e3850eb79 SOURCES/oauth2client-4.0.0.tar.gz 326a73f58a62ebee00c11a12cfdd838b196e0e8e SOURCES/pycryptodome-3.6.4.tar.gz diff --git a/.gitignore b/.gitignore index 4f69c86..9e11ca4 100644 --- a/.gitignore +++ b/.gitignore @@ -4,7 +4,7 @@ SOURCES/aliyun-python-sdk-vpc-3.0.2.tar.gz SOURCES/fasteners-0.9.0.tar.gz SOURCES/fence-agents-4.2.1.tar.gz SOURCES/google-api-python-client-1.6.3.tar.gz -SOURCES/httplib2-0.9.1.tar.gz +SOURCES/httplib2-0.18.1.tar.gz SOURCES/keyring-5.0.zip SOURCES/oauth2client-4.0.0.tar.gz SOURCES/pycryptodome-3.6.4.tar.gz diff --git a/SOURCES/bz1860545-fence_lpar-fix-long-user-host-issue.patch b/SOURCES/bz1860545-fence_lpar-fix-long-user-host-issue.patch new file mode 100644 index 0000000..f65f6ba --- /dev/null +++ b/SOURCES/bz1860545-fence_lpar-fix-long-user-host-issue.patch @@ -0,0 +1,127 @@ +From 3424464d3e447308f171399302cf76eb573a618f Mon Sep 17 00:00:00 2001 +From: Reid wahl +Date: Fri, 24 Jul 2020 18:22:24 -0700 +Subject: [PATCH] fence_lpar: Fix parse error from long command line + +When Pacemaker executes `fence_lpar` and the HMC command line is greater +than 80 characters, a parse error causes agent failure. This can happen +with a long user name and/or long managed system name. It happens only +when Pacemaker spawns the `fence_lpar` process; it does not happen when +`fence_lpar` is run from the CLI. + +A long command line gets a carriage return ('\r') added at the 80 +character mark and wraps back to the beginning of the line with no line +feed ('\n'), overwriting the displayed characters. `fence_lpar`'s regex +matches handle this fine when it's run from the command line. + +The problem is that when Pacemaker spawns fence_lpar, **for some +reason** there are backspace characters in the buffer when we hit the +'\r' character. This seems to overwrite some of the `conn.before` +string. As a result, the regex doesn't match `conn.before`, and the +agent fails. + +This patch works around the `conn.before` weirdness by reading and +discarding the first received line **before** any regex processing. + +Resolves: RHBZ#1860544 +Resolves: RHBZ#1860545 + +Signed-off-by: Reid Wahl +--- + agents/lpar/fence_lpar.py | 33 +++++++++++++++++++++++++++------ + 1 file changed, 27 insertions(+), 6 deletions(-) + +diff --git a/agents/lpar/fence_lpar.py b/agents/lpar/fence_lpar.py +index 270bbe3b..9dfabc43 100644 +--- a/agents/lpar/fence_lpar.py ++++ b/agents/lpar/fence_lpar.py +@@ -19,6 +19,9 @@ + def get_power_status(conn, options): + if options["--hmc-version"] == "3": + conn.send("lssyscfg -r lpar -m " + options["--managed"] + " -n " + options["--plug"] + " -F name,state\n") ++ ++ # First line (command) may cause parsing issues if long ++ conn.readline() + conn.log_expect(options["--command-prompt"], int(options["--power-timeout"])) + + try: +@@ -29,6 +32,9 @@ def get_power_status(conn, options): + elif options["--hmc-version"] in ["4", "IVM"]: + conn.send("lssyscfg -r lpar -m "+ options["--managed"] + + " --filter 'lpar_names=" + options["--plug"] + "'\n") ++ ++ # First line (command) may cause parsing issues if long ++ conn.readline() + conn.log_expect(options["--command-prompt"], int(options["--power-timeout"])) + + try: +@@ -49,6 +55,9 @@ def set_power_status(conn, options): + if options["--hmc-version"] == "3": + conn.send("chsysstate -o " + options["--action"] + " -r lpar -m " + options["--managed"] + + " -n " + options["--plug"] + "\n") ++ ++ # First line (command) may cause parsing issues if long ++ conn.readline() + conn.log_expect(options["--command-prompt"], int(options["--power-timeout"])) + elif options["--hmc-version"] in ["4", "IVM"]: + if options["--action"] == "on": +@@ -60,17 +69,23 @@ def set_power_status(conn, options): + else: + conn.send("chsysstate -o shutdown -r lpar --immed" + + " -m " + options["--managed"] + " -n " + options["--plug"] + "\n") ++ ++ # First line (command) may cause parsing issues if long ++ conn.readline() + conn.log_expect(options["--command-prompt"], int(options["--power-timeout"])) + + def get_lpar_list(conn, options): + outlets = {} + if options["--hmc-version"] == "3": + conn.send("query_partition_names -m " + options["--managed"] + "\n") ++ ++ ## We have to remove first line (command) ++ conn.readline() + conn.log_expect(options["--command-prompt"], int(options["--power-timeout"])) + +- ## We have to remove first 3 lines (command + header) and last line (part of new prompt) ++ ## We have to remove next 2 lines (header) and last line (part of new prompt) + #### +- res = re.search("^.+?\n(.+?\n){2}(.*)\n.*$", conn.before, re.S) ++ res = re.search("^(.+?\n){2}(.*)\n.*$", conn.before, re.S) + + if res == None: + fail_usage("Unable to parse output of list command") +@@ -81,11 +96,14 @@ def get_lpar_list(conn, options): + elif options["--hmc-version"] == "4": + conn.send("lssyscfg -r lpar -m " + options["--managed"] + + " -F name:state\n") ++ ++ ## We have to remove first line (command) ++ conn.readline() + conn.log_expect(options["--command-prompt"], int(options["--power-timeout"])) + +- ## We have to remove first line (command) and last line (part of new prompt) ++ ## We have to remove last line (part of new prompt) + #### +- res = re.search("^.+?\n(.*)\n.*$", conn.before, re.S) ++ res = re.search("^(.*)\n.*$", conn.before, re.S) + + if res == None: + fail_usage("Unable to parse output of list command") +@@ -100,11 +118,14 @@ def get_lpar_list(conn, options): + elif options["--hmc-version"] == "IVM": + conn.send("lssyscfg -r lpar -m " + options["--managed"] + + " -F name,state\n") ++ ++ ## We have to remove first line (command) ++ conn.readline() + conn.log_expect(options["--command-prompt"], int(options["--power-timeout"])) + +- ## We have to remove first line (command) and last line (part of new prompt) ++ ## We have to remove last line (part of new prompt) + #### +- res = re.search("^.+?\n(.*)\n.*$", conn.before, re.S) ++ res = re.search("^(.*)\n.*$", conn.before, re.S) + + if res == None: + fail_usage("Unable to parse output of list command") diff --git a/SOURCES/bz1862024-fence_evacuate-support-private-flavors.patch b/SOURCES/bz1862024-fence_evacuate-support-private-flavors.patch new file mode 100644 index 0000000..60eddd2 --- /dev/null +++ b/SOURCES/bz1862024-fence_evacuate-support-private-flavors.patch @@ -0,0 +1,26 @@ +From 18ef1622475db947aef70042523f4a176c4155bd Mon Sep 17 00:00:00 2001 +From: Luca Miccini +Date: Thu, 23 Jul 2020 14:33:38 +0200 +Subject: [PATCH] [fence_evacuate] Enable evacuation of instances using private + flavors + +This commit extends the flavor.list() api call in the fence_evacuate +agent to fetch private flavors that could be tagged with the 'evacuable' +attribute, allowing instance-ha to be enabled on a per tenant basis. +--- + agents/evacuate/fence_evacuate.py | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/agents/evacuate/fence_evacuate.py b/agents/evacuate/fence_evacuate.py +index 88837dd8..53d6fd15 100644 +--- a/agents/evacuate/fence_evacuate.py ++++ b/agents/evacuate/fence_evacuate.py +@@ -87,7 +87,7 @@ def _is_server_evacuable(server, evac_flavors, evac_images): + + def _get_evacuable_flavors(connection): + result = [] +- flavors = connection.flavors.list() ++ flavors = connection.flavors.list(is_public=None) + # Since the detailed view for all flavors doesn't provide the extra specs, + # we need to call each of the flavor to get them. + for flavor in flavors: diff --git a/SOURCES/python-httplib2-0.9-cve-2013-2037.patch b/SOURCES/python-httplib2-0.9-cve-2013-2037.patch deleted file mode 100644 index 6a09337..0000000 --- a/SOURCES/python-httplib2-0.9-cve-2013-2037.patch +++ /dev/null @@ -1,21 +0,0 @@ -diff -Nur httplib2-0.9.orig/python2/httplib2/__init__.py httplib2-0.9/python2/httplib2/__init__.py ---- httplib2-0.9.orig/python2/httplib2/__init__.py 2015-04-03 13:10:43.401035131 -0600 -+++ httplib2-0.9/python2/httplib2/__init__.py 2015-04-03 13:10:08.470685647 -0600 -@@ -1042,7 +1042,7 @@ - raise CertificateHostnameMismatch( - 'Server presented certificate that does not match ' - 'host %s: %s' % (hostname, cert), hostname, cert) -- except ssl_SSLError, e: -+ except (ssl_SSLError, CertificateHostnameMismatch), e: - if sock: - sock.close() - if self.sock: -@@ -1052,7 +1052,7 @@ - # to get at more detailed error information, in particular - # whether the error is due to certificate validation or - # something else (such as SSL protocol mismatch). -- if e.errno == ssl.SSL_ERROR_SSL: -+ if hasattr(e, 'errno') and e.errno == ssl.SSL_ERROR_SSL: - raise SSLHandshakeError(e) - else: - raise diff --git a/SOURCES/python-httplib2-0.9-proxy-http.patch b/SOURCES/python-httplib2-0.9-proxy-http.patch deleted file mode 100644 index 0d55002..0000000 --- a/SOURCES/python-httplib2-0.9-proxy-http.patch +++ /dev/null @@ -1,16 +0,0 @@ -diff -Nur httplib2-0.9.orig/python2/httplib2/__init__.py httplib2-0.9/python2/httplib2/__init__.py ---- httplib2-0.9.orig/python2/httplib2/__init__.py 2015-04-03 12:56:04.834370332 -0600 -+++ httplib2-0.9/python2/httplib2/__init__.py 2015-04-03 12:58:16.441925454 -0600 -@@ -838,7 +838,11 @@ - else: - port = dict(https=443, http=80)[method] - -- proxy_type = 3 # socks.PROXY_TYPE_HTTP -+ if method == 'http': -+ proxy_type = 4 # socks.PROXY_TYPE_HTTP_NO_TUNNEL -+ else: -+ proxy_type = 3 # socks.PROXY_TYPE_HTTP -+ - return ProxyInfo( - proxy_type = proxy_type, - proxy_host = host, diff --git a/SOURCES/python-httplib2.certfile.patch b/SOURCES/python-httplib2.certfile.patch deleted file mode 100644 index e351169..0000000 --- a/SOURCES/python-httplib2.certfile.patch +++ /dev/null @@ -1,31 +0,0 @@ -diff -Nur httplib2-0.9.orig/python2/httplib2/__init__.py httplib2-0.9/python2/httplib2/__init__.py ---- httplib2-0.9.orig/python2/httplib2/__init__.py 2014-04-14 06:52:57.000000000 -0600 -+++ httplib2-0.9/python2/httplib2/__init__.py 2014-05-23 21:17:02.082118837 -0600 -@@ -191,8 +191,10 @@ - CA_CERTS = ca_certs_locater.get() - except ImportError: - # Default CA certificates file bundled with httplib2. -- CA_CERTS = os.path.join( -- os.path.dirname(os.path.abspath(__file__ )), "cacerts.txt") -+# CA_CERTS = os.path.join( -+# os.path.dirname(os.path.abspath(__file__ )), "cacerts.txt") -+# Use Fedora system-wide shared certificate store for security, consistency. -+ CA_CERTS = "/etc/pki/tls/certs/ca-bundle.crt" - - # Which headers are hop-by-hop headers by default - HOP_BY_HOP = ['connection', 'keep-alive', 'proxy-authenticate', 'proxy-authorization', 'te', 'trailers', 'transfer-encoding', 'upgrade'] ---- httplib2-0.9/python3/httplib2/__init__.py 2014-04-14 05:52:57.000000000 -0700 -+++ httplib2-0.9/python3/httplib2/__init__.py.new 2015-01-12 17:22:19.815505848 -0800 -@@ -124,8 +124,10 @@ - HOP_BY_HOP = ['connection', 'keep-alive', 'proxy-authenticate', 'proxy-authorization', 'te', 'trailers', 'transfer-encoding', 'upgrade'] - - # Default CA certificates file bundled with httplib2. --CA_CERTS = os.path.join( -- os.path.dirname(os.path.abspath(__file__ )), "cacerts.txt") -+#CA_CERTS = os.path.join( -+# os.path.dirname(os.path.abspath(__file__ )), "cacerts.txt") -+# Use Fedora system-wide shared certificate store for security, consistency. -+CA_CERTS = "/etc/pki/tls/certs/ca-bundle.crt" - - def _get_end2end_headers(response): - hopbyhop = list(HOP_BY_HOP) diff --git a/SOURCES/python-httplib2.getCertHost.patch b/SOURCES/python-httplib2.getCertHost.patch deleted file mode 100644 index f9c53de..0000000 --- a/SOURCES/python-httplib2.getCertHost.patch +++ /dev/null @@ -1,21 +0,0 @@ -diff -up ./python2/httplib2/__init__.py.getCertHost ./python2/httplib2/__init__.py ---- ./python2/httplib2/__init__.py.getCertHost 2012-05-03 17:16:33.834155219 +1000 -+++ ./python2/httplib2/__init__.py 2012-06-21 18:19:33.804660257 +1000 -@@ -942,11 +942,12 @@ class HTTPSConnectionWithTimeout(httplib - list: A list of valid host globs. - """ - if 'subjectAltName' in cert: -- return [x[1] for x in cert['subjectAltName'] -- if x[0].lower() == 'dns'] -- else: -- return [x[0][1] for x in cert['subject'] -- if x[0][0].lower() == 'commonname'] -+ # Patch from richardfearn@gmail.com -+ return [x[1] for x in cert['subjectAltName'] -+ if x[0].lower() == "dns"] -+ -+ return [x[0][1] for x in cert['subject'] -+ if x[0][0].lower() == 'commonname'] - - def _ValidateCertificateHostname(self, cert, hostname): - """Validates that a given hostname is valid for an SSL certificate. diff --git a/SOURCES/python-httplib2.rfc2459.patch b/SOURCES/python-httplib2.rfc2459.patch deleted file mode 100644 index 523129e..0000000 --- a/SOURCES/python-httplib2.rfc2459.patch +++ /dev/null @@ -1,19 +0,0 @@ -diff -up ./python2/httplib2/__init__.py.orig ./python2/httplib2/__init__.py ---- ./python2/httplib2/__init__.py.orig 2012-07-27 18:35:59.215300471 +1000 -+++ ./python2/httplib2/__init__.py 2012-07-27 18:36:30.697287505 +1000 -@@ -943,8 +943,13 @@ class HTTPSConnectionWithTimeout(httplib - """ - if 'subjectAltName' in cert: - # Patch from richardfearn@gmail.com -- return [x[1] for x in cert['subjectAltName'] -+ # RFC 2459 states that subjectAltName may contain: -+ # either DNS, email, IP or URI -+ # email, URI, -+ hosts=[x[1] for x in cert['subjectAltName'] - if x[0].lower() == "dns"] -+ if hosts: -+ return hosts - - return [x[0][1] for x in cert['subject'] - if x[0][0].lower() == 'commonname'] - diff --git a/SPECS/fence-agents.spec b/SPECS/fence-agents.spec index e67821c..314c7ce 100644 --- a/SPECS/fence-agents.spec +++ b/SPECS/fence-agents.spec @@ -27,7 +27,7 @@ %global oauth2client_dir %{bundled_lib_dir}/gce/%{oauth2client} # python-httplib2 bundle %global httplib2 httplib2 -%global httplib2_version 0.9.1 +%global httplib2_version 0.18.1 %global httplib2_dir %{bundled_lib_dir}/gce/%{httplib2} # python-fasteners bundle %global fasteners fasteners @@ -67,7 +67,7 @@ Name: fence-agents Summary: Fence Agents for Red Hat Cluster Version: 4.2.1 -Release: 41%{?alphatag:.%{alphatag}}%{?dist} +Release: 41%{?alphatag:.%{alphatag}}%{?dist}.2 License: GPLv2+ and LGPLv2+ Group: System Environment/Base URL: https://github.com/ClusterLabs/fence-agents @@ -135,16 +135,13 @@ Patch60: bz1654058-fence_vmware_rest-1-add-filter-parameter.patch Patch61: bz1654058-fence_vmware_rest-2-fix-1000-VM-monitor-error.patch Patch62: bz1793738-fence_vmware_rest-2-support-utf-8-vm-names.patch Patch63: bz1832289-fence_aws-improve-catch-connectionerror.patch +Patch64: bz1860545-fence_lpar-fix-long-user-host-issue.patch +Patch65: bz1862024-fence_evacuate-support-private-flavors.patch # bundle patches Patch1000: bz1568753-4-fence_gce-bundled-libs.patch Patch1001: bz1568753-5-%{oauth2client}-docs-build-fix.patch Patch1002: bz1568753-6-%{oauth2client}-python-rsa-to-cryptography.patch -Patch1003: python-%{httplib2}.certfile.patch -Patch1004: python-%{httplib2}.getCertHost.patch -Patch1005: python-%{httplib2}.rfc2459.patch -Patch1006: python-%{httplib2}-0.9-proxy-http.patch -Patch1007: python-%{httplib2}-0.9-cve-2013-2037.patch -Patch1008: bz1568753-7-%{keyring}-fix-gnome-version-warning.patch +Patch1003: bz1568753-7-%{keyring}-fix-gnome-version-warning.patch %if 0%{?rhel} %global supportedagents amt_ws apc apc_snmp bladecenter brocade cisco_mds cisco_ucs compute drac5 eaton_snmp emerson eps evacuate hpblade ibmblade ifmib ilo ilo_moonshot ilo_mp ilo_ssh intelmodular ipdu ipmilan lpar mpath kdump redfish rhevm rsa rsb sbd scsi vmware_rest vmware_soap wti @@ -236,6 +233,8 @@ BuildRequires: python-six >= 1.6.1 %patch61 -p1 %patch62 -p1 %patch63 -p1 +%patch64 -p1 +%patch65 -p1 # prevent compilation of something that won't get used anyway sed -i.orig 's|FENCE_ZVM=1|FENCE_ZVM=0|' configure.ac @@ -336,18 +335,9 @@ sed -i 's/httplib2>=0.9.1/httplib2/' setup.py rm -f docs/source/oauth2client.contrib.appengine.rst oauth2client/appengine.py popd -# python-httplib2 bundle -pushd %{httplib2_dir} -%patch1003 -p1 -%patch1004 -p1 -%patch1005 -p1 -%patch1006 -p1 -%patch1007 -p1 -popd - # python-keyring bundle pushd %{keyring_dir} -%patch1008 -p1 +%patch1003 -p1 rm -fr keyring.egg-info # Drop redundant shebangs. sed -i '1{\@^#!/usr/bin/env python@d}' keyring/cli.py @@ -1196,6 +1186,18 @@ The fence-agents-zvm package contains a fence agent for z/VM hypervisors %endif %changelog +* Fri Oct 2 2020 Oyvind Albrigtsen - 4.2.1-41.2 +- Upgrade bundled python-httplib2 to fix CVE-2020-11078 + Resolves: rhbz#1850114 + +* Mon Aug 3 2020 Oyvind Albrigtsen - 4.2.1-41.1 +- fence_lpar: fix issue with long username, hostname, etc not + working when the command run by the agent exceeds 80 characters +- fence_evacuate: enable evacuation of instances using private flavors + + Resolves: rhbz#1860545 + Resolves: rhbz#1862024 + * Mon May 25 2020 Oyvind Albrigtsen - 4.2.1-41 - fence_aws: improve logging and metadata/usage text Resolves: rhbz#1832289