From 218f5c3648a47cf1b0ca02232c0661219a4f4fb6 Mon Sep 17 00:00:00 2001 From: Alexander Sowitzki Date: Tue, 2 Feb 2021 16:36:02 +0100 Subject: [PATCH] user - Prevent user fact lookup failure if LOGNAME is set (#17029) (#73439) The `UserFactCollector` queries the user login name via `getpass.getuser()` and looks up the corresponding entry in the password database. The login name may differ from the actual user name, eg. if the `LOGNAME` env variable is set. The lookup fails in this case. Added a fallback in this case that tries to get the entry via the user ID. --- ...-fact-lookup-failure-is-logname-is-set.yml | 2 + lib/ansible/module_utils/facts/system/user.py | 5 ++- .../module_utils/facts/system/test_user.py | 40 +++++++++++++++++++ 3 files changed, 46 insertions(+), 1 deletion(-) create mode 100644 changelogs/fragments/17029-prevent-user-fact-lookup-failure-is-logname-is-set.yml create mode 100644 test/units/module_utils/facts/system/test_user.py diff --git a/changelogs/fragments/17029-prevent-user-fact-lookup-failure-is-logname-is-set.yml b/changelogs/fragments/17029-prevent-user-fact-lookup-failure-is-logname-is-set.yml new file mode 100644 index 00000000000..2424b3397e4 --- /dev/null +++ b/changelogs/fragments/17029-prevent-user-fact-lookup-failure-is-logname-is-set.yml @@ -0,0 +1,2 @@ +bugfixes: + - Lookup user by UID in password database if login name is not found (https://github.com/ansible/ansible/issues/17029) diff --git a/lib/ansible/module_utils/facts/system/user.py b/lib/ansible/module_utils/facts/system/user.py index 745b5db3f6f..35a07759950 100644 --- a/lib/ansible/module_utils/facts/system/user.py +++ b/lib/ansible/module_utils/facts/system/user.py @@ -35,7 +35,10 @@ class UserFactCollector(BaseFactCollector): user_facts['user_id'] = getpass.getuser() - pwent = pwd.getpwnam(getpass.getuser()) + try: + pwent = pwd.getpwnam(getpass.getuser()) + except KeyError: + pwent = pwd.getpwuid(os.getuid()) user_facts['user_uid'] = pwent.pw_uid user_facts['user_gid'] = pwent.pw_gid diff --git a/test/units/module_utils/facts/system/test_user.py b/test/units/module_utils/facts/system/test_user.py new file mode 100644 index 00000000000..5edfe146bc4 --- /dev/null +++ b/test/units/module_utils/facts/system/test_user.py @@ -0,0 +1,40 @@ +# unit tests for ansible system lsb fact collectors +# -*- coding: utf-8 -*- +# +# Ansible is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Ansible is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Ansible. If not, see . +# + +# Make coding more python3-ish +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type + +from ansible.module_utils.facts.system.user import UserFactCollector + +import os + + +def test_logname(): + """ Test if ``UserFactCollector`` still works with LOGNAME set """ + collector = UserFactCollector() + + unmodified_facts = collector.collect() + # Change logname env var and check if the collector still finds + # the pw entry. + os.environ["LOGNAME"] = "NONEXISTINGUSERDONTEXISTPLEASE" + modified_facts = collector.collect() + + # Set logname should be different to the real name. + assert unmodified_facts['user_id'] != modified_facts['user_id'] + # Actual UID is the same. + assert unmodified_facts['user_uid'] == modified_facts['user_uid']