Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package salt for openSUSE:Factory checked in at 2024-09-01 19:21:01 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/salt (Old) and /work/SRC/openSUSE:Factory/.salt.new.2698 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "salt" Sun Sep 1 19:21:01 2024 rev:157 rq:1197895 version:3006.0 Changes: -------- --- /work/SRC/openSUSE:Factory/salt/salt.changes 2024-08-30 13:29:25.859014183 +0200 +++ /work/SRC/openSUSE:Factory/.salt.new.2698/salt.changes 2024-09-01 19:21:10.999417126 +0200 @@ -1,0 +2,12 @@ +Fri Aug 30 14:42:00 UTC 2024 - Victor Zhestkov <vzhest...@suse.com> + +- Avoid crash on wrong output of systemctl version (bsc#1229539) +- Improve error handling with different OpenSSL versions +- Remove redundant run_func from salt.master.MWorker._handle_aes + +- Added: + * avoid-crash-on-wrong-output-of-systemctl-version-bsc.patch + * improve-error-handling-with-different-openssl-versio.patch + * remove-redundant-run_func-from-salt.master.mworker._.patch + +------------------------------------------------------------------- New: ---- avoid-crash-on-wrong-output-of-systemctl-version-bsc.patch improve-error-handling-with-different-openssl-versio.patch remove-redundant-run_func-from-salt.master.mworker._.patch BETA DEBUG BEGIN: New:- Added: * avoid-crash-on-wrong-output-of-systemctl-version-bsc.patch * improve-error-handling-with-different-openssl-versio.patch New: * avoid-crash-on-wrong-output-of-systemctl-version-bsc.patch * improve-error-handling-with-different-openssl-versio.patch * remove-redundant-run_func-from-salt.master.mworker._.patch New: * improve-error-handling-with-different-openssl-versio.patch * remove-redundant-run_func-from-salt.master.mworker._.patch BETA DEBUG END: ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ salt.spec ++++++ --- /var/tmp/diff_new_pack.CQeSPU/_old 2024-09-01 19:21:14.515561085 +0200 +++ /var/tmp/diff_new_pack.CQeSPU/_new 2024-09-01 19:21:14.515561085 +0200 @@ -420,6 +420,13 @@ # PATCH-FIX_OPENSUSE: https://github.com/openSUSE/salt/pull/671 # PATCH-FIX_UPSTREAM: https://github.com/saltstack/salt/pull/64173 Patch130: join-masters-if-it-is-a-list-671.patch +# PATCH-FIX_UPSTREAM: https://github.com/saltstack/salt/pull/66509 +# PATCH-FIX_UPSTREAM: https://github.com/saltstack/salt/commit/0c3ebc0795f9c2adec90118281343cae3070e0f6 +Patch131: remove-redundant-run_func-from-salt.master.mworker._.patch +# PATCH-FIX_UPSTREAM: https://github.com/saltstack/salt/pull/66818 +Patch132: improve-error-handling-with-different-openssl-versio.patch +# PATCH-FIX_UPSTREAM: https://github.com/saltstack/salt/pull/66856 +Patch133: avoid-crash-on-wrong-output-of-systemctl-version-bsc.patch ### IMPORTANT: The line below is used as a snippet marker. Do not touch it. ### SALT PATCHES LIST END ++++++ _lastrevision ++++++ --- /var/tmp/diff_new_pack.CQeSPU/_old 2024-09-01 19:21:14.627565670 +0200 +++ /var/tmp/diff_new_pack.CQeSPU/_new 2024-09-01 19:21:14.631565834 +0200 @@ -1,3 +1,3 @@ -06f92313dcbe69d75634862b15653b81dc74e340 +691a47044edb2338cd754103a09089b4a8cf9994 (No newline at EOF) ++++++ avoid-crash-on-wrong-output-of-systemctl-version-bsc.patch ++++++ >From b2faa019f0f5aa03b03e6c54c9aa60b7f6aa4f91 Mon Sep 17 00:00:00 2001 From: Victor Zhestkov <vzhest...@suse.com> Date: Fri, 30 Aug 2024 14:35:33 +0200 Subject: [PATCH] Avoid crash on wrong output of systemctl version (bsc#1229539) * Better handling output of systemctl --version * Add more cases to test grains.core._systemd --- salt/grains/core.py | 27 +++++++- tests/pytests/unit/grains/test_core.py | 89 ++++++++++++++++++++++++++ 2 files changed, 113 insertions(+), 3 deletions(-) diff --git a/salt/grains/core.py b/salt/grains/core.py index 4454c303fe..98bbd3868e 100644 --- a/salt/grains/core.py +++ b/salt/grains/core.py @@ -2432,10 +2432,31 @@ def _systemd(): """ Return the systemd grain """ - systemd_info = __salt__["cmd.run"]("systemctl --version").splitlines() + systemd_version = "UNDEFINED" + systemd_features = "" + try: + systemd_output = __salt__["cmd.run_all"]("systemctl --version") + except Exception: # pylint: disable=broad-except + log.error("Exception while executing `systemctl --version`", exc_info=True) + return { + "version": systemd_version, + "features": systemd_features, + } + if systemd_output.get("retcode") == 0: + systemd_info = systemd_output.get("stdout", "").splitlines() + try: + if systemd_info[0].startswith("systemd "): + systemd_version = systemd_info[0].split()[1] + systemd_features = systemd_info[1] + except IndexError: + pass + if systemd_version == "UNDEFINED" or systemd_features == "": + log.error( + "Unexpected output returned by `systemctl --version`: %s", systemd_output + ) return { - "version": systemd_info[0].split()[1], - "features": systemd_info[1], + "version": systemd_version, + "features": systemd_features, } diff --git a/tests/pytests/unit/grains/test_core.py b/tests/pytests/unit/grains/test_core.py index 36545287b9..b64b8c4bf8 100644 --- a/tests/pytests/unit/grains/test_core.py +++ b/tests/pytests/unit/grains/test_core.py @@ -3593,3 +3593,92 @@ def test_virtual_set_virtual_ec2(): assert virtual_grains["virtual"] == "Nitro" assert virtual_grains["virtual_subtype"] == "Amazon EC2" + + +@pytest.mark.parametrize( + "systemd_data,expected", + ( + ( + { + "pid": 1234, + "retcode": 0, + "stdout": "systemd 254 (254.3-1)\n+PAM +AUDIT -SELINUX -APPARMOR -IMA +SMACK " + "+SECCOMP +GCRYPT +GNUTLS +OPENSSL +ACL +BLKID +CURL +ELFUTILS " + "+FIDO2 +IDN2 -IDN +IPTC +KMOD +LIBCRYPTSETUP +LIBFDISK +PCRE2 " + "-PWQUALITY +P11KIT -QRENCODE +TPM2 +BZIP2 +LZ4 +XZ +ZLIB +ZSTD " + "+BPF_FRAMEWORK +XKBCOMMON +UTMP -SYSVINIT default-hierarchy=unified", + "stderr": "", + }, + { + "version": "254", + "features": "+PAM +AUDIT -SELINUX -APPARMOR -IMA +SMACK +SECCOMP +GCRYPT +GNUTLS +OPENSSL " + "+ACL +BLKID +CURL +ELFUTILS +FIDO2 +IDN2 -IDN +IPTC +KMOD +LIBCRYPTSETUP " + "+LIBFDISK +PCRE2 -PWQUALITY +P11KIT -QRENCODE +TPM2 +BZIP2 +LZ4 +XZ " + "+ZLIB +ZSTD +BPF_FRAMEWORK +XKBCOMMON +UTMP -SYSVINIT default-hierarchy=unified", + }, + ), + ( + { + "pid": 2345, + "retcode": 1, + "stdout": "", + "stderr": "some garbage in the output", + }, + { + "version": "UNDEFINED", + "features": "", + }, + ), + ( + { + "pid": 3456, + "retcode": 0, + "stdout": "unexpected stdout\none more line", + "stderr": "", + }, + { + "version": "UNDEFINED", + "features": "", + }, + ), + ( + { + "pid": 4567, + "retcode": 0, + "stdout": "", + "stderr": "", + }, + { + "version": "UNDEFINED", + "features": "", + }, + ), + ( + Exception("Some exception on calling `systemctl --version`"), + { + "version": "UNDEFINED", + "features": "", + }, + ), + ), +) +def test__systemd(systemd_data, expected): + """ + test _systemd + """ + + def mock_run_all_systemd(_): + if isinstance(systemd_data, Exception): + raise systemd_data + return systemd_data + + with patch.dict( + core.__salt__, + { + "cmd.run_all": mock_run_all_systemd, + }, + ): + ret = core._systemd() + assert "version" in ret + assert "features" in ret + assert ret == expected -- 2.46.0 ++++++ improve-error-handling-with-different-openssl-versio.patch ++++++ >From 4e226426d0897f2d9dc64891ced78487b181d40e Mon Sep 17 00:00:00 2001 From: Victor Zhestkov <vzhest...@suse.com> Date: Fri, 30 Aug 2024 14:33:51 +0200 Subject: [PATCH] Improve error handling with different OpenSSL versions * Make error checking of x509 more flexible for most recent cryptography and openSSL versions * Add test for different exception value on loading private key * Add fix for test_privkey_new_with_prereq on old OpenSSL --- salt/utils/x509.py | 3 +- .../pytests/functional/states/test_x509_v2.py | 29 +++++++++++++++++++ .../integration/states/test_x509_v2.py | 7 +++++ 3 files changed, 38 insertions(+), 1 deletion(-) diff --git a/salt/utils/x509.py b/salt/utils/x509.py index 5b2ae15882..f9fdca64d9 100644 --- a/salt/utils/x509.py +++ b/salt/utils/x509.py @@ -695,7 +695,8 @@ def load_privkey(pk, passphrase=None, get_encoding=False): return pk, "pem", None return pk except ValueError as err: - if "Bad decrypt" in str(err): + str_err = str(err) + if "Bad decrypt" in str_err or "Could not deserialize key data" in str_err: raise SaltInvocationError( "Bad decrypt - is the password correct?" ) from err diff --git a/tests/pytests/functional/states/test_x509_v2.py b/tests/pytests/functional/states/test_x509_v2.py index 929be014cd..47a1c555f8 100644 --- a/tests/pytests/functional/states/test_x509_v2.py +++ b/tests/pytests/functional/states/test_x509_v2.py @@ -3,6 +3,8 @@ from pathlib import Path import pytest +from tests.support.mock import patch + try: import cryptography import cryptography.x509 as cx509 @@ -2826,3 +2828,30 @@ def _get_privkey(pk, encoding="pem", passphrase=None): pk = base64.b64decode(pk) return pkcs12.load_pkcs12(pk, passphrase).key raise ValueError("Need correct encoding") + + +@pytest.mark.usefixtures("existing_pk") +@pytest.mark.parametrize("existing_pk", [{"passphrase": "password"}], indirect=True) +def test_exceptions_on_calling_load_pem_private_key(x509, pk_args): + pk_args["passphrase"] = "hunter1" + pk_args["overwrite"] = True + + with patch( + "cryptography.hazmat.primitives.serialization.load_pem_private_key", + side_effect=ValueError("Bad decrypt. Incorrect password?"), + ): + ret = x509.private_key_managed(**pk_args) + _assert_pk_basic(ret, "rsa", passphrase="hunter1") + + with patch( + "cryptography.hazmat.primitives.serialization.load_pem_private_key", + side_effect=ValueError( + "Could not deserialize key data. The data may be in an incorrect format, " + "the provided password may be incorrect, " + "it may be encrypted with an unsupported algorithm, " + "or it may be an unsupported key type " + "(e.g. EC curves with explicit parameters)." + ), + ): + ret = x509.private_key_managed(**pk_args) + _assert_pk_basic(ret, "rsa", passphrase="hunter1") diff --git a/tests/pytests/integration/states/test_x509_v2.py b/tests/pytests/integration/states/test_x509_v2.py index 4f94341295..ad8d904c92 100644 --- a/tests/pytests/integration/states/test_x509_v2.py +++ b/tests/pytests/integration/states/test_x509_v2.py @@ -195,6 +195,13 @@ Certificate: """ with x509_salt_master.state_tree.base.temp_file("manage_cert.sls", state): ret = x509_salt_call_cli.run("state.apply", "manage_cert") + if ( + ret.returncode == 1 + and "NotImplementedError: ECDSA keys with unnamed curves" in ret.stdout + ): + pytest.skip( + "The version of OpenSSL doesn't support ECDSA keys with unnamed curves" + ) assert ret.returncode == 0 assert ret.data[next(iter(ret.data))]["changes"] assert (tmp_path / "priv.key").exists() -- 2.46.0 ++++++ remove-redundant-run_func-from-salt.master.mworker._.patch ++++++ >From ff789d88541954e4fc1678dff728bc6a3ea7472e Mon Sep 17 00:00:00 2001 From: Victor Zhestkov <vzhest...@suse.com> Date: Fri, 30 Aug 2024 14:30:27 +0200 Subject: [PATCH] Remove redundant run_func from salt.master.MWorker._handle_aes * New request context * Fix docs * Remove redundant run_func from salt.master.MWorker._handle_aes * Get rid of run_func in salt.Minion._target --------- Co-authored-by: Daniel A. Wozniak <dwozn...@vmware.com> --- doc/topics/releases/3007.0.rst | 0 salt/_logging/impl.py | 15 ++++++--- salt/master.py | 12 ++----- salt/minion.py | 10 ++---- salt/utils/ctx.py | 60 +++++++++++----------------------- 5 files changed, 34 insertions(+), 63 deletions(-) create mode 100644 doc/topics/releases/3007.0.rst diff --git a/doc/topics/releases/3007.0.rst b/doc/topics/releases/3007.0.rst new file mode 100644 index 0000000000..e69de29bb2 diff --git a/salt/_logging/impl.py b/salt/_logging/impl.py index 1d71cb8be8..4d1ebd2495 100644 --- a/salt/_logging/impl.py +++ b/salt/_logging/impl.py @@ -26,6 +26,8 @@ GARBAGE = logging.GARBAGE = 1 QUIET = logging.QUIET = 1000 import salt.defaults.exitcodes # isort:skip pylint: disable=unused-import +import salt.utils.ctx + from salt._logging.handlers import DeferredStreamHandler # isort:skip from salt._logging.handlers import RotatingFileHandler # isort:skip from salt._logging.handlers import StreamHandler # isort:skip @@ -33,7 +35,6 @@ from salt._logging.handlers import SysLogHandler # isort:skip from salt._logging.handlers import WatchedFileHandler # isort:skip from salt._logging.mixins import LoggingMixinMeta # isort:skip from salt.exceptions import LoggingRuntimeError # isort:skip -from salt.utils.ctx import RequestContext # isort:skip from salt.utils.immutabletypes import freeze, ImmutableDict # isort:skip from salt.utils.textformat import TextFormat # isort:skip @@ -242,10 +243,14 @@ class SaltLoggingClass(LOGGING_LOGGER_CLASS, metaclass=LoggingMixinMeta): if extra is None: extra = {} - # pylint: disable=no-member - current_jid = RequestContext.current.get("data", {}).get("jid", None) - log_fmt_jid = RequestContext.current.get("opts", {}).get("log_fmt_jid", None) - # pylint: enable=no-member + current_jid = ( + salt.utils.ctx.get_request_context().get("data", {}).get("jid", None) + ) + log_fmt_jid = ( + salt.utils.ctx.get_request_context() + .get("opts", {}) + .get("log_fmt_jid", None) + ) if current_jid is not None: extra["jid"] = current_jid diff --git a/salt/master.py b/salt/master.py index d7182d10b5..49cfb68860 100644 --- a/salt/master.py +++ b/salt/master.py @@ -38,6 +38,7 @@ import salt.state import salt.utils.args import salt.utils.atomicfile import salt.utils.crypt +import salt.utils.ctx import salt.utils.event import salt.utils.files import salt.utils.gitfs @@ -58,10 +59,8 @@ import salt.wheel from salt.cli.batch_async import BatchAsync, batch_async_required from salt.config import DEFAULT_INTERVAL from salt.defaults import DEFAULT_TARGET_DELIM -from salt.ext.tornado.stack_context import StackContext from salt.transport import TRANSPORTS from salt.utils.channel import iter_transport_opts -from salt.utils.ctx import RequestContext from salt.utils.debug import ( enable_sigusr1_handler, enable_sigusr2_handler, @@ -1108,13 +1107,8 @@ class MWorker(salt.utils.process.SignalHandlingProcess): start = time.time() self.stats[cmd]["runs"] += 1 - def run_func(data): - return self.aes_funcs.run_func(data["cmd"], data) - - with StackContext( - functools.partial(RequestContext, {"data": data, "opts": self.opts}) - ): - ret = run_func(data) + with salt.utils.ctx.request_context({"data": data, "opts": self.opts}): + ret = self.aes_funcs.run_func(data["cmd"], data) if self.opts["master_stats"]: self._post_stats(start, cmd) diff --git a/salt/minion.py b/salt/minion.py index 2ccd0cd5a9..e21a017cfd 100644 --- a/salt/minion.py +++ b/salt/minion.py @@ -39,6 +39,7 @@ import salt.transport import salt.utils.args import salt.utils.context import salt.utils.crypt +import salt.utils.ctx import salt.utils.data import salt.utils.dictdiffer import salt.utils.dictupdate @@ -70,7 +71,6 @@ from salt.exceptions import ( SaltSystemExit, ) from salt.template import SLS_ENCODING -from salt.utils.ctx import RequestContext from salt.utils.debug import enable_sigusr1_handler from salt.utils.event import tagify from salt.utils.network import parse_host_port @@ -1805,18 +1805,12 @@ class Minion(MinionBase): uid = salt.utils.user.get_uid(user=opts.get("user", None)) minion_instance.proc_dir = get_proc_dir(opts["cachedir"], uid=uid) - def run_func(minion_instance, opts, data): + with salt.utils.ctx.request_context({"data": data, "opts": opts}): if isinstance(data["fun"], tuple) or isinstance(data["fun"], list): return Minion._thread_multi_return(minion_instance, opts, data) else: return Minion._thread_return(minion_instance, opts, data) - with salt.ext.tornado.stack_context.StackContext( - functools.partial(RequestContext, {"data": data, "opts": opts}) - ): - with salt.ext.tornado.stack_context.StackContext(minion_instance.ctx): - run_func(minion_instance, opts, data) - def _execute_job_function( self, function_name, function_args, executors, opts, data ): diff --git a/salt/utils/ctx.py b/salt/utils/ctx.py index a9c0931bd8..2f4b5b4c9b 100644 --- a/salt/utils/ctx.py +++ b/salt/utils/ctx.py @@ -1,49 +1,27 @@ -import threading +import contextlib +try: + # Try the stdlib C extension first + import _contextvars as contextvars +except ImportError: + # Py<3.7 + import contextvars -class ClassProperty(property): - """ - Use a classmethod as a property - http://stackoverflow.com/a/1383402/1258307 - """ +DEFAULT_CTX_VAR = "request_ctxvar" +request_ctxvar = contextvars.ContextVar(DEFAULT_CTX_VAR) - def __get__(self, cls, owner): - return self.fget.__get__(None, owner)() # pylint: disable=no-member - -class RequestContext: +@contextlib.contextmanager +def request_context(data): """ - A context manager that saves some per-thread state globally. - Intended for use with Tornado's StackContext. - https://gist.github.com/simon-weber/7755289 - Simply import this class into any module and access the current request handler by this - class's class method property 'current'. If it returns None, there's no active request. - .. code:: python - from raas.utils.ctx import RequestContext - current_request_handler = RequestContext.current + A context manager that sets and un-sets the loader context """ + tok = request_ctxvar.set(data) + try: + yield + finally: + request_ctxvar.reset(tok) - _state = threading.local() - _state.current_request = {} - - def __init__(self, current_request): - self._current_request = current_request - - @ClassProperty - @classmethod - def current(cls): - if not hasattr(cls._state, "current_request"): - return {} - return cls._state.current_request - - def __enter__(self): - self._prev_request = self.__class__.current - self.__class__._state.current_request = self._current_request - - def __exit__(self, *exc): - self.__class__._state.current_request = self._prev_request - del self._prev_request - return False - def __call__(self): - return self +def get_request_context(): + return request_ctxvar.get({}) -- 2.46.0