7
0

14 Commits

Author SHA256 Message Date
a0f24b2e44 remove saltbundlepy-deb from include-deb 2026-01-14 15:54:55 +01:00
a52c5a84f5 Drop saltbundlepy-apt dependency 2026-01-14 15:51:16 +01:00
aa70523380 Synchronize latest patches 2026-01-14 15:27:12 +01:00
6391ebfedc Synchronize git 2026-01-08 10:08:16 +01:00
Alexander Graul
fca15a9979 - Add minimum_auth_version to enforce security (CVE-2025-62349)
- Backport security fixes for vendored tornado
  * BDSA-2024-3438
  * BDSA-2024-3439
  * BDSA-2024-9026
- Junos module yaml loader fix (CVE-2025-62348)
- Added:
  * backport-3006.17-security-fixes-739.patch
2025-11-25 16:33:56 +01:00
98722f7422 Merge pull request 'Synchronize lastrevision' (#9) from mczernek/venv-salt-minion:sync-testing into bundle_testing
Reviewed-on: #9
Reviewed-by: Pablo Suárez Hernández <psuarezhernandez@noreply.src.opensuse.org>
2025-11-13 13:39:56 +01:00
a564c87732 Synchronize lastrevision 2025-11-13 13:16:47 +01:00
f0b919b9eb Merge pull request 'Fix TLS and x509 modules for OSes with older cryptography module' (#6) from mczernek/venv-salt-minion:mcz_bundle_testing into bundle_testing
Reviewed-on: #6
Reviewed-by: Pablo Suárez Hernández <psuarezhernandez@noreply.src.opensuse.org>
2025-11-11 10:38:27 +01:00
3b5688587a Fix TLS and x509 modules for OSes with older cryptography module 2025-11-11 09:40:34 +01:00
d724ea46a7 Merge pull request '[bundle_testing] Fix Salt for Python > 3.11 (bsc#1252285) (bsc#1252244)' (#4) from PSuarezHernandez/venv-salt-minion:bundle_testing-tw-fixes into bundle_testing
Reviewed-on: #4
Reviewed-by: Victor Zhestkov <vizhestkov@noreply.src.opensuse.org>
2025-11-10 11:14:24 +01:00
08df922270 Bump _lastrevision after skiping unneeded fix 2025-11-10 09:59:58 +00:00
f673ca273e Fix Salt for Python > 3.11 (bsc#1252285) (bsc#1252244)
* Use external tornado on Python > 3.11
* Make tls and x509 to use python-cryptography
* Remove usage of spwd
2025-11-10 09:23:21 +00:00
9c78e0d1ef Merge pull request 'Add missing patches to "bundle_testing" branch' (#2) from PSuarezHernandez/venv-salt-minion:bundle_testing-missing-patches into bundle_testing
Reviewed-on: #2
Reviewed-by: Marek Czernek <mczernek@noreply.src.opensuse.org>
2025-10-30 11:30:34 +01:00
a8dda26a96 Add missing patches to bundle_testing 2025-10-29 10:47:46 +00:00
18 changed files with 13836 additions and 6 deletions

View File

@@ -1 +1 @@
3084db7285ade6f5552ea3e79c11d57a17a6b529
720580e5796703426c70d97b2db1487a3d504349

View File

@@ -0,0 +1,26 @@
From ea87110248948eb61628cda607ae1af34e83fdfe Mon Sep 17 00:00:00 2001
From: Victor Zhestkov <vzhestkov@suse.com>
Date: Wed, 1 Oct 2025 14:19:27 +0200
Subject: [PATCH] Add python3.11 as preferable for salt-ssh to avoid
tests fails
---
salt/client/ssh/__init__.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/salt/client/ssh/__init__.py b/salt/client/ssh/__init__.py
index 1d8426b7c2..bfb7d3d1d1 100644
--- a/salt/client/ssh/__init__.py
+++ b/salt/client/ssh/__init__.py
@@ -157,7 +157,7 @@ SSH_PY_CODE='import base64;
if [ -n "$DEBUG" ]
then set -x
fi
-PYTHON_CMDS="/var/tmp/venv-salt-minion/bin/python python3 /usr/libexec/platform-python python27 python2.7 python26 python2.6 python2 python"
+PYTHON_CMDS="/var/tmp/venv-salt-minion/bin/python python3.11 python3 /usr/libexec/platform-python python27 python2.7 python26 python2.6 python2 python"
for py_cmd in $PYTHON_CMDS
do
if command -v "$py_cmd" >/dev/null 2>&1 && "$py_cmd" -c "import sys; sys.exit(not (sys.version_info >= (2, 6)));"
--
2.51.0

View File

@@ -0,0 +1,76 @@
From 6a57e821f3e16981c01078dc7e928672a6f77b88 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pablo=20Su=C3=A1rez=20Hern=C3=A1ndez?=
<psuarezhernandez@suse.com>
Date: Mon, 6 Oct 2025 09:34:17 +0100
Subject: [PATCH] Allow libgit2 to guess sysdir homedir successfully
(bsc#1250520) (bsc#1227207) (#731)
* Allow libgit2 to guess sysdir homedir successfully
This prevents the generic error:
_pygit2.GitError: error loading known_hosts:
which is happening in certain pygit2/libgit2 versions
* Fix pygit2 unit test to check HOME is injected
---
salt/utils/gitfs.py | 19 ++++++++++++-------
tests/pytests/unit/utils/test_gitfs.py | 4 +++-
2 files changed, 15 insertions(+), 8 deletions(-)
diff --git a/salt/utils/gitfs.py b/salt/utils/gitfs.py
index 2a8ecf1d0cb..d597c17b870 100644
--- a/salt/utils/gitfs.py
+++ b/salt/utils/gitfs.py
@@ -110,6 +110,15 @@ try:
with warnings.catch_warnings():
warnings.simplefilter("ignore")
+ if "HOME" not in os.environ:
+ # Make sure $HOME env variable is set before importing pygit2 to prevent
+ # _pygit2.GitError: error loading known_hosts in some libgit2 versions.
+ # The internal "git_sysdir__dirs" from libgit2, is initializated
+ # when importing pygit2. The $HOME env must be present to allow libgit2
+ # guessing function to successfully set the homedir in the initializated
+ # libgit2 stack.
+ # https://github.com/saltstack/salt/issues/64121
+ os.environ["HOME"] = os.path.expanduser("~")
import pygit2
PYGIT2_VERSION = Version(pygit2.__version__)
LIBGIT2_VERSION = Version(pygit2.LIBGIT2_VERSION)
@@ -1890,13 +1899,9 @@ class Pygit2(GitProvider):
"""
# https://github.com/libgit2/pygit2/issues/339
# https://github.com/libgit2/libgit2/issues/2122
- # https://github.com/saltstack/salt/issues/64121
- home = os.path.expanduser("~")
- if "HOME" not in os.environ:
- # Make sure $HOME env variable is set to prevent
- # _pygit2.GitError: error loading known_hosts in some libgit2 versions.
- os.environ["HOME"] = home
- pygit2.settings.search_path[pygit2.GIT_CONFIG_LEVEL_GLOBAL] = home
+ pygit2.settings.search_path[pygit2.GIT_CONFIG_LEVEL_GLOBAL] = (
+ os.path.expanduser("~")
+ )
new = False
if not os.listdir(self._cachedir):
# Repo cachedir is empty, initialize a new repo there
diff --git a/tests/pytests/unit/utils/test_gitfs.py b/tests/pytests/unit/utils/test_gitfs.py
index baedd9fd708..4ab8e7735f0 100644
--- a/tests/pytests/unit/utils/test_gitfs.py
+++ b/tests/pytests/unit/utils/test_gitfs.py
@@ -251,7 +251,9 @@ def test_checkout_pygit2_with_home_env_unset(_prepare_provider):
provider.credentials = None
with patched_environ(__cleanup__=["HOME"]):
assert "HOME" not in os.environ
- provider.init_remote()
+ import importlib
+
+ importlib.reload(salt.utils.gitfs)
assert "HOME" in os.environ
--
2.51.0

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,36 @@
From 002a58144563a15034f982b19ba851326535570a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pablo=20Su=C3=A1rez=20Hern=C3=A1ndez?=
<psuarezhernandez@suse.com>
Date: Wed, 29 Oct 2025 10:30:58 +0000
Subject: [PATCH] Do not break signature verification on latest
M2Crypto versions (bsc#1251776)
---
salt/crypt.py | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/salt/crypt.py b/salt/crypt.py
index 981f633d51f..29fd159b48c 100644
--- a/salt/crypt.py
+++ b/salt/crypt.py
@@ -243,7 +243,7 @@ def sign_message(privkey_path, message, passphrase=None):
md = EVP.MessageDigest("sha1")
md.update(salt.utils.stringutils.to_bytes(message))
digest = md.final()
- return key.sign(digest)
+ return key.sign(digest, algo="sha1")
else:
signer = PKCS1_v1_5.new(key)
return signer.sign(SHA.new(salt.utils.stringutils.to_bytes(message)))
@@ -262,7 +262,7 @@ def verify_signature(pubkey_path, message, signature):
md.update(salt.utils.stringutils.to_bytes(message))
digest = md.final()
try:
- return pubkey.verify(digest, signature)
+ return pubkey.verify(digest, signature, algo="sha1")
except RSA.RSAError as exc:
log.debug("Signature verification failed: %s", exc.args[0])
return False
--
2.51.1

View File

@@ -0,0 +1,65 @@
From dc3027bab4925228cacde00ae626bf651d0a0c3b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pablo=20Su=C3=A1rez=20Hern=C3=A1ndez?=
<psuarezhernandez@suse.com>
Date: Wed, 17 Sep 2025 09:56:44 +0200
Subject: [PATCH] Even more reliable pillar timeout test
* Even more reliable pillar timeout test
* Use sys.executable on test_pillar_timeout test
---------
Co-authored-by: Daniel A. Wozniak <dwozniak@vmware.com>
---
.../integration/minion/test_return_retries.py | 18 +++++++++++-------
1 file changed, 11 insertions(+), 7 deletions(-)
diff --git a/tests/pytests/integration/minion/test_return_retries.py b/tests/pytests/integration/minion/test_return_retries.py
index 45dea9c4c76..9b71bed58c5 100644
--- a/tests/pytests/integration/minion/test_return_retries.py
+++ b/tests/pytests/integration/minion/test_return_retries.py
@@ -5,6 +5,7 @@ import pytest
from saltfactories.utils import random_string
from tests.support.helpers import dedent
+import salt.utils.files
@pytest.fixture(scope="function")
@@ -57,14 +58,13 @@ def test_publish_retry(salt_master, salt_minion_retry, salt_cli, salt_run_cli):
@pytest.mark.slow_test
@pytest.mark.flaky(max_runs=4)
-def test_pillar_timeout(salt_master_factory):
- cmd = (
- sys.executable
- + ' -c "import time; time.sleep(4.8); print(\'{\\"foo\\": \\"bar\\"}\');"'
- ).strip()
+def test_pillar_timeout(salt_master_factory, tmp_path):
+ with salt.utils.files.fopen(tmp_path / "script.py", "w") as fp:
+ fp.write('print(\'{"foo": "bar"}\');\n')
+
master_overrides = {
"ext_pillar": [
- {"cmd_json": cmd},
+ {"cmd_json": f"{sys.executable} {tmp_path / 'script.py'}"},
],
"auto_accept": True,
"worker_threads": 3,
@@ -110,7 +110,11 @@ def test_pillar_timeout(salt_master_factory):
sls_tempfile = master.state_tree.base.temp_file(
"{}.sls".format(sls_name), sls_contents
)
- with master.started(), minion1.started(), minion2.started(), minion3.started(), minion4.started(), sls_tempfile:
+ with master.started(), minion1.started(), minion2.started(), minion3.started(), minion4.started(), (
+ sls_tempfile
+ ):
+ with salt.utils.files.fopen(tmp_path / "script.py", "w") as fp:
+ fp.write('import time; time.sleep(6); print(\'{"foo": "bang"}\');\n')
proc = cli.run("state.sls", sls_name, minion_tgt="*")
# At least one minion should have a Pillar timeout
print(proc)
--
2.51.0

View File

@@ -0,0 +1,164 @@
From 85d5cab70fc36994427fb4d4ca483b09f55d28f7 Mon Sep 17 00:00:00 2001
From: Marek Czernek <marek.czernek@suse.com>
Date: Thu, 8 Jan 2026 09:17:14 +0100
Subject: [PATCH] Extend fails to warnings until 2027 (#742)
---
salt/_logging/handlers.py | 6 +++---
salt/log/__init__.py | 2 +-
salt/log/handlers/__init__.py | 2 +-
salt/log/mixins.py | 2 +-
salt/log/setup.py | 4 ++--
salt/modules/aptpkg.py | 2 +-
salt/modules/cassandra_mod.py | 2 +-
salt/returners/cassandra_return.py | 2 +-
salt/returners/django_return.py | 2 +-
9 files changed, 12 insertions(+), 12 deletions(-)
diff --git a/salt/_logging/handlers.py b/salt/_logging/handlers.py
index d8bc68a49db..6b1521d7915 100644
--- a/salt/_logging/handlers.py
+++ b/salt/_logging/handlers.py
@@ -36,7 +36,7 @@ class TemporaryLoggingHandler(logging.NullHandler):
def __init__(self, level=logging.NOTSET, max_queue_size=10000):
warn_until_date(
- "20260101",
+ "20270101",
"Please stop using '{name}.TemporaryLoggingHandler'. "
"'{name}.TemporaryLoggingHandler' will go away after "
"{{date}}.".format(name=__name__),
@@ -229,7 +229,7 @@ if sys.version_info < (3, 7):
def __init__(self, queue): # pylint: disable=useless-super-delegation
super().__init__(queue)
warn_until_date(
- "20260101",
+ "20270101",
"Please stop using '{name}.QueueHandler' and instead "
"use 'logging.handlers.QueueHandler'. "
"'{name}.QueueHandler' will go away after "
@@ -287,7 +287,7 @@ else:
def __init__(self, queue): # pylint: disable=useless-super-delegation
super().__init__(queue)
warn_until_date(
- "20260101",
+ "20270101",
"Please stop using '{name}.QueueHandler' and instead "
"use 'logging.handlers.QueueHandler'. "
"'{name}.QueueHandler' will go away after "
diff --git a/salt/log/__init__.py b/salt/log/__init__.py
index 69bfa8ed15b..392fd1561dd 100644
--- a/salt/log/__init__.py
+++ b/salt/log/__init__.py
@@ -24,7 +24,7 @@ from salt.log.setup import (
from salt.utils.versions import warn_until_date
warn_until_date(
- "20260101",
+ "20270101",
"Please stop using '{name}' and instead use 'salt._logging'. "
"'{name}' will go away after {{date}}.".format(name=__name__),
stacklevel=3,
diff --git a/salt/log/handlers/__init__.py b/salt/log/handlers/__init__.py
index 55cf10cdb78..f6f8102fd65 100644
--- a/salt/log/handlers/__init__.py
+++ b/salt/log/handlers/__init__.py
@@ -12,7 +12,7 @@ from salt._logging.handlers import (
from salt.utils.versions import warn_until_date
warn_until_date(
- "20260101",
+ "20270101",
"Please stop using '{name}' and instead use 'salt._logging.handlers'. "
"'{name}' will go away after {{date}}.".format(name=__name__),
)
diff --git a/salt/log/mixins.py b/salt/log/mixins.py
index 65f5ed7f78a..4564ac225c3 100644
--- a/salt/log/mixins.py
+++ b/salt/log/mixins.py
@@ -11,7 +11,7 @@ from salt.utils.versions import warn_until_date
# pylint: enable=unused-import
warn_until_date(
- "20260101",
+ "20270101",
"Please stop using '{name}' and instead use 'salt._logging.mixins'. "
"'{name}' will go away after {{date}}.".format(name=__name__),
)
diff --git a/salt/log/setup.py b/salt/log/setup.py
index f4c80b0f280..5435d6de88f 100644
--- a/salt/log/setup.py
+++ b/salt/log/setup.py
@@ -21,7 +21,7 @@ from salt._logging.impl import set_log_record_factory as setLogRecordFactory
from salt.utils.versions import warn_until_date
warn_until_date(
- "20260101",
+ "20270101",
"Please stop using '{name}' and instead use 'salt._logging'. "
"'{name}' will go away after {{date}}. Do note however that "
"'salt._logging' is now considered a non public implementation "
@@ -34,7 +34,7 @@ def _deprecated_warning(func):
@wraps(func)
def wrapper(*args, **kwargs):
warn_until_date(
- "20260101",
+ "20270101",
"Please stop using 'salt.log.setup.{name}()' as it no longer does anything and "
"will go away after {{date}}.".format(name=func.__qualname__),
stacklevel=4,
diff --git a/salt/modules/aptpkg.py b/salt/modules/aptpkg.py
index 8244c639e85..f7884d9ccde 100644
--- a/salt/modules/aptpkg.py
+++ b/salt/modules/aptpkg.py
@@ -3215,7 +3215,7 @@ def expand_repo_def(**kwargs):
NOT USABLE IN THE CLI
"""
warn_until_date(
- "20260101",
+ "20270101",
"The pkg.expand_repo_def function is deprecated and set for removal "
"after {date}. This is only unsed internally by the apt pkg state "
"module. If that's not the case, please file an new issue requesting "
diff --git a/salt/modules/cassandra_mod.py b/salt/modules/cassandra_mod.py
index db9c8821920..660a1ff70dd 100644
--- a/salt/modules/cassandra_mod.py
+++ b/salt/modules/cassandra_mod.py
@@ -45,7 +45,7 @@ def __virtual__():
)
warn_until_date(
- "20260101",
+ "20270101",
"The cassandra returner is broken and deprecated, and will be removed"
" after {date}. Use the cassandra_cql returner instead",
)
diff --git a/salt/returners/cassandra_return.py b/salt/returners/cassandra_return.py
index 5fcc00ee8ce..00c6748eaeb 100644
--- a/salt/returners/cassandra_return.py
+++ b/salt/returners/cassandra_return.py
@@ -53,7 +53,7 @@ def __virtual__():
if not HAS_PYCASSA:
return False, "Could not import cassandra returner; pycassa is not installed."
warn_until_date(
- "20260101",
+ "20270101",
"The cassandra returner is broken and deprecated, and will be removed"
" after {date}. Use the cassandra_cql returner instead",
)
diff --git a/salt/returners/django_return.py b/salt/returners/django_return.py
index 474653f3831..46f5c8791e8 100644
--- a/salt/returners/django_return.py
+++ b/salt/returners/django_return.py
@@ -57,7 +57,7 @@ __virtualname__ = "django"
def __virtual__():
warn_until_date(
- "20260101",
+ "20270101",
"The django returner is broken and deprecated, and will be removed"
" after {date}.",
)
--
2.52.0

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,290 @@
From 7f15657c26c4e5e9fabc72f4da2d9a91353d5d3a Mon Sep 17 00:00:00 2001
From: Marek Czernek <marek.czernek@suse.com>
Date: Tue, 11 Nov 2025 08:46:20 +0100
Subject: [PATCH] Fix tls and x509 modules for older cryptography
module (#737)
---
salt/modules/tls.py | 73 +++++++++++++++++-------
salt/modules/x509.py | 128 +++++++++++++++++++++++++++++++++++--------
2 files changed, 158 insertions(+), 43 deletions(-)
diff --git a/salt/modules/tls.py b/salt/modules/tls.py
index 9d29bd1e9b..4d7db87f93 100644
--- a/salt/modules/tls.py
+++ b/salt/modules/tls.py
@@ -104,6 +104,7 @@ import logging
import math
import os
import re
+import sys
import time
from datetime import datetime
@@ -1594,6 +1595,9 @@ def create_pkcs12(ca_name, CN, passphrase="", cacert_path=None, replace=False):
salt '*' tls.create_pkcs12 test localhost
"""
+ # Necessary for OSes with older cryptography module
+ compat_mode = sys.version_info < (3,12)
+
set_ca_path(cacert_path)
p12_path = f"{cert_base_path()}/{ca_name}/certs/{CN}.p12"
ca_cert_path = f"{cert_base_path()}/{ca_name}/{ca_name}_ca_cert.crt"
@@ -1605,7 +1609,12 @@ def create_pkcs12(ca_name, CN, passphrase="", cacert_path=None, replace=False):
try:
with salt.utils.files.fopen(ca_cert_path, "rb") as fhr:
- ca_cert = cryptography.x509.load_pem_x509_certificate(fhr.read())
+ if compat_mode:
+ ca_cert = OpenSSL.crypto.load_certificate(
+ OpenSSL.crypto.FILETYPE_PEM, fhr.read()
+ )
+ else:
+ ca_cert = cryptography.x509.load_pem_x509_certificate(fhr.read())
except OSError:
return 'There is no CA named "{}"'.format(ca_name)
except ValueError as e:
@@ -1613,34 +1622,58 @@ def create_pkcs12(ca_name, CN, passphrase="", cacert_path=None, replace=False):
try:
with salt.utils.files.fopen(cert_path, "rb") as fhr:
- cert = cryptography.x509.load_pem_x509_certificate(fhr.read())
+ if compat_mode:
+ cert = OpenSSL.crypto.load_certificate(
+ OpenSSL.crypto.FILETYPE_PEM, fhr.read()
+ )
+ else:
+ cert = cryptography.x509.load_pem_x509_certificate(fhr.read())
with salt.utils.files.fopen(priv_key_path, "rb") as fhr:
- key = cryptography_serialization.load_pem_private_key(
- fhr.read(),
- password=None,
- )
+ if compat_mode:
+ key = OpenSSL.crypto.load_privatekey(
+ OpenSSL.crypto.FILETYPE_PEM, fhr.read()
+ )
+ else:
+ key = cryptography_serialization.load_pem_private_key(
+ fhr.read(),
+ password=None,
+ )
except OSError:
return 'There is no certificate that matches the CN "{}"'.format(CN)
except ValueError as e:
return f'Could not load certificate {cert_path}: {e}'
- if passphrase:
- encryption_algorithm = cryptography_serialization.BestAvailableEncryption(
- salt.utils.stringutils.to_bytes(passphrase)
- )
+ if compat_mode:
+ pkcs12 = OpenSSL.crypto.PKCS12()
+
+ pkcs12.set_certificate(cert)
+ pkcs12.set_ca_certificates([ca_cert])
+ pkcs12.set_privatekey(key)
+
+ with salt.utils.files.fopen(
+ "{}/{}/certs/{}.p12".format(cert_base_path(), ca_name, CN), "wb"
+ ) as ofile:
+ ofile.write(
+ pkcs12.export(passphrase=salt.utils.stringutils.to_bytes(passphrase))
+ )
else:
- encryption_algorithm = cryptography_serialization.NoEncryption()
+ if passphrase:
+ encryption_algorithm = cryptography_serialization.BestAvailableEncryption(
+ salt.utils.stringutils.to_bytes(passphrase)
+ )
+ else:
+ encryption_algorithm = cryptography_serialization.NoEncryption()
- pkcs12 = cryptography_pkcs12.serialize_key_and_certificates(
- name=salt.utils.stringutils.to_bytes(CN),
- key=key,
- cert=cert,
- cas=[ca_cert],
- encryption_algorithm=encryption_algorithm,
- )
+ pkcs12 = cryptography_pkcs12.serialize_key_and_certificates(
+ name=salt.utils.stringutils.to_bytes(CN),
+ key=key,
+ cert=cert,
+ cas=[ca_cert],
+ encryption_algorithm=encryption_algorithm,
+ )
- with salt.utils.files.fopen(p12_path, "wb") as ofile:
- ofile.write(pkcs12)
+ with salt.utils.files.fopen(p12_path, "wb") as ofile:
+ ofile.write(pkcs12)
return 'Created PKCS#12 Certificate for "{0}": "{1}/{2}/certs/{0}.p12"'.format(
CN,
diff --git a/salt/modules/x509.py b/salt/modules/x509.py
index 164541fc76..373e394856 100644
--- a/salt/modules/x509.py
+++ b/salt/modules/x509.py
@@ -32,16 +32,20 @@ import tempfile
import salt.exceptions
import salt.utils.data
-import salt.utils.dictupdate
import salt.utils.files
import salt.utils.path
import salt.utils.platform
import salt.utils.stringutils
import salt.utils.versions
-import salt.utils.x509 as x509util
from salt.state import STATE_INTERNAL_KEYWORDS as _STATE_INTERNAL_KEYWORDS
from salt.utils.odict import OrderedDict
+# Necessary for OSes with older cryptography module
+COMPAT_MODE = sys.version_info < (3,12)
+if not COMPAT_MODE:
+ import salt.utils.dictupdate
+ import salt.utils.x509 as x509util
+
try:
import M2Crypto
@@ -988,35 +992,113 @@ def create_crl(
if revoked is None:
revoked = []
+ if COMPAT_MODE:
+ crl = OpenSSL.crypto.CRL()
+ for rev_item in revoked:
+ if "certificate" in rev_item:
+ rev_cert = read_certificate(rev_item["certificate"])
+ rev_item["serial_number"] = rev_cert["Serial Number"]
+ rev_item["not_after"] = rev_cert["Not After"]
- for rev_item in revoked:
- if "reason" in rev_item:
- salt.utils.dictupdate.set_dict_key_value(
- rev_item, "extensions:CRLReason", rev_item["reason"]
+ serial_number = rev_item["serial_number"].replace(":", "")
+ # OpenSSL bindings requires this to be a non-unicode string
+ serial_number = salt.utils.stringutils.to_bytes(serial_number)
+
+ if "not_after" in rev_item and not include_expired:
+ not_after = datetime.datetime.strptime(
+ rev_item["not_after"], "%Y-%m-%d %H:%M:%S"
+ )
+ if datetime.datetime.now() > not_after:
+ continue
+
+ if "revocation_date" not in rev_item:
+ rev_item["revocation_date"] = datetime.datetime.now().strftime(
+ "%Y-%m-%d %H:%M:%S"
+ )
+
+ rev_date = datetime.datetime.strptime(
+ rev_item["revocation_date"], "%Y-%m-%d %H:%M:%S"
)
+ rev_date = rev_date.strftime("%Y%m%d%H%M%SZ")
+ rev_date = salt.utils.stringutils.to_bytes(rev_date)
- builder, private_key_obj = x509util.build_crl(
- signing_private_key=signing_private_key,
- signing_private_key_passphrase=signing_private_key_passphrase,
- include_expired=include_expired,
- revoked=revoked,
- signing_cert=signing_cert,
- days_valid=days_valid,
- )
+ rev = OpenSSL.crypto.Revoked()
+ rev.set_serial(salt.utils.stringutils.to_bytes(serial_number))
+ rev.set_rev_date(salt.utils.stringutils.to_bytes(rev_date))
+
+ if "reason" in rev_item:
+ # Same here for OpenSSL bindings and non-unicode strings
+ reason = salt.utils.stringutils.to_bytes(rev_item["reason"])
+ rev.set_reason(reason)
+
+ crl.add_revoked(rev)
+
+ signing_cert = _text_or_file(signing_cert)
+ cert = OpenSSL.crypto.load_certificate(
+ OpenSSL.crypto.FILETYPE_PEM, get_pem_entry(signing_cert, pem_type="CERTIFICATE")
+ )
+ signing_private_key = _get_private_key_obj(
+ signing_private_key, passphrase=signing_private_key_passphrase
+ ).as_pem(cipher=None)
+ key = OpenSSL.crypto.load_privatekey(
+ OpenSSL.crypto.FILETYPE_PEM, get_pem_entry(signing_private_key)
+ )
+
+ export_kwargs = {
+ "cert": cert,
+ "key": key,
+ "type": OpenSSL.crypto.FILETYPE_PEM,
+ "days": days_valid,
+ }
+ if digest:
+ export_kwargs["digest"] = salt.utils.stringutils.to_bytes(digest)
+ else:
+ log.warning("No digest specified. The default md5 digest will be used.")
+
+ try:
+ crltext = crl.export(**export_kwargs)
+ except (TypeError, ValueError):
+ log.warning(
+ "Error signing crl with specified digest. Are you using "
+ "pyopenssl 0.15 or newer? The default md5 digest will be used."
+ )
+ export_kwargs.pop("digest", None)
+ crltext = crl.export(**export_kwargs)
+
+ if text:
+ return crltext
+
+ return write_pem(text=crltext, path=path, pem_type="X509 CRL")
- if digest:
- hashing_algorithm = x509util.get_hashing_algorithm(digest)
else:
- log.warning("No digest specified. The default md5 digest will be used.")
- hashing_algorithm = x509util.get_hashing_algorithm("MD5")
+ for rev_item in revoked:
+ if "reason" in rev_item:
+ salt.utils.dictupdate.set_dict_key_value(
+ rev_item, "extensions:CRLReason", rev_item["reason"]
+ )
- crl = builder.sign(private_key_obj, algorithm=hashing_algorithm)
- crl_bytes = crl.public_bytes(x509util.serialization.Encoding.PEM)
+ builder, private_key_obj = x509util.build_crl(
+ signing_private_key=signing_private_key,
+ signing_private_key_passphrase=signing_private_key_passphrase,
+ include_expired=include_expired,
+ revoked=revoked,
+ signing_cert=signing_cert,
+ days_valid=days_valid,
+ )
- if text:
- return crl_bytes.decode()
+ if digest:
+ hashing_algorithm = x509util.get_hashing_algorithm(digest)
+ else:
+ log.warning("No digest specified. The default md5 digest will be used.")
+ hashing_algorithm = x509util.get_hashing_algorithm("MD5")
- return write_pem(text=crl_bytes, path=path, pem_type="X509 CRL")
+ crl = builder.sign(private_key_obj, algorithm=hashing_algorithm)
+ crl_bytes = crl.public_bytes(x509util.serialization.Encoding.PEM)
+
+ if text:
+ return crl_bytes.decode()
+
+ return write_pem(text=crl_bytes, path=path, pem_type="X509 CRL")
def sign_remote_certificate(argdic, **kwargs):
--
2.51.1

View File

@@ -0,0 +1,232 @@
From 324c7740438fd0bbcde1e0b6be70c92007c022ac Mon Sep 17 00:00:00 2001
From: Victor Zhestkov <vzhestkov@suse.com>
Date: Wed, 14 Jan 2026 14:08:48 +0100
Subject: [PATCH] Fixes for security issues (CVE-2025-13836,
CVE-2025-67725, CVE-2025-67726) (#744)
* Fixes for security issues (CVE-2025-67725)
httputil: Fix quadratic performance of repeated header lines
Previouisly, when many header lines with the same name were found
in an HTTP request or response, repeated string concatenation would
result in quadratic performance. This change does the concatenation
lazily (with a cache) so that repeated headers can be processed
efficiently.
Security: The previous behavior allowed a denial of service attack
via a maliciously crafted HTTP message, but only if the
max_header_size was increased from its default of 64kB.
* Patch tornado for (BDSA-2025-60811, CVE-2025-67726)
httputil: Fix quadratic behavior in _parseparam
Prior to this change, _parseparam had O(n^2) behavior when parsing
certain inputs, which could be a DoS vector. This change adapts
logic from the equivalent function in the python standard library
in https://github.com/python/cpython/pull/136072/files
* Set a safe limit to http.client response read (CVE-2025-13836)
https://github.com/saltstack/salt/pull/68611
* Remove duplicated test
---------
Co-authored-by: Twangboy <shane.d.lee@gmail.com>
Co-authored-by: Marek Czernek <marek.czernek@suse.com>
---
salt/ext/tornado/httputil.py | 56 ++++++++++++++++++--------
salt/ext/tornado/test/httputil_test.py | 38 +++++++++++++++++
salt/utils/nxos.py | 3 +-
3 files changed, 79 insertions(+), 18 deletions(-)
diff --git a/salt/ext/tornado/httputil.py b/salt/ext/tornado/httputil.py
index 4866b0c991..78953c5f6b 100644
--- a/salt/ext/tornado/httputil.py
+++ b/salt/ext/tornado/httputil.py
@@ -139,8 +139,8 @@ class HTTPHeaders(MutableMapping):
"""
def __init__(self, *args, **kwargs):
- self._dict = {} # type: typing.Dict[str, str]
self._as_list = {} # type: typing.Dict[str, typing.List[str]]
+ self._combined_cache = {} # type: typing.Dict[str, str]
self._last_key = None
if len(args) == 1 and len(kwargs) == 0 and isinstance(args[0], HTTPHeaders):
# Copy constructor
@@ -158,9 +158,7 @@ class HTTPHeaders(MutableMapping):
norm_name = _normalized_headers[name]
self._last_key = norm_name
if norm_name in self:
- self._dict[norm_name] = (
- native_str(self[norm_name]) + "," + native_str(value)
- )
+ self._combined_cache.pop(norm_name, None)
self._as_list[norm_name].append(value)
else:
self[norm_name] = value
@@ -193,7 +191,7 @@ class HTTPHeaders(MutableMapping):
# continuation of a multi-line header
new_part = " " + line.lstrip(HTTP_WHITESPACE)
self._as_list[self._last_key][-1] += new_part
- self._dict[self._last_key] += new_part
+ self._combined_cache.pop(self._last_key, None)
else:
name, value = line.split(":", 1)
self.add(name, value.strip(HTTP_WHITESPACE))
@@ -216,23 +214,33 @@ class HTTPHeaders(MutableMapping):
def __setitem__(self, name, value):
norm_name = _normalized_headers[name]
- self._dict[norm_name] = value
+ self._combined_cache[norm_name] = value
self._as_list[norm_name] = [value]
+ def __contains__(self, name):
+ # This is an important optimization to avoid the expensive concatenation
+ # in __getitem__ when it's not needed.
+ if not isinstance(name, str):
+ return False
+ return name in self._as_list
+
def __getitem__(self, name):
# type: (str) -> str
- return self._dict[_normalized_headers[name]]
+ header = _normalized_headers[name]
+ if header not in self._combined_cache:
+ self._combined_cache[header] = ",".join(self._as_list[header])
+ return self._combined_cache[header]
def __delitem__(self, name):
norm_name = _normalized_headers[name]
- del self._dict[norm_name]
+ del self._combined_cache[norm_name]
del self._as_list[norm_name]
def __len__(self):
- return len(self._dict)
+ return len(self._as_list)
def __iter__(self):
- return iter(self._dict)
+ return iter(self._as_list)
def copy(self):
# defined in dict but not in MutableMapping.
@@ -894,19 +902,33 @@ def parse_response_start_line(line):
# combinations of semicolons and double quotes.
# It has also been modified to support valueless parameters as seen in
# websocket extension negotiations.
+#
+# _parseparam has been further modified with the logic from
+# https://github.com/python/cpython/pull/136072/files
+# to avoid quadratic behavior when parsing semicolons in quoted strings.
+#
+# TODO: See if we can switch to email.message.Message for this functionality.
+# This is the suggested replacement for the cgi.py module now that cgi has
+# been removed from recent versions of Python. We need to verify that
+# the email module is consistent with our existing behavior (and all relevant
def _parseparam(s):
- while s[:1] == ";":
- s = s[1:]
- end = s.find(";")
- while end > 0 and (s.count('"', 0, end) - s.count('\\"', 0, end)) % 2:
- end = s.find(";", end + 1)
+ start = 0
+ while s.find(";", start) == start:
+ start += 1
+ end = s.find(";", start)
+ ind, diff = start, 0
+ while end > 0:
+ diff += s.count('"', ind, end) - s.count('\\"', ind, end)
+ if diff % 2 == 0:
+ break
+ end, ind = ind, s.find(";", end + 1)
if end < 0:
end = len(s)
- f = s[:end]
+ f = s[start:end]
yield f.strip()
- s = s[end:]
+ start = end
def _parse_header(line):
diff --git a/salt/ext/tornado/test/httputil_test.py b/salt/ext/tornado/test/httputil_test.py
index c613b4e41a..bdbfaa2b6a 100644
--- a/salt/ext/tornado/test/httputil_test.py
+++ b/salt/ext/tornado/test/httputil_test.py
@@ -245,6 +245,30 @@ Foo
self.assertEqual(file["body"], b"Foo")
+ def test_disposition_param_linear_performance(self):
+ # This is a regression test for performance of parsing parameters
+ # to the content-disposition header, specifically for semicolons within
+ # quoted strings.
+ def f(n):
+ start = time.time()
+ message = (
+ b"--1234\r\nContent-Disposition: form-data; "
+ + b'x="'
+ + b";" * n
+ + b'"; '
+ + b'name="files"; filename="a.txt"\r\n\r\nFoo\r\n--1234--\r\n'
+ )
+ args: dict[str, list[bytes]] = {}
+ files: dict[str, list[HTTPFile]] = {}
+ parse_multipart_form_data(b"1234", message, args, files)
+ return time.time() - start
+
+ d1 = f(1_000)
+ d2 = f(10_000)
+ if d2 / d1 > 20:
+ self.fail(f"Disposition param parsing is not linear: {d1=} vs {d2=}")
+
+
class HTTPHeadersTest(unittest.TestCase):
def test_multi_line(self):
# Lines beginning with whitespace are appended to the previous line
@@ -367,6 +391,20 @@ Foo: even
headers2 = HTTPHeaders.parse(str(headers))
self.assertEquals(headers, headers2)
+ def test_linear_performance(self):
+ def f(n):
+ start = time.time()
+ headers = HTTPHeaders()
+ for i in range(n):
+ headers.add("X-Foo", "bar")
+ return time.time() - start
+
+ # This runs under 50ms on my laptop as of 2025-12-09.
+ d1 = f(10000)
+ d2 = f(100000)
+ if d2 / d1 > 20:
+ # d2 should be about 10x d1 but allow a wide margin for variability.
+ self.fail("HTTPHeaders.add() does not scale linearly: %s vs %s" % (d1, d2))
class FormatTimestampTest(unittest.TestCase):
# Make sure that all the input types are supported.
diff --git a/salt/utils/nxos.py b/salt/utils/nxos.py
index 2572a76267..654290155e 100644
--- a/salt/utils/nxos.py
+++ b/salt/utils/nxos.py
@@ -212,7 +212,8 @@ class NxapiClient:
body = response
if self.nxargs["connect_over_uds"]:
- body = json.loads(response.read().decode("utf-8"))
+ max_safe_read = 10 * 1024 * 1024
+ body = json.loads(response.read(max_safe_read).decode("utf-8"))
# Proceed with caution. The JSON may not be complete.
# Don't just return body['ins_api']['outputs']['output'] directly.
--
2.52.0

View File

@@ -40,7 +40,6 @@ saltbundlepy-requests.deb$
saltbundlepy-setuptools.deb$
saltbundlepy-six.deb$
saltbundlepy-urllib3.deb$
saltbundlepy-apt.deb$
saltbundlepy-docker.deb$
saltbundlepy-docker-pycreds.deb$

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,173 @@
From 7cbb68f36824161743f4cc60d8920e2cea039e5e Mon Sep 17 00:00:00 2001
From: Marek Czernek <marek.czernek@suse.com>
Date: Fri, 9 Jan 2026 16:49:19 +0100
Subject: [PATCH] Simplify utils.json.find_json function
The previous implementation computed all combinations of potential JSON
documents and tried to `json.loads()`them. That resumted in num({) *
num(}) tries, which could take hours on large inputs.
The approach implemented with this change simplifies the work we do: we
only look for opening '{' and '[' characters, and try to parse the rest
of input string with JSONDecoder.raw_decode. This method ignores
extraneous data at the end and is faster than doing it ourselves in
Python.
Co-authored-by: Alexander Graul <agraul@suse.com>
---
changelog/68258.fixed.md | 1 +
salt/utils/json.py | 80 ++++++---------------------
tests/pytests/unit/utils/test_json.py | 5 --
tests/unit/utils/test_json.py | 12 ++++
4 files changed, 31 insertions(+), 67 deletions(-)
create mode 100644 changelog/68258.fixed.md
diff --git a/changelog/68258.fixed.md b/changelog/68258.fixed.md
new file mode 100644
index 0000000000..a9afeccef7
--- /dev/null
+++ b/changelog/68258.fixed.md
@@ -0,0 +1 @@
+Simplied and sped up `utils.json.find_json` function
diff --git a/salt/utils/json.py b/salt/utils/json.py
index 26cb38cdbe..1605e75f9f 100644
--- a/salt/utils/json.py
+++ b/salt/utils/json.py
@@ -2,7 +2,7 @@
Functions to work with JSON
"""
-
+import contextlib
import json
import logging
@@ -25,69 +25,25 @@ def __split(raw):
return raw.splitlines()
-def find_json(raw):
- """
- Pass in a raw string and load the json when it starts. This allows for a
- string to start with garbage and end with json but be cleanly loaded
- """
- ret = {}
- lines = __split(raw)
- lengths = list(map(len, lines))
- starts = []
- ends = []
-
- # Search for possible starts end ends of the json fragments
- for ind, _ in enumerate(lines):
- line = lines[ind].lstrip()
- line = line[0] if line else line
- if line == "{" or line == "[":
- starts.append((ind, line))
- if line == "}" or line == "]":
- ends.append((ind, line))
-
- # List all the possible pairs of starts and ends,
- # and fill the length of each block to sort by size after
- starts_ends = []
- for start, start_br in starts:
- for end, end_br in reversed(ends):
- if end > start and (
- (start_br == "{" and end_br == "}")
- or (start_br == "[" and end_br == "]")
- ):
- starts_ends.append((start, end, sum(lengths[start : end + 1])))
-
- # Iterate through all the possible pairs starting from the largest
- starts_ends.sort(key=lambda x: (x[2], x[1] - x[0], x[0]), reverse=True)
- for start, end, _ in starts_ends:
- working = "\n".join(lines[start : end + 1])
- try:
- ret = json.loads(working)
- return ret
- except ValueError:
- pass
- # Try filtering non-JSON text right after the last closing curly brace
- end_str = lines[end].lstrip()[0]
- working = "\n".join(lines[start : end]) + end_str
- try:
- ret = json.loads(working)
- return ret
- except ValueError:
- continue
+def find_json(s: str):
+ """Pass in a string and load JSON within it.
- # Fall back to old implementation for backward compatibility
- # excpecting json after the text
- for ind, _ in enumerate(lines):
- working = "\n".join(lines[ind:])
- try:
- ret = json.loads(working)
- except ValueError:
- continue
- if ret:
- return ret
+ The string may contain non-JSON text before and after the JSON document.
- if not ret:
- # Not json, raise an error
- raise ValueError
+ Raises ValueError if no valid JSON was found.
+ """
+ decoder = json.JSONDecoder()
+
+ # We look for the beginning of JSON objects / arrays and let raw_decode() handle
+ # extraneous data at the end.
+ for idx, char in enumerate(s):
+ if char == "{" or char == "[":
+ # JSONDecodeErrors are expected on stray '{'/'[' in the non-JSON part
+ with contextlib.suppress(json.JSONDecodeError):
+ data, _ = decoder.raw_decode(s[idx:])
+ return data
+
+ raise ValueError
def import_json():
diff --git a/tests/pytests/unit/utils/test_json.py b/tests/pytests/unit/utils/test_json.py
index 72b1023003..f7aed28b42 100644
--- a/tests/pytests/unit/utils/test_json.py
+++ b/tests/pytests/unit/utils/test_json.py
@@ -107,11 +107,6 @@ def test_find_json():
ret = salt.utils.json.find_json(garbage_around_json)
assert ret == expected_ret
- # Now pre-pend small json and re-test
- small_json_pre_json = f"{test_small_json}{test_sample_json}"
- ret = salt.utils.json.find_json(small_json_pre_json)
- assert ret == expected_ret
-
# Now post-pend small json and re-test
small_json_post_json = f"{test_sample_json}{test_small_json}"
ret = salt.utils.json.find_json(small_json_post_json)
diff --git a/tests/unit/utils/test_json.py b/tests/unit/utils/test_json.py
index 5ea409a705..f5dcc1f72d 100644
--- a/tests/unit/utils/test_json.py
+++ b/tests/unit/utils/test_json.py
@@ -49,6 +49,18 @@ class JSONTestCase(TestCase):
)
)
+ def test_find_json_unbalanced_brace_in_string(self):
+ test_sample_json = '{"title": "I like curly braces like this one:{"}'
+ expected_ret = {"title": "I like curly braces like this one:{"}
+ ret = salt.utils.json.find_json(test_sample_json)
+ self.assertDictEqual(ret, expected_ret)
+
+ def test_find_json_unbalanced_square_bracket_in_string(self):
+ test_sample_json = '{"title": "I like square brackets like this one:["}'
+ expected_ret = {"title": "I like square brackets like this one:["}
+ ret = salt.utils.json.find_json(test_sample_json)
+ self.assertDictEqual(ret, expected_ret)
+
def test_find_json(self):
test_sample_json = """
{
--
2.52.0

View File

@@ -0,0 +1,91 @@
From c4542e59844bce3a65726564fa364170c1fe7b8c Mon Sep 17 00:00:00 2001
From: Victor Zhestkov <vzhestkov@suse.com>
Date: Wed, 14 Jan 2026 14:12:44 +0100
Subject: [PATCH] Speedup wheel key.finger call (bsc#1240532) (#713)
* Reduce the number of os.path.basename calls with key.finger
* Simplify and speedup salt.key.Key.name_match
* Avoid not needed printing while calling wheel from master
* Populate missing parts for clear_load
* Remove redundant events to be fired
---
salt/key.py | 20 ++++++++++----------
salt/master.py | 11 ++++++++---
2 files changed, 18 insertions(+), 13 deletions(-)
diff --git a/salt/key.py b/salt/key.py
index b15b80eca3..8cd248bb8c 100644
--- a/salt/key.py
+++ b/salt/key.py
@@ -491,16 +491,15 @@ class Key:
ret = {}
if "," in match and isinstance(match, str):
match = match.split(",")
+ if not isinstance(match, list):
+ match = [match]
for status, keys in matches.items():
+ if match == ["*"] and keys:
+ ret[status] = keys
+ continue
for key in salt.utils.data.sorted_ignorecase(keys):
- if isinstance(match, list):
- for match_item in match:
- if fnmatch.fnmatch(key, match_item):
- if status not in ret:
- ret[status] = []
- ret[status].append(key)
- else:
- if fnmatch.fnmatch(key, match):
+ for match_item in match:
+ if fnmatch.fnmatch(key, match_item):
if status not in ret:
ret[status] = []
ret[status].append(key)
@@ -543,12 +542,13 @@ class Key:
for dir_ in key_dirs:
if dir_ is None:
continue
- ret[os.path.basename(dir_)] = []
+ base_dir = os.path.basename(dir_)
+ ret[base_dir] = []
try:
for fn_ in salt.utils.data.sorted_ignorecase(os.listdir(dir_)):
if not fn_.startswith("."):
if os.path.isfile(os.path.join(dir_, fn_)):
- ret[os.path.basename(dir_)].append(
+ ret[base_dir].append(
salt.utils.stringutils.to_unicode(fn_)
)
except OSError:
diff --git a/salt/master.py b/salt/master.py
index 09ce7d36a7..b9f009a028 100644
--- a/salt/master.py
+++ b/salt/master.py
@@ -2093,12 +2093,17 @@ class ClearFuncs(TransportMethods):
"tag": tag,
"user": username,
}
-
- self.event.fire_event(data, tagify([jid, "new"], "wheel"))
+ clear_load.update(
+ {
+ "__jid__": jid,
+ "__tag__": tag,
+ "__user__": username,
+ "print_event": clear_load.get("print_event", False),
+ }
+ )
ret = self.wheel_.call_func(fun, full_return=True, **clear_load)
data["return"] = ret["return"]
data["success"] = ret["success"]
- self.event.fire_event(data, tagify([jid, "ret"], "wheel"))
return {"tag": tag, "data": data}
except Exception as exc: # pylint: disable=broad-except
log.error("Exception occurred while introspecting %s: %s", fun, exc)
--
2.52.0

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,33 @@
From 1df479ec297e340bbe5f4913afce02f6c8427bd4 Mon Sep 17 00:00:00 2001
From: Victor Zhestkov <vzhestkov@suse.com>
Date: Mon, 6 Oct 2025 16:41:46 +0200
Subject: [PATCH] Use versioned python interpreter for salt-ssh
---
salt/client/ssh/__init__.py | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/salt/client/ssh/__init__.py b/salt/client/ssh/__init__.py
index bfb7d3d1d1..86e4bcceb0 100644
--- a/salt/client/ssh/__init__.py
+++ b/salt/client/ssh/__init__.py
@@ -157,7 +157,7 @@ SSH_PY_CODE='import base64;
if [ -n "$DEBUG" ]
then set -x
fi
-PYTHON_CMDS="/var/tmp/venv-salt-minion/bin/python python3.11 python3 /usr/libexec/platform-python python27 python2.7 python26 python2.6 python2 python"
+PYTHON_CMDS="/var/tmp/venv-salt-minion/bin/python {{PY3XX_CMD}}python3 /usr/libexec/platform-python python27 python2.7 python26 python2.6 python2 python"
for py_cmd in $PYTHON_CMDS
do
if command -v "$py_cmd" >/dev/null 2>&1 && "$py_cmd" -c "import sys; sys.exit(not (sys.version_info >= (2, 6)));"
@@ -1533,6 +1533,7 @@ ARGS = {arguments}\n'''.format(
SSH_PY_CODE=py_code_enc,
HOST_PY_MAJOR=sys.version_info[0],
SET_PATH=self.set_path,
+ PY3XX_CMD=f"python3.{sys.version_info.minor} " if sys.version_info >= (3, 11) else "",
)
else:
cmd = saltwinshell.gen_shim(py_code_enc)
--
2.51.0

View File

@@ -1,3 +1,103 @@
-------------------------------------------------------------------
Wed Jan 14 14:25:41 UTC 2026 - Marek Czernek <marek.czernek@suse.com>
- Use internal deb classes instead of external aptsource lib
* Drop dependency on saltbundlepy-apt
- Speed up wheel key.finger call (bsc#1240532)
- Add security patches (bsc#1254903,bsc#1254905,bsc#1254904)
- Simplify and speed up utils.find_json function (bsc#1246130)
- Added:
* use-internal-salt.utils.pkg.deb-classes-instead-of-a.patch
* speedup-wheel-key.finger-call-bsc-1240532-713.patch
* fixes-for-security-issues-cve-2025-13836-cve-2025-67.patch
* simplify-utils.json.find_json-function.patch
- Modified:
* include-deb
-------------------------------------------------------------------
Thu Jan 8 08:39:12 UTC 2026 - Marek Czernek <marek.czernek@suse.com>
- Extend warn_until period to 2027
- Added:
* extend-fails-to-warnings-until-2027-742.patch
-------------------------------------------------------------------
Mon Nov 24 21:02:49 UTC 2025 - Alexander Graul <alexander.graul@suse.com>
- Add minimum_auth_version to enforce security (CVE-2025-62349)
- Backport security fixes for vendored tornado
* BDSA-2024-3438
* BDSA-2024-3439
* BDSA-2024-9026
- Junos module yaml loader fix (CVE-2025-62348)
- Added:
* backport-3006.17-security-fixes-739.patch
-------------------------------------------------------------------
Tue Nov 11 08:03:59 UTC 2025 - Marek Czernek <marek.czernek@suse.com>
- Fix TLS and x509 modules for OSes with older cryptography module
- Added:
* fix-tls-and-x509-modules-for-older-cryptography-modu.patch
-------------------------------------------------------------------
Fri Nov 7 16:37:10 UTC 2025 - Pablo Suárez Hernández <pablo.suarezhernandez@suse.com>
- Fix Salt for Python > 3.11 (bsc#1252285) (bsc#1252244)
* Use external tornado on Python > 3.11
* Make tls and x509 to use python-cryptography
* Remove usage of spwd
- Added:
* fix-salt-for-python-3.11.patch
-------------------------------------------------------------------
Wed Oct 29 10:38:04 UTC 2025 - Pablo Suárez Hernández <pablo.suarezhernandez@suse.com>
- Fix payload signature verification on Tumbleweed (bsc#1251776)
- Added:
* do-not-break-signature-verification-on-latest-m2cryp.patch
-------------------------------------------------------------------
Mon Oct 6 14:54:30 UTC 2025 - Victor Zhestkov <vzhestkov@suse.com>
- Use versioned python interpreter for salt-ssh
- Added:
* use-versioned-python-interpreter-for-salt-ssh.patch
-------------------------------------------------------------------
Mon Oct 6 08:40:19 UTC 2025 - Pablo Suárez Hernández <pablo.suarezhernandez@suse.com>
- Fix known_hosts error on gitfs (bsc#1250520) (bsc#1227207)
- Added:
* allow-libgit2-to-guess-sysdir-homedir-successfully-b.patch
-------------------------------------------------------------------
Wed Oct 1 12:46:17 UTC 2025 - Victor Zhestkov <vzhestkov@suse.com>
- Add python3.11 as preferable for salt-ssh to avoid tests fails
- Added:
* add-python3.11-as-preferable-for-salt-ssh-to-avoid-t.patch
-------------------------------------------------------------------
Wed Sep 17 08:16:34 UTC 2025 - Pablo Suárez Hernández <pablo.suarezhernandez@suse.com>
- Make test_pillar_timeout test more reliable
- Modify README and other doc files for openSUSE
- Added:
* even-more-reliable-pillar-timeout-test.patch
* modify-readme-for-opensuse-728.patch
-------------------------------------------------------------------
Mon Aug 11 14:02:35 UTC 2025 - Victor Zhestkov <vzhestkov@suse.com>

View File

@@ -539,6 +539,44 @@ Patch177: fix-the-tests-failing-on-almalinux-10-and-other-clon.patch
Patch178: fix-functional.states.test_user-for-sles-16-and-micr.patch
# PATCH-FIX_UPSTREAM: https://github.com/saltstack/salt/pull/68247
Patch179: improve-sl-micro-6.2-detection-with-grains.patch
# PATCH-FIX_OPENSUSE: https://github.com/openSUSE/salt/pull/728
Patch180: modify-readme-for-opensuse-728.patch
# PATCH-FIX_UPSTREAM: https://github.com/saltstack/salt/pull/68331
# PATCH-FIX_OPENSUSE: https://github.com/openSUSE/salt/pull/729
Patch181: even-more-reliable-pillar-timeout-test.patch
# PATCH-FIX_OPENSUSE: https://github.com/openSUSE/salt/pull/730
Patch182: add-python3.11-as-preferable-for-salt-ssh-to-avoid-t.patch
# PATCH-FIX_UPSTREAM: https://github.com/saltstack/salt/pull/68366
Patch183: allow-libgit2-to-guess-sysdir-homedir-successfully-b.patch
# PATCH-FIX_OPENSUSE: https://github.com/openSUSE/salt/pull/732
Patch184: use-versioned-python-interpreter-for-salt-ssh.patch
# PATCH-FIX_OPENSUSE: https://github.com/openSUSE/salt/pull/735
Patch185: do-not-break-signature-verification-on-latest-m2cryp.patch
# PATCH-FIX_OPENSUSE: https://github.com/openSUSE/salt/pull/736
Patch186: fix-salt-for-python-3.11.patch
# PATCH-FIX_OPENSUSE: https://github.com/openSUSE/salt/pull/737
Patch187: fix-tls-and-x509-modules-for-older-cryptography-modu.patch
# PATCH-FIX_UPSTREAM: https://github.com/saltstack/salt/issues/68377
# PATCH-FIX_UPSTREAM: https://github.com/saltstack/salt/issues/68379
# PATCH-FIX_UPSTREAM: https://github.com/saltstack/salt/issues/68383
# PATCH-FIX_UPSTREAM: https://github.com/saltstack/salt/issues/68467
# PATCH-FIX_UPSTREAM: https://github.com/saltstack/salt/issues/68469
# PATCH-FIX_OPENSUSE: https://github.com/openSUSE/salt/pull/739
Patch188: backport-3006.17-security-fixes-739.patch
# PATCH-FIX_OPENSUSE: https://github.com/openSUSE/salt/pull/742
Patch189: extend-fails-to-warnings-until-2027-742.patch
# PATCH-FIX_UPSTREAM: https://github.com/saltstack/salt/pull/68253
Patch190: simplify-utils.json.find_json-function.patch
# PATCH-FIX_UPSTREAM: https://github.com/saltstack/salt/pull/68595
# PATCH-FIX_UPSTREAM: https://github.com/saltstack/salt/pull/68611
# PATCH-FIX_UPSTREAM: https://github.com/tornadoweb/tornado/pull/3553
# PATCH-FIX_UPSTREAM: https://github.com/tornadoweb/tornado/commit/771472cfdaeebc0d89a9cc46e249f8891a6b29cd
Patch191: fixes-for-security-issues-cve-2025-13836-cve-2025-67.patch
# PATCH-FIX_UPSTREAM: https://github.com/saltstack/salt/pull/68251
Patch192: speedup-wheel-key.finger-call-bsc-1240532-713.patch
# PATCH-FIX_UPSTREAM: https://github.com/saltstack/salt/pull/67956
Patch193: use-internal-salt.utils.pkg.deb-classes-instead-of-a.patch
### IMPORTANT: The line below is used as a snippet marker. Do not touch it.
### SALT PATCHES LIST END
@@ -605,10 +643,6 @@ BuildRequires: python
Requires(post): policycoreutils
%endif
%if 0%{?debian} || 0%{?raspbian} || 0%{?ubuntu}
BuildRequires: saltbundlepy-apt
%endif
# --- [venvjail - BuildRequires] END ---
# --- [venvjail - Requires] START ---
# --- [venvjail - Requires] END ---