From c21d6a0a9905f4b8a7c46456c2c6d581f16294f1 Mon Sep 17 00:00:00 2001 From: Wesley Whetstone Date: Thu, 2 Jul 2020 15:39:26 -0700 Subject: [PATCH 1/7] add support for Big Sur when searching for libcrypto --- salt/utils/mac_utils.py | 32 ++++++++++++++++++++++++++++ salt/utils/rsax931.py | 31 ++++++++++++++++----------- tests/unit/utils/test_mac_utils.py | 11 ++++++++++ tests/unit/utils/test_rsax931.py | 34 ++++++++++++++++++++++++++++-- 4 files changed, 94 insertions(+), 14 deletions(-) diff --git a/salt/utils/mac_utils.py b/salt/utils/mac_utils.py index e6fa93a29fcf..1388e2f89a31 100644 --- a/salt/utils/mac_utils.py +++ b/salt/utils/mac_utils.py @@ -8,6 +8,7 @@ # Import Python Libraries import logging import os +import platform import plistlib import subprocess import time @@ -513,3 +514,34 @@ def console_user(username=False): return pwd.getpwuid(uid)[0] return uid + + +def os_version(only_major_minor=True, as_tuple=False): + """ + Get the macOS version of the machine. + + :param bool only_major_minor: If true returns on the major and minor + version of the OS (10.15). Otherwise full version 10.15.2. Defaults + to ``True`` + + :param bool as_tuple: If true will make return type a tuple otherwise + a string. + + :return: The current os version. + + :rtype: Tuple of OS version or a string of osversion. + + CLI Example: + + .. code-block:: bash + + import salt.utils.mac_utils + salt.utils.mac_utils.os_version(as_tuple=True) + """ + #lovingly borrowed from the munki project + os_version_tuple = platform.mac_ver()[0].split(".") + if only_major_minor: + os_version_tuple = os_version_tuple[0:2] + if as_tuple: + return tuple(map(int, os_version_tuple)) + return ".".join(os_version_tuple) diff --git a/salt/utils/rsax931.py b/salt/utils/rsax931.py index c60ef6ba0ed3..83330dfe37b3 100644 --- a/salt/utils/rsax931.py +++ b/salt/utils/rsax931.py @@ -15,6 +15,7 @@ from ctypes import c_char_p, c_int, c_void_p, cdll, create_string_buffer, pointer # Import Salt libs +import salt.utils.mac_utils import salt.utils.platform import salt.utils.stringutils @@ -30,6 +31,24 @@ def _find_libcrypto(): """ if sys.platform.startswith("win"): lib = str("libeay32") + elif salt.utils.platform.is_darwin(): + # will look for several different location on the system, + # Search in the following order. salts pkg, homebrew, macports, finnally + # system. + # look in salts pkg install location. + lib = glob.glob("/opt/salt/lib/libcrypto.dylib") + # Find library symlinks in Homebrew locations. + lib = lib or glob.glob("/usr/local/opt/openssl/lib/libcrypto.dylib") + lib = lib or glob.glob("/usr/local/opt/openssl@*/lib/libcrypto.dylib") + # look in macports. + lib = lib or glob.glob("/opt/local/lib/libcrypto.dylib") + # check if 10.15, regular libcrypto.dylib is just a false pointer. + if salt.utils.mac_utils.os_version(as_tuple=True) == (10, 15): + lib = lib or glob.glob("/usr/lib/libcrypto.*.dylib") + lib = list(reversed(sorted(lib))) + # last but not least all the other macOS versions should work here. + # including Big Sur + lib = lib[0] if lib else str("/usr/lib/libcrypto.dylib") elif getattr(sys, "frozen", False) and salt.utils.platform.is_smartos(): lib = glob.glob(os.path.join(os.path.dirname(sys.executable), "libcrypto.so*")) lib = lib[0] if lib else None @@ -53,18 +72,6 @@ def _find_libcrypto(): else: lib = glob.glob("/opt/freeware/lib/libcrypto.so*") lib = lib[0] if lib else None - elif salt.utils.platform.is_darwin(): - # Find versioned libraries in system locations, being careful - # to avoid the unversioned stub which is no longer permitted. - lib = glob.glob("/usr/lib/libcrypto.*.dylib") - if lib: - # Sort so as to prefer the newest version. - lib = list(reversed(sorted(lib))) - else: - # Find library symlinks in Homebrew locations. - lib = glob.glob("/usr/local/opt/openssl/lib/libcrypto.dylib") - lib = lib or glob.glob("/usr/local/opt/openssl@*/lib/libcrypto.dylib") - lib = lib[0] if lib else None if not lib: raise OSError("Cannot locate OpenSSL libcrypto") return lib diff --git a/tests/unit/utils/test_mac_utils.py b/tests/unit/utils/test_mac_utils.py index 955af5b87469..af4435a2d59a 100644 --- a/tests/unit/utils/test_mac_utils.py +++ b/tests/unit/utils/test_mac_utils.py @@ -7,6 +7,7 @@ from __future__ import absolute_import, unicode_literals import os +import platform import plistlib import xml.parsers.expat @@ -168,6 +169,16 @@ def test_validate_enabled_false(self): """ self.assertEqual(mac_utils.validate_enabled(False), "off") + @patch.object(platform, "mac_ver", lambda: ('10.15.5', ('', '', ''), 'x86_64')) + def test_os_version(self): + """ + test multiple outputs of os_version + """ + self.assertEqual(mac_utils.os_version(), "10.15") + self.assertEqual(mac_utils.os_version(as_tuple=True), (10, 15)) + self.assertEqual(mac_utils.os_version(only_major_minor=False), '10.15.5') + self.assertEqual(mac_utils.os_version(only_major_minor=False, as_tuple=True), (10, 15, 5)) + def test_launchctl(self): """ test launchctl function diff --git a/tests/unit/utils/test_rsax931.py b/tests/unit/utils/test_rsax931.py index 85d5e4e32f7d..1136fac7d2a2 100644 --- a/tests/unit/utils/test_rsax931.py +++ b/tests/unit/utils/test_rsax931.py @@ -174,25 +174,55 @@ def test_find_libcrypto_aix(self): ) @skipIf(not salt.utils.platform.is_darwin(), "Host OS is not Darwin-like or macOS.") - def test_find_libcrypto_darwin(self): + @patch.object(salt.utils.mac_utils, "os_version", lambda as_tuple: (10.14)) + @patch.object(glob, "glob", lambda _: []) + def test_find_libcrypto_with_system_and_not_catalina(self): """ - Test _find_libcrypto on a Darwin-like or macOS host. + Test _find_libcrypto on a Catalina-like macOS host, simulate + not finding any other libcryptos and just defaulting to system. """ lib_path = _find_libcrypto() passed = False for i in ( + "/opt/salt/lib/libcrypto.dylib", + "/usr/local/opt/openssl/lib/libcrypto.dylib", + "/usr/local/opt/openssl@*/lib/libcrypto.dylib", + "/opt/local/lib/libcrypto.dylib", "/usr/lib/libcrypto.*.dylib", + ): + if fnmatch.fnmatch(lib_path, i): + passed = True + break + self.assertFalse(passed) + self.assertEqual(lib_path, "/usr/lib/libcrypto.dylib") + + @skipIf(not salt.utils.platform.is_darwin(), "Host OS is not Darwin-like or macOS.") + @patch.object(salt.utils.mac_utils, "os_version", lambda as_tuple: (10.15)) + def test_find_libcrypto_darwin_catalina(self): + """ + Test _find_libcrypto on a Darwin-like macOS host where there isn't a + lacation returned by ctypes.util.find_library() + """ + lib_path = _find_libcrypto() + passed = False + for i in ( + "/opt/salt/lib/libcrypto.dylib", "/usr/local/opt/openssl/lib/libcrypto.dylib", "/usr/local/opt/openssl@*/lib/libcrypto.dylib", + "/opt/local/lib/libcrypto.dylib", + "/usr/lib/libcrypto.*.dylib", ): if fnmatch.fnmatch(lib_path, i): passed = True break self.assertTrue(passed) + # we should never return the stub on catalina + self.assertNotEqual(lib_path, "/usr/lib/libcrypto.dylib") @patch.object(ctypes.util, "find_library", lambda a: None) @patch.object(glob, "glob", lambda a: []) @patch.object(sys, "platform", "unknown") + @patch.object(salt.utils.platform, "is_darwin", lambda: False) def test_find_libcrypto_unsupported(self): """ Ensure that _find_libcrypto works correctly on an unsupported host OS. From 2d056994e35e599898650ceb7a61856856a39353 Mon Sep 17 00:00:00 2001 From: Wesley Whetstone Date: Thu, 2 Jul 2020 15:44:03 -0700 Subject: [PATCH 2/7] run precommit --- salt/utils/mac_utils.py | 2 +- tests/unit/utils/test_mac_utils.py | 8 +++++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/salt/utils/mac_utils.py b/salt/utils/mac_utils.py index 1388e2f89a31..fc37ec4e0057 100644 --- a/salt/utils/mac_utils.py +++ b/salt/utils/mac_utils.py @@ -538,7 +538,7 @@ def os_version(only_major_minor=True, as_tuple=False): import salt.utils.mac_utils salt.utils.mac_utils.os_version(as_tuple=True) """ - #lovingly borrowed from the munki project + # lovingly borrowed from the munki project os_version_tuple = platform.mac_ver()[0].split(".") if only_major_minor: os_version_tuple = os_version_tuple[0:2] diff --git a/tests/unit/utils/test_mac_utils.py b/tests/unit/utils/test_mac_utils.py index af4435a2d59a..9d7132b99249 100644 --- a/tests/unit/utils/test_mac_utils.py +++ b/tests/unit/utils/test_mac_utils.py @@ -169,15 +169,17 @@ def test_validate_enabled_false(self): """ self.assertEqual(mac_utils.validate_enabled(False), "off") - @patch.object(platform, "mac_ver", lambda: ('10.15.5', ('', '', ''), 'x86_64')) + @patch.object(platform, "mac_ver", lambda: ("10.15.5", ("", "", ""), "x86_64")) def test_os_version(self): """ test multiple outputs of os_version """ self.assertEqual(mac_utils.os_version(), "10.15") self.assertEqual(mac_utils.os_version(as_tuple=True), (10, 15)) - self.assertEqual(mac_utils.os_version(only_major_minor=False), '10.15.5') - self.assertEqual(mac_utils.os_version(only_major_minor=False, as_tuple=True), (10, 15, 5)) + self.assertEqual(mac_utils.os_version(only_major_minor=False), "10.15.5") + self.assertEqual( + mac_utils.os_version(only_major_minor=False, as_tuple=True), (10, 15, 5) + ) def test_launchctl(self): """ From fb9314ea87f3a0bf335fced1b6352c515e43d1cd Mon Sep 17 00:00:00 2001 From: Wesley Whetstone Date: Mon, 6 Jul 2020 11:58:08 -0700 Subject: [PATCH 3/7] remove mac_utils version in favor of in line check, and add other recommendations --- salt/utils/mac_utils.py | 32 ------------------------------ salt/utils/rsax931.py | 4 ++-- tests/unit/utils/test_mac_utils.py | 13 ------------ tests/unit/utils/test_rsax931.py | 7 +++---- 4 files changed, 5 insertions(+), 51 deletions(-) diff --git a/salt/utils/mac_utils.py b/salt/utils/mac_utils.py index fc37ec4e0057..e6fa93a29fcf 100644 --- a/salt/utils/mac_utils.py +++ b/salt/utils/mac_utils.py @@ -8,7 +8,6 @@ # Import Python Libraries import logging import os -import platform import plistlib import subprocess import time @@ -514,34 +513,3 @@ def console_user(username=False): return pwd.getpwuid(uid)[0] return uid - - -def os_version(only_major_minor=True, as_tuple=False): - """ - Get the macOS version of the machine. - - :param bool only_major_minor: If true returns on the major and minor - version of the OS (10.15). Otherwise full version 10.15.2. Defaults - to ``True`` - - :param bool as_tuple: If true will make return type a tuple otherwise - a string. - - :return: The current os version. - - :rtype: Tuple of OS version or a string of osversion. - - CLI Example: - - .. code-block:: bash - - import salt.utils.mac_utils - salt.utils.mac_utils.os_version(as_tuple=True) - """ - # lovingly borrowed from the munki project - os_version_tuple = platform.mac_ver()[0].split(".") - if only_major_minor: - os_version_tuple = os_version_tuple[0:2] - if as_tuple: - return tuple(map(int, os_version_tuple)) - return ".".join(os_version_tuple) diff --git a/salt/utils/rsax931.py b/salt/utils/rsax931.py index 83330dfe37b3..772c7255c643 100644 --- a/salt/utils/rsax931.py +++ b/salt/utils/rsax931.py @@ -9,13 +9,13 @@ import ctypes.util import glob import os +import platform import sys # Import 3rd-party libs from ctypes import c_char_p, c_int, c_void_p, cdll, create_string_buffer, pointer # Import Salt libs -import salt.utils.mac_utils import salt.utils.platform import salt.utils.stringutils @@ -43,7 +43,7 @@ def _find_libcrypto(): # look in macports. lib = lib or glob.glob("/opt/local/lib/libcrypto.dylib") # check if 10.15, regular libcrypto.dylib is just a false pointer. - if salt.utils.mac_utils.os_version(as_tuple=True) == (10, 15): + if platform.mac_ver()[0].split(".")[:2] == ["10", "15"]: lib = lib or glob.glob("/usr/lib/libcrypto.*.dylib") lib = list(reversed(sorted(lib))) # last but not least all the other macOS versions should work here. diff --git a/tests/unit/utils/test_mac_utils.py b/tests/unit/utils/test_mac_utils.py index 9d7132b99249..955af5b87469 100644 --- a/tests/unit/utils/test_mac_utils.py +++ b/tests/unit/utils/test_mac_utils.py @@ -7,7 +7,6 @@ from __future__ import absolute_import, unicode_literals import os -import platform import plistlib import xml.parsers.expat @@ -169,18 +168,6 @@ def test_validate_enabled_false(self): """ self.assertEqual(mac_utils.validate_enabled(False), "off") - @patch.object(platform, "mac_ver", lambda: ("10.15.5", ("", "", ""), "x86_64")) - def test_os_version(self): - """ - test multiple outputs of os_version - """ - self.assertEqual(mac_utils.os_version(), "10.15") - self.assertEqual(mac_utils.os_version(as_tuple=True), (10, 15)) - self.assertEqual(mac_utils.os_version(only_major_minor=False), "10.15.5") - self.assertEqual( - mac_utils.os_version(only_major_minor=False, as_tuple=True), (10, 15, 5) - ) - def test_launchctl(self): """ test launchctl function diff --git a/tests/unit/utils/test_rsax931.py b/tests/unit/utils/test_rsax931.py index 1136fac7d2a2..311d3d6694e4 100644 --- a/tests/unit/utils/test_rsax931.py +++ b/tests/unit/utils/test_rsax931.py @@ -11,6 +11,7 @@ import fnmatch import glob import os +import platform import sys import salt.utils.platform @@ -174,7 +175,7 @@ def test_find_libcrypto_aix(self): ) @skipIf(not salt.utils.platform.is_darwin(), "Host OS is not Darwin-like or macOS.") - @patch.object(salt.utils.mac_utils, "os_version", lambda as_tuple: (10.14)) + @patch.object(platform, "mac_ver", lambda: ("10.14.2", (), "")) @patch.object(glob, "glob", lambda _: []) def test_find_libcrypto_with_system_and_not_catalina(self): """ @@ -197,7 +198,7 @@ def test_find_libcrypto_with_system_and_not_catalina(self): self.assertEqual(lib_path, "/usr/lib/libcrypto.dylib") @skipIf(not salt.utils.platform.is_darwin(), "Host OS is not Darwin-like or macOS.") - @patch.object(salt.utils.mac_utils, "os_version", lambda as_tuple: (10.15)) + @patch.object(platform, "mac_ver", lambda: ("10.15.2", (), "")) def test_find_libcrypto_darwin_catalina(self): """ Test _find_libcrypto on a Darwin-like macOS host where there isn't a @@ -216,8 +217,6 @@ def test_find_libcrypto_darwin_catalina(self): passed = True break self.assertTrue(passed) - # we should never return the stub on catalina - self.assertNotEqual(lib_path, "/usr/lib/libcrypto.dylib") @patch.object(ctypes.util, "find_library", lambda a: None) @patch.object(glob, "glob", lambda a: []) From 25ae2bb36661aea1a2b0941e7a9dd4e7d28566eb Mon Sep 17 00:00:00 2001 From: Wesley Whetstone Date: Mon, 6 Jul 2020 13:37:27 -0700 Subject: [PATCH 4/7] add changelog --- changelog/57787.fixed | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelog/57787.fixed diff --git a/changelog/57787.fixed b/changelog/57787.fixed new file mode 100644 index 000000000000..ebb11c3a26ad --- /dev/null +++ b/changelog/57787.fixed @@ -0,0 +1 @@ +Adds a fix so salt can run on the latest macOS version Big Sur. From 1595715e90f68b1a82c488f8dde3d2d3377d2555 Mon Sep 17 00:00:00 2001 From: Wesley Whetstone Date: Tue, 7 Jul 2020 13:25:41 -0700 Subject: [PATCH 5/7] remove str cast on macOS and add comment for windows str cast --- salt/utils/rsax931.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/salt/utils/rsax931.py b/salt/utils/rsax931.py index 772c7255c643..28beb0668b1f 100644 --- a/salt/utils/rsax931.py +++ b/salt/utils/rsax931.py @@ -30,6 +30,7 @@ def _find_libcrypto(): Find the path (or return the short name) of libcrypto. """ if sys.platform.startswith("win"): + # cdll.LoadLibrary on windows requires a 'str' argument lib = str("libeay32") elif salt.utils.platform.is_darwin(): # will look for several different location on the system, @@ -47,8 +48,8 @@ def _find_libcrypto(): lib = lib or glob.glob("/usr/lib/libcrypto.*.dylib") lib = list(reversed(sorted(lib))) # last but not least all the other macOS versions should work here. - # including Big Sur - lib = lib[0] if lib else str("/usr/lib/libcrypto.dylib") + # including Big Sur. + lib = lib[0] if lib else "/usr/lib/libcrypto.dylib" elif getattr(sys, "frozen", False) and salt.utils.platform.is_smartos(): lib = glob.glob(os.path.join(os.path.dirname(sys.executable), "libcrypto.so*")) lib = lib[0] if lib else None From 242115e2481119c4da74254343151ac55f35a2bf Mon Sep 17 00:00:00 2001 From: Wesley Whetstone Date: Wed, 8 Jul 2020 12:39:59 -0700 Subject: [PATCH 6/7] remove windows str cast --- salt/utils/rsax931.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/salt/utils/rsax931.py b/salt/utils/rsax931.py index 28beb0668b1f..4ec180ce14c9 100644 --- a/salt/utils/rsax931.py +++ b/salt/utils/rsax931.py @@ -31,7 +31,7 @@ def _find_libcrypto(): """ if sys.platform.startswith("win"): # cdll.LoadLibrary on windows requires a 'str' argument - lib = str("libeay32") + lib = "libeay32" elif salt.utils.platform.is_darwin(): # will look for several different location on the system, # Search in the following order. salts pkg, homebrew, macports, finnally From e7c19ef849eaf5d28f678b5b81d2fbb84c5f9090 Mon Sep 17 00:00:00 2001 From: Wesley Whetstone Date: Wed, 8 Jul 2020 13:12:11 -0700 Subject: [PATCH 7/7] remove old windows string comment --- salt/utils/rsax931.py | 1 - 1 file changed, 1 deletion(-) diff --git a/salt/utils/rsax931.py b/salt/utils/rsax931.py index 4ec180ce14c9..7fa979bd8532 100644 --- a/salt/utils/rsax931.py +++ b/salt/utils/rsax931.py @@ -30,7 +30,6 @@ def _find_libcrypto(): Find the path (or return the short name) of libcrypto. """ if sys.platform.startswith("win"): - # cdll.LoadLibrary on windows requires a 'str' argument lib = "libeay32" elif salt.utils.platform.is_darwin(): # will look for several different location on the system,