Skip to content

Commit

Permalink
ws: Conditionally block channel requests to remote hosts
Browse files Browse the repository at this point in the history
When AllowMultiHost is false, cockpit-ws will reject all GET requests
that would load from a non-localhost bridge.
  • Loading branch information
mvollmer committed Sep 20, 2024
1 parent 6592eda commit fc9a506
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 0 deletions.
9 changes: 9 additions & 0 deletions src/ws/cockpitchannelresponse.c
Original file line number Diff line number Diff line change
Expand Up @@ -601,6 +601,7 @@ cockpit_channel_response_serve (CockpitWebService *service,
gchar *channel = NULL;
gpointer key;
gpointer value;
gboolean allow_multihost;

g_return_if_fail (COCKPIT_IS_WEB_SERVICE (service));
g_return_if_fail (in_headers != NULL);
Expand All @@ -614,6 +615,14 @@ cockpit_channel_response_serve (CockpitWebService *service,
goto out;
}

allow_multihost = cockpit_conf_bool ("WebService", "AllowMultiHost", ALLOW_MULTIHOST_DEFAULT);
if (!allow_multihost && g_strcmp0 (host, "localhost") != 0)
{
cockpit_web_response_error (response, 403, NULL, NULL);
handled = TRUE;
goto out;
}

if (quoted_etag)
{
cache_type = COCKPIT_WEB_RESPONSE_CACHE;
Expand Down
31 changes: 31 additions & 0 deletions test/verify/check-shell-multi-machine
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
# along with Cockpit; If not, see <https://www.gnu.org/licenses/>.

import re
import subprocess
import time

import testlib
Expand Down Expand Up @@ -372,6 +373,36 @@ class TestMultiMachine(testlib.MachineCase):
self.allow_hostkey_messages()
self.allow_journal_messages(".* Failed to resolve hostname bad .*")

# Check whether AllowMultiHost blocks access already in cockpit-ws.

self.enable_multihost(m)
self.setup_ssh_auth()

# login into cockpit on machine1
self.login_and_go("/system")
cookie = b.cookie("cockpit")

def http_code(url):
return int(subprocess.check_output(["curl",
"--silent",
"-b", f"cockpit={cookie['value']}",
"-o", "/dev/null", "-w", "%{http_code" + "}",
f"http://{b.address}:{b.port}{url}"]))

# Now we can get resources from machine1 and machine2
self.assertEqual(200, http_code("/cockpit/@localhost/manifests.json"))
self.assertEqual(200, http_code("/cockpit/@10.111.113.2/manifests.json"))

# But not when AllowMultiHost is false
m.write("/etc/cockpit/cockpit.conf",
'[WebService]\nAllowMultiHost=no\n')
m.restart_cockpit()
b.relogin("/system")
cookie = b.cookie("cockpit")

self.assertEqual(200, http_code("/cockpit/@localhost/manifests.json"))
self.assertEqual(403, http_code("/cockpit/@10.111.113.2/manifests.json"))

def testDirectLogin(self):
self.machine.start_cockpit()
self.checkDirectLogin('/')
Expand Down

0 comments on commit fc9a506

Please sign in to comment.