Accepting request 1143453 from home:PSuarezHernandez:branches:systemsmanagement:saltstack
- Prevent directory traversal when creating syndic cache directory on the master (CVE-2024-22231, bsc#1219430) - Prevent directory traversal attacks in the master's serve_file method (CVE-2024-22232, bsc#1219431) - Added: * fix-cve-2024-22231-and-cve-2024-22232-bsc-1219430-bs.patch OBS-URL: https://build.opensuse.org/request/show/1143453 OBS-URL: https://build.opensuse.org/package/show/systemsmanagement:saltstack/salt?expand=0&rev=229
This commit is contained in:
parent
c300ccc9de
commit
ae633bde18
@ -1 +1 @@
|
||||
d02a7d8eb7fdb302ed603f2c45525b41e812beb7
|
||||
d0c2f35ff4a0b21786b20c884cbb191ad2e63904
|
544
fix-cve-2024-22231-and-cve-2024-22232-bsc-1219430-bs.patch
Normal file
544
fix-cve-2024-22231-and-cve-2024-22232-bsc-1219430-bs.patch
Normal file
@ -0,0 +1,544 @@
|
||||
From 5710bc3ff3887762182f8326bd74f40d3872a69f Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Pablo=20Su=C3=A1rez=20Hern=C3=A1ndez?=
|
||||
<psuarezhernandez@suse.com>
|
||||
Date: Thu, 1 Feb 2024 11:50:16 +0000
|
||||
Subject: [PATCH] Fix "CVE-2024-22231" and "CVE-2024-22232"
|
||||
(bsc#1219430, bsc#1219431) (#621)
|
||||
|
||||
* Fix CVE-2024-22231 and CVE-2024-22232
|
||||
|
||||
* Add changelogs for CVE-2024-22231 and CVE-2024-22232
|
||||
|
||||
* Fix linter issue
|
||||
|
||||
* Add credit
|
||||
|
||||
* Fix wart in patch
|
||||
|
||||
* Clean up test fixtures
|
||||
|
||||
* Fix test on windows
|
||||
|
||||
* Update changelog file name
|
||||
|
||||
* Fix fileroots tests
|
||||
|
||||
---------
|
||||
|
||||
Co-authored-by: Daniel A. Wozniak <dwozniak@vmware.com>
|
||||
---
|
||||
changelog/565.security.md | 4 +
|
||||
salt/fileserver/__init__.py | 9 +-
|
||||
salt/fileserver/roots.py | 26 +++++
|
||||
salt/master.py | 15 ++-
|
||||
tests/pytests/unit/fileserver/test_roots.py | 58 +++++++--
|
||||
tests/pytests/unit/test_fileserver.py | 123 ++++++++++++++++++++
|
||||
tests/pytests/unit/test_master.py | 33 ++++++
|
||||
tests/unit/test_fileserver.py | 79 -------------
|
||||
8 files changed, 250 insertions(+), 97 deletions(-)
|
||||
create mode 100644 changelog/565.security.md
|
||||
create mode 100644 tests/pytests/unit/test_fileserver.py
|
||||
delete mode 100644 tests/unit/test_fileserver.py
|
||||
|
||||
diff --git a/changelog/565.security.md b/changelog/565.security.md
|
||||
new file mode 100644
|
||||
index 00000000000..5d7ec8202ba
|
||||
--- /dev/null
|
||||
+++ b/changelog/565.security.md
|
||||
@@ -0,0 +1,4 @@
|
||||
+CVE-2024-22231 Prevent directory traversal when creating syndic cache directory on the master
|
||||
+CVE-2024-22232 Prevent directory traversal attacks in the master's serve_file method.
|
||||
+These vulerablities were discovered and reported by:
|
||||
+Yudi Zhao(Huawei Nebula Security Lab),Chenwei Jiang(Huawei Nebula Security Lab)
|
||||
diff --git a/salt/fileserver/__init__.py b/salt/fileserver/__init__.py
|
||||
index 99f12387f91..4eca98d14a4 100644
|
||||
--- a/salt/fileserver/__init__.py
|
||||
+++ b/salt/fileserver/__init__.py
|
||||
@@ -568,11 +568,6 @@ class Fileserver:
|
||||
saltenv = salt.utils.stringutils.to_unicode(saltenv)
|
||||
back = self.backends(back)
|
||||
kwargs = {}
|
||||
- fnd = {"path": "", "rel": ""}
|
||||
- if os.path.isabs(path):
|
||||
- return fnd
|
||||
- if "../" in path:
|
||||
- return fnd
|
||||
if salt.utils.url.is_escaped(path):
|
||||
# don't attempt to find URL query arguments in the path
|
||||
path = salt.utils.url.unescape(path)
|
||||
@@ -588,6 +583,10 @@ class Fileserver:
|
||||
args = comp.split("=", 1)
|
||||
kwargs[args[0]] = args[1]
|
||||
|
||||
+ fnd = {"path": "", "rel": ""}
|
||||
+ if os.path.isabs(path) or "../" in path:
|
||||
+ return fnd
|
||||
+
|
||||
if "env" in kwargs:
|
||||
# "env" is not supported; Use "saltenv".
|
||||
kwargs.pop("env")
|
||||
diff --git a/salt/fileserver/roots.py b/salt/fileserver/roots.py
|
||||
index a02b597c6f8..e2ea92029c3 100644
|
||||
--- a/salt/fileserver/roots.py
|
||||
+++ b/salt/fileserver/roots.py
|
||||
@@ -27,6 +27,7 @@ import salt.utils.hashutils
|
||||
import salt.utils.path
|
||||
import salt.utils.platform
|
||||
import salt.utils.stringutils
|
||||
+import salt.utils.verify
|
||||
import salt.utils.versions
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
@@ -98,6 +99,11 @@ def find_file(path, saltenv="base", **kwargs):
|
||||
if saltenv == "__env__":
|
||||
root = root.replace("__env__", actual_saltenv)
|
||||
full = os.path.join(root, path)
|
||||
+
|
||||
+ # Refuse to serve file that is not under the root.
|
||||
+ if not salt.utils.verify.clean_path(root, full, subdir=True):
|
||||
+ continue
|
||||
+
|
||||
if os.path.isfile(full) and not salt.fileserver.is_file_ignored(__opts__, full):
|
||||
fnd["path"] = full
|
||||
fnd["rel"] = path
|
||||
@@ -128,6 +134,26 @@ def serve_file(load, fnd):
|
||||
ret["dest"] = fnd["rel"]
|
||||
gzip = load.get("gzip", None)
|
||||
fpath = os.path.normpath(fnd["path"])
|
||||
+
|
||||
+ actual_saltenv = saltenv = load["saltenv"]
|
||||
+ if saltenv not in __opts__["file_roots"]:
|
||||
+ if "__env__" in __opts__["file_roots"]:
|
||||
+ log.debug(
|
||||
+ "salt environment '%s' maps to __env__ file_roots directory", saltenv
|
||||
+ )
|
||||
+ saltenv = "__env__"
|
||||
+ else:
|
||||
+ return fnd
|
||||
+ file_in_root = False
|
||||
+ for root in __opts__["file_roots"][saltenv]:
|
||||
+ if saltenv == "__env__":
|
||||
+ root = root.replace("__env__", actual_saltenv)
|
||||
+ # Refuse to serve file that is not under the root.
|
||||
+ if salt.utils.verify.clean_path(root, fpath, subdir=True):
|
||||
+ file_in_root = True
|
||||
+ if not file_in_root:
|
||||
+ return ret
|
||||
+
|
||||
with salt.utils.files.fopen(fpath, "rb") as fp_:
|
||||
fp_.seek(load["loc"])
|
||||
data = fp_.read(__opts__["file_buffer_size"])
|
||||
diff --git a/salt/master.py b/salt/master.py
|
||||
index 3d2ba1e29de..425b4121481 100644
|
||||
--- a/salt/master.py
|
||||
+++ b/salt/master.py
|
||||
@@ -1038,7 +1038,10 @@ class MWorker(salt.utils.process.SignalHandlingProcess):
|
||||
"""
|
||||
key = payload["enc"]
|
||||
load = payload["load"]
|
||||
- ret = {"aes": self._handle_aes, "clear": self._handle_clear}[key](load)
|
||||
+ if key == "aes":
|
||||
+ ret = self._handle_aes(load)
|
||||
+ else:
|
||||
+ ret = self._handle_clear(load)
|
||||
raise salt.ext.tornado.gen.Return(ret)
|
||||
|
||||
def _post_stats(self, start, cmd):
|
||||
@@ -1213,7 +1216,7 @@ class AESFuncs(TransportMethods):
|
||||
"_dir_list",
|
||||
"_symlink_list",
|
||||
"_file_envs",
|
||||
- "_ext_nodes", # To keep compatibility with old Salt minion versions
|
||||
+ "_ext_nodes", # To keep compatibility with old Salt minion versions
|
||||
)
|
||||
|
||||
def __init__(self, opts, context=None):
|
||||
@@ -1746,10 +1749,16 @@ class AESFuncs(TransportMethods):
|
||||
self.mminion.returners[fstr](load["jid"], load["load"])
|
||||
|
||||
# Register the syndic
|
||||
+
|
||||
+ # We are creating a path using user suplied input. Use the
|
||||
+ # clean_path to prevent a directory traversal.
|
||||
+ root = os.path.join(self.opts["cachedir"], "syndics")
|
||||
syndic_cache_path = os.path.join(
|
||||
self.opts["cachedir"], "syndics", load["id"]
|
||||
)
|
||||
- if not os.path.exists(syndic_cache_path):
|
||||
+ if salt.utils.verify.clean_path(
|
||||
+ root, syndic_cache_path
|
||||
+ ) and not os.path.exists(syndic_cache_path):
|
||||
path_name = os.path.split(syndic_cache_path)[0]
|
||||
if not os.path.exists(path_name):
|
||||
os.makedirs(path_name)
|
||||
diff --git a/tests/pytests/unit/fileserver/test_roots.py b/tests/pytests/unit/fileserver/test_roots.py
|
||||
index 96bceb0fd3d..c1660280bc5 100644
|
||||
--- a/tests/pytests/unit/fileserver/test_roots.py
|
||||
+++ b/tests/pytests/unit/fileserver/test_roots.py
|
||||
@@ -5,6 +5,7 @@
|
||||
import copy
|
||||
import pathlib
|
||||
import shutil
|
||||
+import sys
|
||||
import textwrap
|
||||
|
||||
import pytest
|
||||
@@ -28,14 +29,14 @@ def unicode_dirname():
|
||||
return "соль"
|
||||
|
||||
|
||||
-@pytest.fixture(autouse=True)
|
||||
+@pytest.fixture
|
||||
def testfile(tmp_path):
|
||||
fp = tmp_path / "testfile"
|
||||
fp.write_text("This is a testfile")
|
||||
return fp
|
||||
|
||||
|
||||
-@pytest.fixture(autouse=True)
|
||||
+@pytest.fixture
|
||||
def tmp_state_tree(tmp_path, testfile, unicode_filename, unicode_dirname):
|
||||
dirname = tmp_path / "roots_tmp_state_tree"
|
||||
dirname.mkdir(parents=True, exist_ok=True)
|
||||
@@ -54,11 +55,15 @@ def tmp_state_tree(tmp_path, testfile, unicode_filename, unicode_dirname):
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
-def configure_loader_modules(tmp_state_tree, temp_salt_master):
|
||||
- opts = temp_salt_master.config.copy()
|
||||
+def testfilepath(tmp_state_tree, testfile):
|
||||
+ return tmp_state_tree / testfile.name
|
||||
+
|
||||
+
|
||||
+@pytest.fixture
|
||||
+def configure_loader_modules(tmp_state_tree, master_opts):
|
||||
overrides = {"file_roots": {"base": [str(tmp_state_tree)]}}
|
||||
- opts.update(overrides)
|
||||
- return {roots: {"__opts__": opts}}
|
||||
+ master_opts.update(overrides)
|
||||
+ return {roots: {"__opts__": master_opts}}
|
||||
|
||||
|
||||
def test_file_list(unicode_filename):
|
||||
@@ -75,17 +80,17 @@ def test_find_file(tmp_state_tree):
|
||||
assert full_path_to_file == ret["path"]
|
||||
|
||||
|
||||
-def test_serve_file(testfile):
|
||||
+def test_serve_file(testfilepath):
|
||||
with patch.dict(roots.__opts__, {"file_buffer_size": 262144}):
|
||||
load = {
|
||||
"saltenv": "base",
|
||||
- "path": str(testfile),
|
||||
+ "path": str(testfilepath),
|
||||
"loc": 0,
|
||||
}
|
||||
- fnd = {"path": str(testfile), "rel": "testfile"}
|
||||
+ fnd = {"path": str(testfilepath), "rel": "testfile"}
|
||||
ret = roots.serve_file(load, fnd)
|
||||
|
||||
- with salt.utils.files.fopen(str(testfile), "rb") as fp_:
|
||||
+ with salt.utils.files.fopen(str(testfilepath), "rb") as fp_:
|
||||
data = fp_.read()
|
||||
|
||||
assert ret == {"data": data, "dest": "testfile"}
|
||||
@@ -277,3 +282,36 @@ def test_update_mtime_map_unicode_error(tmp_path):
|
||||
},
|
||||
"backend": "roots",
|
||||
}
|
||||
+
|
||||
+
|
||||
+def test_find_file_not_in_root(tmp_state_tree):
|
||||
+ """
|
||||
+ Fileroots should never 'find' a file that is outside of it's root.
|
||||
+ """
|
||||
+ badfile = pathlib.Path(tmp_state_tree).parent / "bar"
|
||||
+ badfile.write_text("Bad file")
|
||||
+ badpath = f"../bar"
|
||||
+ ret = roots.find_file(badpath)
|
||||
+ assert ret == {"path": "", "rel": ""}
|
||||
+ badpath = f"{tmp_state_tree / '..' / 'bar'}"
|
||||
+ ret = roots.find_file(badpath)
|
||||
+ assert ret == {"path": "", "rel": ""}
|
||||
+
|
||||
+
|
||||
+def test_serve_file_not_in_root(tmp_state_tree):
|
||||
+ """
|
||||
+ Fileroots should never 'serve' a file that is outside of it's root.
|
||||
+ """
|
||||
+ badfile = pathlib.Path(tmp_state_tree).parent / "bar"
|
||||
+ badfile.write_text("Bad file")
|
||||
+ badpath = f"../bar"
|
||||
+ load = {"path": "salt://|..\\bar", "saltenv": "base", "loc": 0}
|
||||
+ fnd = {
|
||||
+ "path": f"{tmp_state_tree / '..' / 'bar'}",
|
||||
+ "rel": f"{pathlib.Path('..') / 'bar'}",
|
||||
+ }
|
||||
+ ret = roots.serve_file(load, fnd)
|
||||
+ if "win" in sys.platform:
|
||||
+ assert ret == {"data": "", "dest": "..\\bar"}
|
||||
+ else:
|
||||
+ assert ret == {"data": "", "dest": "../bar"}
|
||||
diff --git a/tests/pytests/unit/test_fileserver.py b/tests/pytests/unit/test_fileserver.py
|
||||
new file mode 100644
|
||||
index 00000000000..8dd3ea0a27d
|
||||
--- /dev/null
|
||||
+++ b/tests/pytests/unit/test_fileserver.py
|
||||
@@ -0,0 +1,123 @@
|
||||
+import datetime
|
||||
+import os
|
||||
+import time
|
||||
+
|
||||
+import salt.fileserver
|
||||
+import salt.utils.files
|
||||
+
|
||||
+
|
||||
+def test_diff_with_diffent_keys():
|
||||
+ """
|
||||
+ Test that different maps are indeed reported different
|
||||
+ """
|
||||
+ map1 = {"file1": 1234}
|
||||
+ map2 = {"file2": 1234}
|
||||
+ assert salt.fileserver.diff_mtime_map(map1, map2) is True
|
||||
+
|
||||
+
|
||||
+def test_diff_with_diffent_values():
|
||||
+ """
|
||||
+ Test that different maps are indeed reported different
|
||||
+ """
|
||||
+ map1 = {"file1": 12345}
|
||||
+ map2 = {"file1": 1234}
|
||||
+ assert salt.fileserver.diff_mtime_map(map1, map2) is True
|
||||
+
|
||||
+
|
||||
+def test_whitelist():
|
||||
+ opts = {
|
||||
+ "fileserver_backend": ["roots", "git", "s3fs", "hgfs", "svn"],
|
||||
+ "extension_modules": "",
|
||||
+ }
|
||||
+ fs = salt.fileserver.Fileserver(opts)
|
||||
+ assert sorted(fs.servers.whitelist) == sorted(
|
||||
+ ["git", "gitfs", "hg", "hgfs", "svn", "svnfs", "roots", "s3fs"]
|
||||
+ ), fs.servers.whitelist
|
||||
+
|
||||
+
|
||||
+def test_future_file_list_cache_file_ignored(tmp_path):
|
||||
+ opts = {
|
||||
+ "fileserver_backend": ["roots"],
|
||||
+ "cachedir": tmp_path,
|
||||
+ "extension_modules": "",
|
||||
+ }
|
||||
+
|
||||
+ back_cachedir = os.path.join(tmp_path, "file_lists/roots")
|
||||
+ os.makedirs(os.path.join(back_cachedir))
|
||||
+
|
||||
+ # Touch a couple files
|
||||
+ for filename in ("base.p", "foo.txt"):
|
||||
+ with salt.utils.files.fopen(os.path.join(back_cachedir, filename), "wb") as _f:
|
||||
+ if filename == "base.p":
|
||||
+ _f.write(b"\x80")
|
||||
+
|
||||
+ # Set modification time to file list cache file to 1 year in the future
|
||||
+ now = datetime.datetime.utcnow()
|
||||
+ future = now + datetime.timedelta(days=365)
|
||||
+ mod_time = time.mktime(future.timetuple())
|
||||
+ os.utime(os.path.join(back_cachedir, "base.p"), (mod_time, mod_time))
|
||||
+
|
||||
+ list_cache = os.path.join(back_cachedir, "base.p")
|
||||
+ w_lock = os.path.join(back_cachedir, ".base.w")
|
||||
+ ret = salt.fileserver.check_file_list_cache(opts, "files", list_cache, w_lock)
|
||||
+ assert (
|
||||
+ ret[1] is True
|
||||
+ ), "Cache file list cache file is not refreshed when future modification time"
|
||||
+
|
||||
+
|
||||
+def test_file_server_url_escape(tmp_path):
|
||||
+ (tmp_path / "srv").mkdir()
|
||||
+ (tmp_path / "srv" / "salt").mkdir()
|
||||
+ (tmp_path / "foo").mkdir()
|
||||
+ (tmp_path / "foo" / "bar").write_text("Bad file")
|
||||
+ fileroot = str(tmp_path / "srv" / "salt")
|
||||
+ badfile = str(tmp_path / "foo" / "bar")
|
||||
+ opts = {
|
||||
+ "fileserver_backend": ["roots"],
|
||||
+ "extension_modules": "",
|
||||
+ "optimization_order": [
|
||||
+ 0,
|
||||
+ ],
|
||||
+ "file_roots": {
|
||||
+ "base": [fileroot],
|
||||
+ },
|
||||
+ "file_ignore_regex": "",
|
||||
+ "file_ignore_glob": "",
|
||||
+ }
|
||||
+ fs = salt.fileserver.Fileserver(opts)
|
||||
+ ret = fs.find_file(
|
||||
+ "salt://|..\\..\\..\\foo/bar",
|
||||
+ "base",
|
||||
+ )
|
||||
+ assert ret == {"path": "", "rel": ""}
|
||||
+
|
||||
+
|
||||
+def test_file_server_serve_url_escape(tmp_path):
|
||||
+ (tmp_path / "srv").mkdir()
|
||||
+ (tmp_path / "srv" / "salt").mkdir()
|
||||
+ (tmp_path / "foo").mkdir()
|
||||
+ (tmp_path / "foo" / "bar").write_text("Bad file")
|
||||
+ fileroot = str(tmp_path / "srv" / "salt")
|
||||
+ badfile = str(tmp_path / "foo" / "bar")
|
||||
+ opts = {
|
||||
+ "fileserver_backend": ["roots"],
|
||||
+ "extension_modules": "",
|
||||
+ "optimization_order": [
|
||||
+ 0,
|
||||
+ ],
|
||||
+ "file_roots": {
|
||||
+ "base": [fileroot],
|
||||
+ },
|
||||
+ "file_ignore_regex": "",
|
||||
+ "file_ignore_glob": "",
|
||||
+ "file_buffer_size": 2048,
|
||||
+ }
|
||||
+ fs = salt.fileserver.Fileserver(opts)
|
||||
+ ret = fs.serve_file(
|
||||
+ {
|
||||
+ "path": "salt://|..\\..\\..\\foo/bar",
|
||||
+ "saltenv": "base",
|
||||
+ "loc": 0,
|
||||
+ }
|
||||
+ )
|
||||
+ assert ret == {"data": "", "dest": ""}
|
||||
diff --git a/tests/pytests/unit/test_master.py b/tests/pytests/unit/test_master.py
|
||||
index 98c796912aa..d338307d1f8 100644
|
||||
--- a/tests/pytests/unit/test_master.py
|
||||
+++ b/tests/pytests/unit/test_master.py
|
||||
@@ -1,3 +1,4 @@
|
||||
+import pathlib
|
||||
import time
|
||||
|
||||
import pytest
|
||||
@@ -249,3 +250,35 @@ def test_mworker_pass_context():
|
||||
loadler_pillars_mock.call_args_list[0][1].get("pack").get("__context__")
|
||||
== test_context
|
||||
)
|
||||
+
|
||||
+
|
||||
+def test_syndic_return_cache_dir_creation(encrypted_requests):
|
||||
+ """master's cachedir for a syndic will be created by AESFuncs._syndic_return method"""
|
||||
+ cachedir = pathlib.Path(encrypted_requests.opts["cachedir"])
|
||||
+ assert not (cachedir / "syndics").exists()
|
||||
+ encrypted_requests._syndic_return(
|
||||
+ {
|
||||
+ "id": "mamajama",
|
||||
+ "jid": "",
|
||||
+ "return": {},
|
||||
+ }
|
||||
+ )
|
||||
+ assert (cachedir / "syndics").exists()
|
||||
+ assert (cachedir / "syndics" / "mamajama").exists()
|
||||
+
|
||||
+
|
||||
+def test_syndic_return_cache_dir_creation_traversal(encrypted_requests):
|
||||
+ """
|
||||
+ master's AESFuncs._syndic_return method cachdir creation is not vulnerable to a directory traversal
|
||||
+ """
|
||||
+ cachedir = pathlib.Path(encrypted_requests.opts["cachedir"])
|
||||
+ assert not (cachedir / "syndics").exists()
|
||||
+ encrypted_requests._syndic_return(
|
||||
+ {
|
||||
+ "id": "../mamajama",
|
||||
+ "jid": "",
|
||||
+ "return": {},
|
||||
+ }
|
||||
+ )
|
||||
+ assert not (cachedir / "syndics").exists()
|
||||
+ assert not (cachedir / "mamajama").exists()
|
||||
diff --git a/tests/unit/test_fileserver.py b/tests/unit/test_fileserver.py
|
||||
deleted file mode 100644
|
||||
index c290b16b7e4..00000000000
|
||||
--- a/tests/unit/test_fileserver.py
|
||||
+++ /dev/null
|
||||
@@ -1,79 +0,0 @@
|
||||
-"""
|
||||
- :codeauthor: Joao Mesquita <jmesquita@sangoma.com>
|
||||
-"""
|
||||
-
|
||||
-
|
||||
-import datetime
|
||||
-import os
|
||||
-import time
|
||||
-
|
||||
-import salt.utils.files
|
||||
-from salt import fileserver
|
||||
-from tests.support.helpers import with_tempdir
|
||||
-from tests.support.mixins import LoaderModuleMockMixin
|
||||
-from tests.support.unit import TestCase
|
||||
-
|
||||
-
|
||||
-class MapDiffTestCase(TestCase):
|
||||
- def test_diff_with_diffent_keys(self):
|
||||
- """
|
||||
- Test that different maps are indeed reported different
|
||||
- """
|
||||
- map1 = {"file1": 1234}
|
||||
- map2 = {"file2": 1234}
|
||||
- assert fileserver.diff_mtime_map(map1, map2) is True
|
||||
-
|
||||
- def test_diff_with_diffent_values(self):
|
||||
- """
|
||||
- Test that different maps are indeed reported different
|
||||
- """
|
||||
- map1 = {"file1": 12345}
|
||||
- map2 = {"file1": 1234}
|
||||
- assert fileserver.diff_mtime_map(map1, map2) is True
|
||||
-
|
||||
-
|
||||
-class VCSBackendWhitelistCase(TestCase, LoaderModuleMockMixin):
|
||||
- def setup_loader_modules(self):
|
||||
- return {fileserver: {}}
|
||||
-
|
||||
- def test_whitelist(self):
|
||||
- opts = {
|
||||
- "fileserver_backend": ["roots", "git", "s3fs", "hgfs", "svn"],
|
||||
- "extension_modules": "",
|
||||
- }
|
||||
- fs = fileserver.Fileserver(opts)
|
||||
- assert sorted(fs.servers.whitelist) == sorted(
|
||||
- ["git", "gitfs", "hg", "hgfs", "svn", "svnfs", "roots", "s3fs"]
|
||||
- ), fs.servers.whitelist
|
||||
-
|
||||
- @with_tempdir()
|
||||
- def test_future_file_list_cache_file_ignored(self, cachedir):
|
||||
- opts = {
|
||||
- "fileserver_backend": ["roots"],
|
||||
- "cachedir": cachedir,
|
||||
- "extension_modules": "",
|
||||
- }
|
||||
-
|
||||
- back_cachedir = os.path.join(cachedir, "file_lists/roots")
|
||||
- os.makedirs(os.path.join(back_cachedir))
|
||||
-
|
||||
- # Touch a couple files
|
||||
- for filename in ("base.p", "foo.txt"):
|
||||
- with salt.utils.files.fopen(
|
||||
- os.path.join(back_cachedir, filename), "wb"
|
||||
- ) as _f:
|
||||
- if filename == "base.p":
|
||||
- _f.write(b"\x80")
|
||||
-
|
||||
- # Set modification time to file list cache file to 1 year in the future
|
||||
- now = datetime.datetime.utcnow()
|
||||
- future = now + datetime.timedelta(days=365)
|
||||
- mod_time = time.mktime(future.timetuple())
|
||||
- os.utime(os.path.join(back_cachedir, "base.p"), (mod_time, mod_time))
|
||||
-
|
||||
- list_cache = os.path.join(back_cachedir, "base.p")
|
||||
- w_lock = os.path.join(back_cachedir, ".base.w")
|
||||
- ret = fileserver.check_file_list_cache(opts, "files", list_cache, w_lock)
|
||||
- assert (
|
||||
- ret[1] is True
|
||||
- ), "Cache file list cache file is not refreshed when future modification time"
|
||||
--
|
||||
2.43.0
|
||||
|
||||
|
11
salt.changes
11
salt.changes
@ -1,8 +1,13 @@
|
||||
-------------------------------------------------------------------
|
||||
Tue Jan 30 09:40:18 UTC 2024 - Pablo Suárez Hernández <pablo.suarezhernandez@suse.com>
|
||||
Thu Feb 1 12:19:06 UTC 2024 - Pablo Suárez Hernández <pablo.suarezhernandez@suse.com>
|
||||
|
||||
- Remove python-boto dependency for the python3-salt-testsuite package for Tumbleweed
|
||||
- Rename salt-tests to python3-salt-testsuite
|
||||
- Prevent directory traversal when creating syndic cache directory
|
||||
on the master (CVE-2024-22231, bsc#1219430)
|
||||
- Prevent directory traversal attacks in the master's serve_file
|
||||
method (CVE-2024-22232, bsc#1219431)
|
||||
|
||||
- Added:
|
||||
* fix-cve-2024-22231-and-cve-2024-22232-bsc-1219430-bs.patch
|
||||
|
||||
-------------------------------------------------------------------
|
||||
Mon Jan 29 13:50:44 UTC 2024 - Pablo Suárez Hernández <pablo.suarezhernandez@suse.com>
|
||||
|
53
salt.spec
53
salt.spec
@ -335,12 +335,14 @@ Patch93: prefer-unittest.mock-for-python-versions-that-are-su.patch
|
||||
Patch94: fix-the-aptpkg.py-unit-test-failure.patch
|
||||
# PATCH-FIX_UPSTREAM https://github.com/saltstack/salt/pull/65092
|
||||
Patch95: update-__pillar__-during-pillar_refresh.patch
|
||||
# PATCH-FIX_UPSTREAM https://github.com/saltstack/salt/pull/65969
|
||||
Patch96: fix-cve-2024-22231-and-cve-2024-22232-bsc-1219430-bs.patch
|
||||
# PATCH-FIX_UPSTREAM https://github.com/saltstack/salt/pull/65009
|
||||
Patch96: fixed-keyerror-in-logs-when-running-a-state-that-fai.patch
|
||||
Patch97: fixed-keyerror-in-logs-when-running-a-state-that-fai.patch
|
||||
# PATCH-FIX_UPSTREAM https://github.com/saltstack/salt/pull/65562
|
||||
Patch97: improve-pip-target-override-condition-with-venv_pip_.patch
|
||||
Patch98: improve-pip-target-override-condition-with-venv_pip_.patch
|
||||
# PATCH-FIX_UPSTREAM https://github.com/saltstack/salt/pull/65819
|
||||
Patch98: allow-kwargs-for-fileserver-roots-update-bsc-1218482.patch
|
||||
Patch99: allow-kwargs-for-fileserver-roots-update-bsc-1218482.patch
|
||||
|
||||
|
||||
### IMPORTANT: The line below is used as a snippet marker. Do not touch it.
|
||||
@ -699,30 +701,12 @@ Requires(pre): %fillup_prereq
|
||||
Salt ssh is a master running without zmq.
|
||||
it enables the management of minions over a ssh connection.
|
||||
|
||||
%package -n python3-salt-testsuite
|
||||
%package tests
|
||||
Summary: Unit and integration tests for Salt
|
||||
Requires: %{name} = %{version}-%{release}
|
||||
Requires: python3-CherryPy
|
||||
Requires: python3-Genshi
|
||||
Requires: python3-Mako
|
||||
%if !0%{?suse_version} > 1600 || 0%{?centos}
|
||||
Requires: python3-boto
|
||||
%endif
|
||||
Requires: python3-boto3
|
||||
Requires: python3-docker
|
||||
Requires: python3-mock
|
||||
Requires: python3-pygit2
|
||||
Requires: python3-pytest >= 7.0.1
|
||||
Requires: python3-pytest-httpserver
|
||||
Requires: python3-pytest-salt-factories >= 1.0.0~rc21
|
||||
Requires: python3-pytest-subtests
|
||||
Requires: python3-testinfra
|
||||
Requires: python3-yamllint
|
||||
|
||||
Obsoletes: %{name}-tests
|
||||
|
||||
%description -n python3-salt-testsuite
|
||||
Collection of unit, functional, and integration tests for %{name}.
|
||||
%description tests
|
||||
Collections of unit and integration tests for Salt
|
||||
|
||||
%if %{with bash_completion}
|
||||
%package bash-completion
|
||||
@ -870,12 +854,10 @@ install -Dd -m 0755 %{buildroot}%{_sysconfdir}/logrotate.d/
|
||||
install -Dpm 0644 salt/cli/support/profiles/* %{buildroot}%{python3_sitelib}/salt/cli/support/profiles
|
||||
|
||||
# Install Salt tests
|
||||
install -Dd %{buildroot}%{python3_sitelib}/salt-testsuite
|
||||
cp -a tests %{buildroot}%{python3_sitelib}/salt-testsuite/
|
||||
# Remove runtests.py which is not used as deprecated method of running the tests
|
||||
rm %{buildroot}%{python3_sitelib}/salt-testsuite/tests/runtests.py
|
||||
# Copy conf files to the testsuite as they are used by the tests
|
||||
cp -a conf %{buildroot}%{python3_sitelib}/salt-testsuite/
|
||||
install -Dd -m 0750 %{buildroot}%{_datadir}/salt
|
||||
install -Dd -m 0750 %{buildroot}%{_datadir}/salt/tests
|
||||
cp -a tests/* %{buildroot}%{_datadir}/salt/tests/
|
||||
sed -i '1s=^#!/usr/bin/\(python\|env python\)[0-9.]*=#!/usr/bin/python3=' %{buildroot}%{_datadir}/salt/tests/runtests.py
|
||||
|
||||
## Install Zypper plugins only on SUSE machines
|
||||
%if 0%{?suse_version}
|
||||
@ -1452,10 +1434,7 @@ rm -f %{_localstatedir}/cache/salt/minion/thin/version
|
||||
|
||||
%files -n python3-salt
|
||||
%defattr(-,root,root,-)
|
||||
%dir %{python3_sitelib}/salt
|
||||
%dir %{python3_sitelib}/salt-*.egg-info
|
||||
%{python3_sitelib}/salt/*
|
||||
%{python3_sitelib}/salt-*.egg-info/*
|
||||
%{python3_sitelib}/*
|
||||
%exclude %{python3_sitelib}/salt/cloud/deploy/*.sh
|
||||
|
||||
%if %{with docs}
|
||||
@ -1464,8 +1443,10 @@ rm -f %{_localstatedir}/cache/salt/minion/thin/version
|
||||
%doc doc/_build/html
|
||||
%endif
|
||||
|
||||
%files -n python3-salt-testsuite
|
||||
%{python3_sitelib}/salt-testsuite
|
||||
%files tests
|
||||
%dir %{_datadir}/salt/
|
||||
%dir %{_datadir}/salt/tests/
|
||||
%{_datadir}/salt/tests/*
|
||||
|
||||
%if %{with bash_completion}
|
||||
%files bash-completion
|
||||
|
Loading…
Reference in New Issue
Block a user