From 4906c52b629bfce275558d4701c083f4c020ef32 Mon Sep 17 00:00:00 2001 From: Rob Crittenden Date: Fri, 30 Jun 2023 14:35:40 -0400 Subject: [PATCH] Catch exceptions during user/group name lookup in FileCheck It's possible that one or more of the allowed users/groups in a file check do not exist on the system. Catch this exception and try to proceed as best as possible. https://github.com/freeipa/freeipa-healthcheck/issues/296 Signed-off-by: Rob Crittenden --- src/ipahealthcheck/core/files.py | 33 +++++++++++++++++++++++---- tests/test_core_files.py | 38 ++++++++++++++++++++++++++++++++ 2 files changed, 67 insertions(+), 4 deletions(-) diff --git a/src/ipahealthcheck/core/files.py b/src/ipahealthcheck/core/files.py index 59e8b76..85d42bc 100644 --- a/src/ipahealthcheck/core/files.py +++ b/src/ipahealthcheck/core/files.py @@ -3,12 +3,15 @@ # import grp +import logging import os import pwd from ipahealthcheck.core import constants from ipahealthcheck.core.plugin import Result, duration +logger = logging.getLogger() + class FileCheck: """Generic check to validate permission and ownership of files @@ -77,14 +80,25 @@ class FileCheck: found = False for o in owner: - fowner = pwd.getpwnam(o) + try: + fowner = pwd.getpwnam(o) + except Exception as e: + logging.debug('user lookup "%s" for "%s" failed: %s', + o, path, e) + continue if fowner.pw_uid == stat.st_uid: found = True break if not found: - actual = pwd.getpwuid(stat.st_uid) key = '%s_owner' % path.replace('/', '_') + try: + actual = pwd.getpwuid(stat.st_uid) + except Exception: + yield Result(self, constants.WARNING, key=key, + path=path, type='owner', expected=owner, + got='Unknown uid %s' % stat.st_uid) + continue if len(owner) == 1: msg = 'Ownership of %s is %s and should ' \ 'be %s' % \ @@ -104,14 +118,25 @@ class FileCheck: found = False for g in group: - fgroup = grp.getgrnam(g) + try: + fgroup = grp.getgrnam(g) + except Exception as e: + logging.debug('group lookup "%s" for "%s" failed: %s', + g, path, e) + continue if fgroup.gr_gid == stat.st_gid: found = True break if not found: key = '%s_group' % path.replace('/', '_') - actual = grp.getgrgid(stat.st_gid) + try: + actual = grp.getgrgid(stat.st_gid) + except Exception: + yield Result(self, constants.WARNING, key=key, + path=path, type='group', expected=group, + got='Unknown gid %s' % stat.st_gid) + continue if len(group) == 1: msg = 'Group of %s is %s and should ' \ 'be %s' % \ diff --git a/tests/test_core_files.py b/tests/test_core_files.py index 6e3ec38..924d7fa 100644 --- a/tests/test_core_files.py +++ b/tests/test_core_files.py @@ -197,3 +197,41 @@ def test_files_not_found(mock_exists): for result in my_results.results: assert result.result == constants.SUCCESS assert result.kw.get('msg') == 'File does not exist' + + +@patch('os.stat') +@patch('pwd.getpwnam') +@patch('pwd.getpwuid') +def test_files_owner_not_found(mock_pwuid, mock_pwnam, mock_stat): + mock_pwuid.side_effect = KeyError('getpwnam(): name not found') + mock_pwnam.side_effect = KeyError('getpwuid(): uid not found') + mock_stat.return_value = make_stat() + + f = FileCheck() + f.files = files + + results = capture_results(f) + + my_results = get_results(results, 'owner') + for result in my_results.results: + assert result.result == constants.WARNING + assert result.kw.get('got') == 'Unknown uid 0' + + +@patch('os.stat') +@patch('grp.getgrnam') +@patch('grp.getgrgid') +def test_files_group_not_found(mock_grgid, mock_grnam, mock_stat): + mock_grgid.side_effect = KeyError('getgrnam(): name not found') + mock_grnam.side_effect = KeyError('getgruid(): gid not found') + mock_stat.return_value = make_stat() + + f = FileCheck() + f.files = files + + results = capture_results(f) + + my_results = get_results(results, 'group') + for result in my_results.results: + assert result.result == constants.WARNING + assert result.kw.get('got') == 'Unknown gid 0' -- 2.41.0