Skip to content

Commit

Permalink
core: Look up live user from PKEXEC_UID
Browse files Browse the repository at this point in the history
anaconda can be run as gnome-initial-setup or liveuser on live
images, depending on how its started by the use.

It currently assumes it will be started as liveuser always.

This commit makes it look up the username and home directory by
querying PKEXEC_UID environment variable.

Resolves: rhbz#2235728
  • Loading branch information
halfline authored and jkonecny12 committed Sep 1, 2023
1 parent 7d57834 commit 5aec17d
Show file tree
Hide file tree
Showing 2 changed files with 84 additions and 21 deletions.
43 changes: 30 additions & 13 deletions pyanaconda/core/live_user.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,14 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#

import os
from collections import namedtuple
from pwd import getpwnam
from pwd import getpwuid

from pyanaconda.anaconda_loggers import get_module_logger
from pyanaconda.core.configuration.anaconda import conf

log = get_module_logger(__name__)

User = namedtuple("User", ["name", "uid", "env_add", "env_prune"])

Expand All @@ -37,18 +40,32 @@ def get_live_user():
if not conf.system.provides_liveuser:
return None

if "PKEXEC_UID" not in os.environ:
return None

pkexec_value = os.environ.get("PKEXEC_UID")

try:
username = "liveuser"
uid = getpwnam(username).pw_uid
env_prune = ("GDK_BACKEND",)
env_add = {
"XDG_RUNTIME_DIR": "/run/user/{}".format(uid),
"USER": username,
"HOME": "/home/{}".format(username),
}
return User(name=username,
uid=uid,
env_add=env_add,
env_prune=env_prune)
uid = int(pkexec_value)
except ValueError:
log.error("Wrong UID obtained from system '%s'", pkexec_value)
return None

try:
passwd_entry = getpwuid(uid)
except KeyError:
log.error("Can't obtain user information from pkexec UID: '%s'", pkexec_value)
return None

username = passwd_entry.pw_name
home_dir = passwd_entry.pw_dir
env_prune = ("GDK_BACKEND",)
env_add = {
"XDG_RUNTIME_DIR": "/run/user/{}".format(uid),
"USER": username,
"HOME": home_dir,
}
return User(name=username,
uid=uid,
env_add=env_add,
env_prune=env_prune)
62 changes: 54 additions & 8 deletions tests/unit_tests/pyanaconda_tests/core/test_live_user.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,16 +25,20 @@
class GetLiveUserTests(TestCase):

@patch("pyanaconda.core.live_user.conf")
@patch("pyanaconda.core.live_user.getpwnam")
def test_get_live_user(self, getpwnam_mock, conf_mock):
@patch("pyanaconda.core.live_user.getpwuid")
def test_get_live_user_not_on_live(self, getpwuid_mock, conf_mock):
# not live = early exit
conf_mock.system.provides_liveuser = False
assert get_live_user() is None
getpwnam_mock.assert_not_called()
getpwuid_mock.assert_not_called()

@patch("pyanaconda.core.live_user.conf")
@patch("pyanaconda.core.live_user.getpwuid")
@patch.dict("pyanaconda.core.live_user.os.environ", {"PKEXEC_UID": "1024"})
def test_get_live_user(self, getpwuid_mock, conf_mock):
# live and has user
conf_mock.system.provides_liveuser = True
getpwnam_mock.return_value = Mock(pw_uid=1024)
getpwuid_mock.return_value = Mock(pw_uid=1024, pw_dir='/home/liveuser', pw_name='liveuser')
assert get_live_user() == User(name="liveuser",
uid=1024,
env_prune=("GDK_BACKEND",),
Expand All @@ -43,10 +47,52 @@ def test_get_live_user(self, getpwnam_mock, conf_mock):
"USER": "liveuser",
"HOME": "/home/liveuser",
})
getpwnam_mock.assert_called_once_with("liveuser")
getpwnam_mock.reset_mock()
getpwuid_mock.assert_called_once_with(1024)
getpwuid_mock.reset_mock()

@patch("pyanaconda.core.live_user.conf")
@patch("pyanaconda.core.live_user.getpwuid")
@patch.dict("pyanaconda.core.live_user.os.environ", {"PKEXEC_UID": "1024"})
def test_get_live_user_with_failed_getpwuid(self, getpwuid_mock, conf_mock):
# supposedly live but missing user
conf_mock.system.provides_liveuser = True
getpwuid_mock.side_effect = KeyError
assert get_live_user() is None
getpwuid_mock.assert_called_once_with(1024)

@patch("pyanaconda.core.live_user.conf")
@patch("pyanaconda.core.live_user.getpwuid")
@patch.dict("pyanaconda.core.live_user.os.environ", dict())
def test_get_live_user_with_missing_pkexec_env(self, getpwuid_mock, conf_mock):
# supposedly live but missing user
conf_mock.system.provides_liveuser = True
assert get_live_user() is None
getpwuid_mock.assert_not_called()

@patch("pyanaconda.core.live_user.conf")
@patch.dict("pyanaconda.core.live_user.os.environ", {"PKEXEC_UID": ""})
def test_get_live_user_with_empty_pkexec_env(self, conf_mock):
# supposedly live but missing user
conf_mock.system.provides_liveuser = True
assert get_live_user() is None

@patch("pyanaconda.core.live_user.conf")
@patch.dict("pyanaconda.core.live_user.os.environ", {"PKEXEC_UID": "hello world"})
def test_get_live_user_with_text_pkexec_env(self, conf_mock):
# supposedly live but missing user
conf_mock.system.provides_liveuser = True
assert get_live_user() is None

@patch("pyanaconda.core.live_user.conf")
@patch.dict("pyanaconda.core.live_user.os.environ", {"PKEXEC_UID": "-1"})
def test_get_live_user_with_negative_pkexec_env(self, conf_mock):
# supposedly live but missing user
getpwnam_mock.side_effect = KeyError
conf_mock.system.provides_liveuser = True
assert get_live_user() is None

@patch("pyanaconda.core.live_user.conf")
@patch.dict("pyanaconda.core.live_user.os.environ", {"PKEXEC_UID": "999999999999999999999999"})
def test_get_live_user_with_high_pkexec_env(self, conf_mock):
# supposedly live but missing user
conf_mock.system.provides_liveuser = True
assert get_live_user() is None
getpwnam_mock.assert_called_once_with("liveuser")

0 comments on commit 5aec17d

Please sign in to comment.