183 lines
7.1 KiB
Diff
183 lines
7.1 KiB
Diff
From 6ada6553eadc08fbbaf69d54129e6d3cc0c214e3 Mon Sep 17 00:00:00 2001
|
|
From: PeterMocary <petermocary@gmail.com>
|
|
Date: Fri, 26 Aug 2022 15:44:50 +0200
|
|
Subject: [PATCH 57/63] Ignore external accounts in /etc/passwd
|
|
|
|
The /etc/passwd can contain special entries to selectively incorporate entries
|
|
from another service source such as NIS or LDAP. These entries don't need to
|
|
contain all the fields that are normally present in the /etc/passwd entry and
|
|
would cause the upgrade failure in facts phase.
|
|
---
|
|
.../systemfacts/libraries/systemfacts.py | 48 ++++++++---
|
|
.../systemfacts/tests/test_systemfacts.py | 85 ++++++++++++++++++-
|
|
2 files changed, 121 insertions(+), 12 deletions(-)
|
|
|
|
diff --git a/repos/system_upgrade/common/actors/systemfacts/libraries/systemfacts.py b/repos/system_upgrade/common/actors/systemfacts/libraries/systemfacts.py
|
|
index e34cb86b..d1eeb28c 100644
|
|
--- a/repos/system_upgrade/common/actors/systemfacts/libraries/systemfacts.py
|
|
+++ b/repos/system_upgrade/common/actors/systemfacts/libraries/systemfacts.py
|
|
@@ -60,13 +60,26 @@ def anyhasprefix(value, prefixes):
|
|
|
|
@aslist
|
|
def _get_system_users():
|
|
+ skipped_user_names = []
|
|
for p in pwd.getpwall():
|
|
- yield User(
|
|
- name=p.pw_name,
|
|
- uid=p.pw_uid,
|
|
- gid=p.pw_gid,
|
|
- home=p.pw_dir
|
|
- )
|
|
+ # The /etc/passwd can contain special entries from another service source such as NIS or LDAP. These entries
|
|
+ # start with + or - sign and might not contain all the mandatory fields, thus are skipped along with other
|
|
+ # invalid entries for now. The UID and GID fields are always defined by pwd to 0 even when not specifiead in
|
|
+ # /etc/passwd.
|
|
+ if p.pw_name != '' and not p.pw_name.startswith(('+', '-')) and p.pw_dir:
|
|
+ yield User(
|
|
+ name=p.pw_name,
|
|
+ uid=p.pw_uid,
|
|
+ gid=p.pw_gid,
|
|
+ home=p.pw_dir
|
|
+ )
|
|
+ else:
|
|
+ skipped_user_names.append(p.pw_name)
|
|
+
|
|
+ if skipped_user_names:
|
|
+ api.current_logger().debug("These users from /etc/passwd that are special entries for service "
|
|
+ "like NIS, or don't contain all mandatory fields won't be included "
|
|
+ "in UsersFacts: {}".format(skipped_user_names))
|
|
|
|
|
|
def get_system_users_status():
|
|
@@ -76,12 +89,25 @@ def get_system_users_status():
|
|
|
|
@aslist
|
|
def _get_system_groups():
|
|
+ skipped_group_names = []
|
|
for g in grp.getgrall():
|
|
- yield Group(
|
|
- name=g.gr_name,
|
|
- gid=g.gr_gid,
|
|
- members=g.gr_mem
|
|
- )
|
|
+ # The /etc/group can contain special entries from another service source such as NIS or LDAP. These entries
|
|
+ # start with + or - sign and might not contain all the mandatory fields, thus are skipped along with other
|
|
+ # invalid entries for now. The GID field is always defined by pwd to 0 even when not specifiead in
|
|
+ # /etc/group.
|
|
+ if g.gr_name != '' and not g.gr_name.startswith(('+', '-')):
|
|
+ yield Group(
|
|
+ name=g.gr_name,
|
|
+ gid=g.gr_gid,
|
|
+ members=g.gr_mem
|
|
+ )
|
|
+ else:
|
|
+ skipped_group_names.append(g.gr_name)
|
|
+
|
|
+ if skipped_group_names:
|
|
+ api.current_logger().debug("These groups from /etc/group that are special entries for service "
|
|
+ "like NIS, or don't contain all mandatory fields won't be included "
|
|
+ "in GroupsFacts: {}".format(skipped_group_names))
|
|
|
|
|
|
def get_system_groups_status():
|
|
diff --git a/repos/system_upgrade/common/actors/systemfacts/tests/test_systemfacts.py b/repos/system_upgrade/common/actors/systemfacts/tests/test_systemfacts.py
|
|
index f94003d5..badf174c 100644
|
|
--- a/repos/system_upgrade/common/actors/systemfacts/tests/test_systemfacts.py
|
|
+++ b/repos/system_upgrade/common/actors/systemfacts/tests/test_systemfacts.py
|
|
@@ -1,4 +1,11 @@
|
|
-from leapp.libraries.actor.systemfacts import anyendswith, anyhasprefix, aslist
|
|
+import grp
|
|
+import pwd
|
|
+
|
|
+import pytest
|
|
+
|
|
+from leapp.libraries.actor.systemfacts import _get_system_groups, _get_system_users, anyendswith, anyhasprefix, aslist
|
|
+from leapp.libraries.common.testutils import logger_mocked
|
|
+from leapp.libraries.stdlib import api
|
|
from leapp.snactor.fixture import current_actor_libraries
|
|
|
|
|
|
@@ -33,3 +40,79 @@ def test_aslist(current_actor_libraries):
|
|
r = local()
|
|
|
|
assert isinstance(r, list) and r[0] and r[2] and not r[1]
|
|
+
|
|
+
|
|
+@pytest.mark.parametrize(
|
|
+ ('etc_passwd_names', 'etc_passwd_directory', 'skipped_user_names'),
|
|
+ [
|
|
+ (['root', 'unbound', 'dbus'], '/', []),
|
|
+ (['root', '+@scanners', 'dbus', '-@usrc', ''], '/', ['+@scanners', '-@usrc', '']),
|
|
+ (['root', '+@scanners', 'dbus'], '', ['root', '+@scanners', 'dbus']),
|
|
+ ]
|
|
+)
|
|
+def test_get_system_users(monkeypatch, etc_passwd_names, etc_passwd_directory, skipped_user_names):
|
|
+
|
|
+ class MockedPwdEntry(object):
|
|
+ def __init__(self, pw_name, pw_uid, pw_gid, pw_dir):
|
|
+ self.pw_name = pw_name
|
|
+ self.pw_uid = pw_uid
|
|
+ self.pw_gid = pw_gid
|
|
+ self.pw_dir = pw_dir
|
|
+
|
|
+ etc_passwd_contents = []
|
|
+ for etc_passwd_name in etc_passwd_names:
|
|
+ etc_passwd_contents.append(MockedPwdEntry(etc_passwd_name, 0, 0, etc_passwd_directory))
|
|
+
|
|
+ monkeypatch.setattr(pwd, 'getpwall', lambda: etc_passwd_contents)
|
|
+ monkeypatch.setattr(api, 'current_logger', logger_mocked())
|
|
+
|
|
+ _get_system_users()
|
|
+
|
|
+ if skipped_user_names:
|
|
+ assert len(api.current_logger().dbgmsg) == 1
|
|
+
|
|
+ for skipped_user_name in skipped_user_names:
|
|
+ assert skipped_user_name in api.current_logger().dbgmsg[0]
|
|
+
|
|
+ for user_name in etc_passwd_names:
|
|
+ if user_name not in skipped_user_names:
|
|
+ assert user_name not in api.current_logger().dbgmsg[0]
|
|
+ else:
|
|
+ assert not api.current_logger().dbgmsg
|
|
+
|
|
+
|
|
+@pytest.mark.parametrize(
|
|
+ ('etc_group_names', 'skipped_group_names'),
|
|
+ [
|
|
+ (['cdrom', 'floppy', 'tape'], []),
|
|
+ (['cdrom', '+@scanners', 'floppy', '-@usrc', ''], ['+@scanners', '-@usrc', '']),
|
|
+ ]
|
|
+)
|
|
+def test_get_system_groups(monkeypatch, etc_group_names, skipped_group_names):
|
|
+
|
|
+ class MockedGrpEntry(object):
|
|
+ def __init__(self, gr_name, gr_gid, gr_mem):
|
|
+ self.gr_name = gr_name
|
|
+ self.gr_gid = gr_gid
|
|
+ self.gr_mem = gr_mem
|
|
+
|
|
+ etc_group_contents = []
|
|
+ for etc_group_name in etc_group_names:
|
|
+ etc_group_contents.append(MockedGrpEntry(etc_group_name, 0, []))
|
|
+
|
|
+ monkeypatch.setattr(grp, 'getgrall', lambda: etc_group_contents)
|
|
+ monkeypatch.setattr(api, 'current_logger', logger_mocked())
|
|
+
|
|
+ _get_system_groups()
|
|
+
|
|
+ if skipped_group_names:
|
|
+ assert len(api.current_logger().dbgmsg) == 1
|
|
+
|
|
+ for skipped_group_name in skipped_group_names:
|
|
+ assert skipped_group_name in api.current_logger().dbgmsg[0]
|
|
+
|
|
+ for group_name in etc_group_names:
|
|
+ if group_name not in skipped_group_names:
|
|
+ assert group_name not in api.current_logger().dbgmsg[0]
|
|
+ else:
|
|
+ assert not api.current_logger().dbgmsg
|
|
--
|
|
2.39.0
|
|
|