From bdab6e6ba082dc8ab6669dbd039ae7d91b4f67d4 Mon Sep 17 00:00:00 2001 From: shadow38 <18661172+shadow38@users.noreply.github.com> Date: Fri, 3 Apr 2026 14:32:45 +0200 Subject: [PATCH 1/3] Fixes support for syslog log when salt is running as non-root user --- salt/utils/parsers.py | 3 +- salt/utils/validate/path.py | 60 +++++++++++++++++++++++++++++++++++++ 2 files changed, 62 insertions(+), 1 deletion(-) diff --git a/salt/utils/parsers.py b/salt/utils/parsers.py index c39e1daec87f..ba060ff2f251 100644 --- a/salt/utils/parsers.py +++ b/salt/utils/parsers.py @@ -40,6 +40,7 @@ import salt.utils.yaml import salt.version as version from salt.defaults import DEFAULT_TARGET_DELIM +from salt.utils.validate.path import is_syslog_path from salt.utils.validate.path import is_writeable from salt.utils.verify import insecure_log, verify_log, verify_log_files @@ -833,7 +834,7 @@ def __setup_logfile_logger_config(self): ), ) - if not is_writeable(logfile, check_parent=True): + if not is_syslog_path(logfile) and not is_writeable(logfile, check_parent=True): # Since we're not be able to write to the log file or its parent # directory (if the log file does not exit), are we the same user # as the one defined in the configuration file? diff --git a/salt/utils/validate/path.py b/salt/utils/validate/path.py index e6f97cfc42f2..7b63dd769b36 100644 --- a/salt/utils/validate/path.py +++ b/salt/utils/validate/path.py @@ -8,7 +8,67 @@ Several path related validators """ +import logging.handlers import os +import pathlib +import stat +from urllib.parse import urlparse + + +def is_syslog_path(path): + """ + Check if a given path is a syslog path. + + ://:/ + + log-facility is optional; must be a valid syslog facility in upper case (e.g. "LOG_USER", "LOG_DAEMON", etc.) + see https://docs.python.org/3/library/logging.handlers.html#logging.handlers.SysLogHandler + + :param path: The path to check + :returns: True or False + """ + + parsed_log_path = urlparse(path) + + if parsed_log_path.scheme in ("tcp", "udp", "file"): + if parsed_log_path.scheme == "file" and parsed_log_path.path: + path = pathlib.Path(parsed_log_path.path) + facility_name = path.name.upper() + if facility_name.startswith("LOG_"): + facility = getattr(logging.handlers.SysLogHandler, facility_name, None) + if facility is None: + return False + file_path = str(path.resolve().parent) + else: + file_path = str(path.resolve()) + + # Check if file_path is a Unix socket + if os.path.exists(file_path): + mode = os.stat(file_path).st_mode + if stat.S_ISSOCK(mode): + return os.access(file_path, os.W_OK) + else: + return False + else: + return False + + elif parsed_log_path.path: + # In case of udp or tcp with a facility specified + path = pathlib.Path(parsed_log_path.path) + facility_name = path.stem.upper() + if not facility_name.startswith("LOG_"): + return False + + facility = getattr(logging.handlers.SysLogHandler, facility_name, None) + if facility is None: + return False + else: + return True + + else: + # This is the case of udp or tcp without a facility specified + return True + return False def is_writeable(path, check_parent=False): From d5db585eec8a81448c1a04355b237e642a20a286 Mon Sep 17 00:00:00 2001 From: shadow38 <18661172+shadow38@users.noreply.github.com> Date: Fri, 3 Apr 2026 14:32:53 +0200 Subject: [PATCH 2/3] Fix linting error on import --- salt/utils/parsers.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/salt/utils/parsers.py b/salt/utils/parsers.py index ba060ff2f251..e5a39791a22c 100644 --- a/salt/utils/parsers.py +++ b/salt/utils/parsers.py @@ -40,8 +40,7 @@ import salt.utils.yaml import salt.version as version from salt.defaults import DEFAULT_TARGET_DELIM -from salt.utils.validate.path import is_syslog_path -from salt.utils.validate.path import is_writeable +from salt.utils.validate.path import is_syslog_path, is_writeable from salt.utils.verify import insecure_log, verify_log, verify_log_files log = logging.getLogger(__name__) From 352f6ba076b554f086a8d1b4747685e27e9e69b8 Mon Sep 17 00:00:00 2001 From: shadow38 <18661172+shadow38@users.noreply.github.com> Date: Tue, 14 Apr 2026 15:31:49 +0200 Subject: [PATCH 3/3] Added some tests for syslog path checking --- tests/unit/utils/validate/test_path.py | 39 ++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 tests/unit/utils/validate/test_path.py diff --git a/tests/unit/utils/validate/test_path.py b/tests/unit/utils/validate/test_path.py new file mode 100644 index 000000000000..17d4793e5938 --- /dev/null +++ b/tests/unit/utils/validate/test_path.py @@ -0,0 +1,39 @@ +from salt.utils.validate import path +from tests.support.unit import TestCase + + +class ValidatePathTestCase(TestCase): + """ + TestCase for salt.utils.validate.path module + """ + + def test_is_syslog_path(self): + + """ + Test syslog path + """ + + valid_paths = [ + "file:///dev/log", + "file:///dev/log/LOG_USER", + "udp://loghost:10514", + "udp://loghost:10514/LOG_USER", + "udp://loghost/LOG_USER", + "tcp://loghost:10514", + "tcp://loghost:10514/LOG_USER", + "tcp://loghost/USER" + ] + + invalid_paths = [ + "/dev/log", + "file:///dev/log/USER", + "udp://loghost/USER", + "tcp://loghost/USER", + "unix:///dev/log" + ] + + for addr in valid_paths: + self.assertTrue(path.is_syslog_path(addr)) + + for addr in invalid_paths: + self.assertFalse(path.is_syslog_path(addr))