diff --git a/src/cockpit/remote.py b/src/cockpit/remote.py index ba0e52899d34..b1cbaf48d80d 100644 --- a/src/cockpit/remote.py +++ b/src/cockpit/remote.py @@ -23,7 +23,7 @@ from cockpit._vendor import ferny -from .jsonutil import JsonObject, get_str +from .jsonutil import JsonDocument, JsonObject, get_str, get_str_or_none from .peer import Peer, PeerError from .router import Router, RoutingRule @@ -153,6 +153,15 @@ def do_kill(self, host: Optional[str], group: Optional[str]) -> None: elif host is None: super().do_kill(None, group) + def do_authorize(self, message: JsonObject) -> None: + if get_str(message, 'challenge').startswith('plain1:'): + cookie = get_str(message, 'cookie') + self.write_control(command='authorize', cookie=cookie, response=self.password or '') + self.password = None # once is enough... + + def do_superuser_init_done(self) -> None: + self.password = None + def __init__(self, router: Router, host: str, user: Optional[str], options: JsonObject, *, private: bool) -> None: super().__init__(router) self.host = host @@ -161,7 +170,15 @@ def __init__(self, router: Router, host: str, user: Optional[str], options: Json self.private = private self.session = ferny.Session() - self.start_in_background(init_host=host) + + superuser: JsonDocument + init_superuser = get_str_or_none(options, 'init-superuser', None) + if init_superuser in (None, 'none'): + superuser = False + else: + superuser = {'id': init_superuser} + + self.start_in_background(init_host=host, superuser=superuser) class HostRoutingRule(RoutingRule): diff --git a/test/verify/check-shell-multi-os b/test/verify/check-shell-multi-os index 55e069cdb462..08828b9f0502 100755 --- a/test/verify/check-shell-multi-os +++ b/test/verify/check-shell-multi-os @@ -69,7 +69,7 @@ def add_stock_machine(b, address, password): @testlib.skipDistroPackage() -class TestMultiOS(testlib.MachineCase): +class TestCentos7(testlib.MachineCase): provision = { "0": {"address": "10.111.113.1/20", "memory_mb": 512}, "centos-7": {"address": "10.111.113.5/20", "image": "centos-7", "memory_mb": 512} @@ -95,16 +95,10 @@ class TestMultiOS(testlib.MachineCase): })""", address) @testlib.todoPybridgeRHEL8() - def testCentOS7(self): + def test(self): dev_m = self.machine dev_b = self.browser - # Newer bridges running under an old cockpit-ws don't get the - # support that they need to prompt for the password. So open - # up sudo for this test. - dev_m.execute("echo '%wheel ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers.d/user-override") - dev_m.execute("echo '%sudo ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers.d/user-override") - self.allow_hostkey_messages() self.login_and_go() @@ -160,6 +154,45 @@ class TestMultiOS(testlib.MachineCase): self.allow_restart_journal_messages() +@testlib.skipDistroPackage() +class TestRHEL8(testlib.MachineCase): + provision = { + "0": {"address": "10.111.113.1/20", "memory_mb": 768}, + "stock": {"address": "10.111.113.5/20", "image": "rhel-8-8", "memory_mb": 512} + } + + @testlib.todoPybridgeRHEL8() + def test(self): + dev_m = self.machine + dev_b = self.browser + + stock_m = self.machines['stock'] + stock_m.execute("hostnamectl set-hostname stock") + + # Wait for connectivity between the two + stock_m.execute("ping -q -w5 -c5 10.111.113.1") + dev_m.execute("ping -q -w5 -c5 10.111.113.5") + + self.allow_hostkey_messages() + + # New machine adding old machine + + self.login_and_go() + dev_b.click("#hosts-sel button") + dev_addresses = ["localhost"] + wait_addresses(dev_b, dev_addresses) + + add_machine(dev_b, "10.111.113.5", password="foobar") + dev_addresses.append("10.111.113.5") + wait_addresses(dev_b, dev_addresses) + + dev_b.go("/@10.111.113.5/") + dev_b.wait_visible("iframe.container-frame[name='cockpit1:10.111.113.5/system'][data-loaded]") + dev_b.enter_page("/system", host="10.111.113.5") + dev_b.wait_in_text(".ct-overview-header-hostname", "stock") + dev_b.wait_in_text(".ct-overview-header-hostname", "running Red Hat Enterprise Linux 8") + + @testlib.skipDistroPackage() class TestMultiOSDirect(testlib.MachineCase): provision = { diff --git a/test/verify/check-superuser b/test/verify/check-superuser index ad9f41c4e76a..2ce25c88057f 100755 --- a/test/verify/check-superuser +++ b/test/verify/check-superuser @@ -595,6 +595,22 @@ class TestSuperuserDashboard(testlib.MachineCase): b.wait_in_text(".super-channel span", 'result: ') self.assertIn('result: uid=0', b.text(".super-channel span")) + # Logging out and logging back in should give us immediate + # superuser on m2 (once we have logged in there). + b.relogin() + b.wait_visible("#machine-troubleshoot") + b.click('#machine-troubleshoot') + b.wait_visible('#hosts_setup_server_dialog') + b.set_input_text("#login-custom-password", "foobar") + b.click('#hosts_setup_server_dialog button:contains("Log in")') + b.wait_not_present('#hosts_setup_server_dialog') + b.check_superuser_indicator("Administrative access") + + b.enter_page("/playground/test", host="10.111.113.2") + b.click(".super-channel button") + b.wait_in_text(".super-channel span", 'result: ') + self.assertIn('result: uid=0', b.text(".super-channel span")) + b.drop_superuser() b.click(".super-channel button") b.wait_in_text(".super-channel span", 'access-denied') @@ -705,7 +721,7 @@ class TestSuperuserDashboardOldMachine(testlib.MachineCase): "machine2": {"address": "10.111.113.2/20", "image": "centos-7"}, } - @testlib.todoPybridge(reason="https://github.com/cockpit-project/cockpit/issues/18712") + @testlib.todoPybridgeRHEL8() def test(self): b = self.browser