From 50b915ce0ce5e4d62a7b188afaf503811954fad3 Mon Sep 17 00:00:00 2001 From: Marius Vollmer Date: Fri, 9 Aug 2024 11:18:41 +0300 Subject: [PATCH] login: Warn before logging into multiple hosts --- pkg/static/login.html | 8 ++++ pkg/static/login.js | 12 ++++- pkg/static/login.scss | 4 +- test/reference | 2 +- test/verify/check-static-login | 85 ++++++++++++++++++++++++++++++++++ 5 files changed, 106 insertions(+), 5 deletions(-) diff --git a/pkg/static/login.html b/pkg/static/login.html index d2b20438653a..91dbba0d4087 100644 --- a/pkg/static/login.html +++ b/pkg/static/login.html @@ -23,6 +23,14 @@ + +
diff --git a/pkg/static/login.js b/pkg/static/login.js index 70cfcbc4aa61..d49080f39ea9 100644 --- a/pkg/static/login.js +++ b/pkg/static/login.js @@ -369,8 +369,16 @@ function debug(...args) { } } - if (cur_machine && !environment.page.allow_multihost) - redirect_to_current_machine(); + if (cur_machine) { + if (!environment.page.allow_multihost) + redirect_to_current_machine(); + else { + id("multihost-message").textContent = format(_("You are already connected to '$0' in this browser session. Connecting to other hosts will allow them to execute arbitrary code on each other. Please be careful."), + cur_machine == "." ? "localhost" : cur_machine); + id("multihost-get-me-there").addEventListener("click", redirect_to_current_machine); + show('#multihost-warning'); + } + } } function boot() { diff --git a/pkg/static/login.scss b/pkg/static/login.scss index 203f32a74b3e..c8ba14571fe3 100644 --- a/pkg/static/login.scss +++ b/pkg/static/login.scss @@ -355,14 +355,14 @@ label.checkbox { display: none; } -.login-pf #banner { +.login-pf #banner, .login-pf #multihost-warning { margin-block: 1rem 0.5rem; margin-inline: 0; grid-area: banner; inline-size: 100%; } -#banner-message { +#banner-message, #multihost-message { white-space: pre-wrap; max-block-size: 12em; overflow: auto; diff --git a/test/reference b/test/reference index c83ced24f3d8..0d2849e2a944 160000 --- a/test/reference +++ b/test/reference @@ -1 +1 @@ -Subproject commit c83ced24f3d8a9d0279808014598b9a85893d061 +Subproject commit 0d2849e2a944573b64cd2fad8a023d84d6b8c413 diff --git a/test/verify/check-static-login b/test/verify/check-static-login index 6c6ae0925d24..c7e046b84750 100755 --- a/test/verify/check-static-login +++ b/test/verify/check-static-login @@ -1111,5 +1111,90 @@ matchrule = ^DC=LAN,DC=COCKPIT,CN=alice$ check_store_hostkey(real_hostkey) +@testlib.skipBeiboot("host switching disabled in beiboot mode") +class TestLoginMultiHost(testlib.MachineCase): + def testBasic(self): + b = self.browser + m1 = self.machines["machine1"] + + ip = "172.27.0.15" + + # Disallow multiple sessions initially + + if self.multihost_enabled: + m1.write("/etc/cockpit/cockpit.conf", + '[WebService]\nAllowMultiHost=no\n') + + m1.start_cockpit() + + # Log in via SSH + + b.open(f"/={ip}/playground") + b.set_val('#login-user-input', "admin") + b.set_val('#login-password-input', "foobar") + b.click("#login-button") + b.wait_in_text("#hostkey-fingerprint", "SHA256:") + b.click("#login-button") + b.wait_visible('#content') + self.assertEqual(b.eval_js("window.location.pathname"), f"/={ip}/playground") + + # Go back to login page. The SSH session from above will still + # be active (for some time until it times out) and the login + # page will immediately redirect us to it. We will end up on + # the Overview (instead of the playground). + + b.eval_js("window.location = '/'") # b.go would run into a "navigation canceled error" + b.wait_js_cond(f"window.location.pathname == '/={ip}/system'") + b.wait_visible('#content') + b.logout() + + # Enable host switcher for the rest of the test + + if self.multihost_enabled: + # clean up AllowMultiHost=no from above + m1.execute("rm /etc/cockpit/cockpit.conf") + self.enable_multihost(m1) + m1.restart_cockpit() + + # Log in via SSH + + b.open("/") + b.set_val('#login-user-input', "admin") + b.set_val('#login-password-input', "foobar") + b.click("#show-other-login-options") + b.set_val("#server-field", ip) + b.click("#login-button") + b.wait_visible('#content') + + # Go back to login page. The SSH session will still be active + # as before, but now the login page will merely warn us about + # it. + + b.open("/") + b.wait_in_text("#multihost-warning", f"You are already connected to '{ip}' in this browser session") + b.assert_pixels("body", "warning") + + # Clicking on the button should redirect us to that session + + b.click("#multihost-warning button") + b.wait_visible('#content') + self.assertEqual(b.eval_js("window.location.pathname"), f"/={ip}/system") + + # Go back to login and log in locally anyway. + + b.open("/") + b.set_val('#login-user-input', "admin") + b.set_val('#login-password-input', "foobar") + b.click("#login-button") + b.wait_visible('#content') + self.assertEqual(b.eval_js("window.location.pathname"), "/system") + + # Go back to first session, it should still be there + + b.open(f"/={ip}") + b.wait_visible('#content') + self.assertEqual(b.eval_js("window.location.pathname"), f"/={ip}/system") + + if __name__ == '__main__': testlib.test_main()