diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 43fe083..28954b8 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,7 +1,7 @@ --- repos: - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v4.1.0 + rev: v4.2.0 hooks: - id: check-added-large-files - id: check-ast diff --git a/README.md b/README.md index bef5b6e..4c6de29 100644 --- a/README.md +++ b/README.md @@ -29,6 +29,8 @@ As user specifications are the most complicated, they are most likely the area t * Run As notations * Commands +One caveat to add is, this module currently does not do anything with `#include`, `#includedir`, `@include` and `@includedir` lines, but simply ignores them. You can, however, parse any included files individually if needed, but any interdependencies between the files will not be resolved. + ## Installing You can use pip to install pysudoers: diff --git a/pysudoers/__init__.py b/pysudoers/__init__.py index 32b4a8e..5a6a1d4 100644 --- a/pysudoers/__init__.py +++ b/pysudoers/__init__.py @@ -1,6 +1,5 @@ # -*- coding: utf-8 -*- """Manage a sudoers file.""" - import logging import re @@ -217,8 +216,13 @@ def parse_rule(self, line): :rtype: dict """ rule_re = re.compile(r"([\S\s]*)=([\S\s]*)") + include_re = re.compile(r"^(@|#)include(dir)?\s+") rule = {} + # Ignore includes for now + if include_re.search(line): + return [] + # Do a basic check for rule syntax match = rule_re.search(line) if not match: diff --git a/tests/test_sudoers.py b/tests/test_sudoers.py index c8a34cf..e0fd4e9 100644 --- a/tests/test_sudoers.py +++ b/tests/test_sudoers.py @@ -240,6 +240,38 @@ def test_escaped_split(self): sudoobj = Sudoers(path=self.fake_path) self.assertEqual(sudoobj.cmnd_aliases, result) + def test_hash_include(self): + """An include with a hash will not cause an exception.""" + # Find the path to the test sudoers file + data = "#include /test/dir/file\n" + mopen = self.get_mock_open(data) + with mock.patch(self.open_patch_id, mopen) as _: + _ = Sudoers(path=self.fake_path) + + def test_at_include(self): + """An include with an @ will not cause an exception.""" + # Find the path to the test sudoers file + data = "@include /test/dir/file\n" + mopen = self.get_mock_open(data) + with mock.patch(self.open_patch_id, mopen) as _: + _ = Sudoers(path=self.fake_path) + + def test_hash_includedir(self): + """An includedir with a hash will not cause an exception.""" + # Find the path to the test sudoers file + data = "#includedir /test/dir/file\n" + mopen = self.get_mock_open(data) + with mock.patch(self.open_patch_id, mopen) as _: + _ = Sudoers(path=self.fake_path) + + def test_at_includedir(self): + """An includedir with an @ will not cause an exception.""" + # Find the path to the test sudoers file + data = "@includedir /test/dir/file\n" + mopen = self.get_mock_open(data) + with mock.patch(self.open_patch_id, mopen) as _: + _ = Sudoers(path=self.fake_path) + class TestResolution(TestSudoers): """Test the alias resolution methods."""