diff --git a/checkbox-ng/plainbox/impl/secure/test_sudo_broker.py b/checkbox-ng/plainbox/impl/secure/test_sudo_broker.py new file mode 100644 index 000000000..2123faa3f --- /dev/null +++ b/checkbox-ng/plainbox/impl/secure/test_sudo_broker.py @@ -0,0 +1,48 @@ +# This file is part of Checkbox. +# +# Copyright 2023 Canonical Ltd. +# +# Checkbox is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 3, +# as published by the Free Software Foundation. +# +# Checkbox 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 Checkbox. If not, see . + +from subprocess import CalledProcessError +from unittest import TestCase, mock + +from plainbox.impl.secure.sudo_broker import is_passwordless_sudo + + +class IsPasswordlessSudoTests(TestCase): + @mock.patch("os.geteuid", return_value=0) + @mock.patch("plainbox.impl.secure.sudo_broker.check_call") + def test_root_happy(self, mock_check_call, mock_getuid): + mock_check_call.return_value = 0 + self.assertTrue(is_passwordless_sudo()) + + @mock.patch("os.geteuid", return_value=0) + @mock.patch("plainbox.impl.secure.sudo_broker.check_call") + def test_root_raising(self, mock_check_call, mock_getuid): + mock_check_call.side_effect = OSError + + with self.assertRaises(SystemExit): + is_passwordless_sudo() + + @mock.patch("os.geteuid", return_value=1000) + @mock.patch("plainbox.impl.secure.sudo_broker.check_call") + def test_non_root_happy(self, mock_check_call, mock_getuid): + mock_check_call.return_value = 0 + self.assertTrue(is_passwordless_sudo()) + + @mock.patch("os.geteuid", return_value=1000) + @mock.patch("plainbox.impl.secure.sudo_broker.check_call") + def test_non_root_raising(self, mock_check_call, mock_getuid): + mock_check_call.side_effect = CalledProcessError(1, "oops") + self.assertFalse(is_passwordless_sudo()) diff --git a/checkbox-ng/plainbox/impl/session/test_remote_assistant.py b/checkbox-ng/plainbox/impl/session/test_remote_assistant.py index 15c01c1d1..62a7b5eef 100644 --- a/checkbox-ng/plainbox/impl/session/test_remote_assistant.py +++ b/checkbox-ng/plainbox/impl/session/test_remote_assistant.py @@ -59,17 +59,19 @@ def not_allowed(self, *args): not_allowed(self_mock) @mock.patch.object(SessionAssistant, "__init__") - @mock.patch("plainbox.impl.secure.sudo_broker.is_passwordless_sudo") + @mock.patch("plainbox.impl.session.remote_assistant.is_passwordless_sudo") def test__reset_sa(self, is_passwordless_sudo_mock, init_mock): init_mock.return_value = None # RSA constructor calls _reset_sa, which in turns creates a new SA rsa = remote_assistant.RemoteSessionAssistant(lambda: None) self.assertEqual(init_mock.call_count, 1) + @mock.patch("plainbox.impl.session.remote_assistant.guess_normal_user") @mock.patch("fnmatch.filter") - def test_start_session_with_launcher(self, mock_filter): + def test_start_session_with_launcher(self, mock_filter, mock_gnu): # the real tp is referenced later on by it's second field mock_filter.return_value = [("tp", "tp")] + mock_gnu.return_value = "user" extra_cfg = dict() extra_cfg["launcher"] = "test_launcher" rsa = mock.Mock() @@ -82,10 +84,12 @@ def test_start_session_with_launcher(self, mock_filter): ) self.assertEqual(tps[0][0][1], "tp") + @mock.patch("plainbox.impl.session.remote_assistant.guess_normal_user") @mock.patch("fnmatch.filter") - def test_start_session_without_launcher(self, mock_filter): + def test_start_session_without_launcher(self, mock_filter, mock_gnu): # the real tp is referenced later on by it's second field mock_filter.return_value = [("tp", "tp")] + mock_gnu.return_value = "user" extra_cfg = dict() extra_cfg["launcher"] = "test_launcher" rsa = mock.Mock()