diff --git a/containers/ws/README.md b/containers/ws/README.md index bdafa4047161..b794f08dfedc 100644 --- a/containers/ws/README.md +++ b/containers/ws/README.md @@ -100,7 +100,7 @@ this by passing your own configuration as a volume: Similarly you can also provide a custom `/etc/os-release` to change the branding. -### SSH authentication +### SSH authentication: Share keys with container The login page asks the user to confirm unknown SSH host key fingerprints. You can mount your known host keys into the container at @@ -119,6 +119,20 @@ You can also mount encrypted private keys inside the container. You can set an e Private keys can be encrypted; then cockpit uses the provided password to decrypt the key. +### SSH authentication: Share SSH agent with container + +Alternatively, if you use [ssh-agent](https://linux.die.net/man/1/ssh-agent) on +your host, you can share it with the container and run the container as your +own user (*not* as system container!). Then logging into remote machines from +Cockpit's login page re-uses the loaded private keys. For that, bind-mount the +agent socket in the container and tell it its path. If your host has SELinux +enabled, you need to disable the isolation for the container, so that it is +allowed to connect to the agent socket: + + -v $SSH_AUTH_SOCK:/ssh-agent \ + -e SSH_AUTH_SOCK=/ssh-agent \ + --security-opt=label=disable + ## More Info * [Cockpit Project](https://cockpit-project.org) diff --git a/containers/ws/label-run b/containers/ws/label-run index 90297677e46e..4610d62d0e67 100755 --- a/containers/ws/label-run +++ b/containers/ws/label-run @@ -42,6 +42,8 @@ else /usr/libexec/cockpit-certificate-ensure - eval $(ssh-agent) + # start SSH agent, unless we already got pointed to one + [ -n "${SSH_AUTH_SOCK:-}" ] || eval "$(ssh-agent)" + exec /usr/libexec/cockpit-ws --local-ssh "$@" fi diff --git a/test/verify/check-ws-bastion b/test/verify/check-ws-bastion index 3d3b5edf0a67..ab3f6da88a9a 100755 --- a/test/verify/check-ws-bastion +++ b/test/verify/check-ws-bastion @@ -255,6 +255,54 @@ class TestWsBastionContainer(testlib.MachineCase): for ssh_key_env in ["COCKPIT_SSH_KEY_PATH", f"COCKPIT_SSH_KEY_PATH_{HOST.upper()}"]: do_test_key_login(ssh_key_env=ssh_key_env) + def testExternalAgent(self): + m = self.machine + b = self.browser + + KEY_PASSWORD = "sshfoobar" + + # run the container as user -- as root does not make sense, as we want to + # share the user's SSH key with it + m.execute(f"podman save localhost/cockpit/ws -o {self.vm_tmpdir}/cockpit-ws.tar") + + self.restore_dir("/home/admin") + m.execute("runuser -u admin -- sh -ex", input=f""" + # we don't start a real login session here, fake it + cd $HOME + export XDG_RUNTIME_DIR=$HOME/run + mkdir -p "$XDG_RUNTIME_DIR" + + # create new key, set it up for logging into host + ssh-keygen -q -f ~/.ssh/id_bastion -N {KEY_PASSWORD} + cat ~/.ssh/id_bastion.pub > /home/admin/.ssh/authorized_keys + ssh-keyscan localhost | sed 's/^localhost/{HOST}/' > ~/.ssh/known_hosts + + # start agent, load key + eval $(ssh-agent -a $XDG_RUNTIME_DIR/ssh-agent) + printf '#!/bin/sh\necho {KEY_PASSWORD}\n' > /tmp/pwd + chmod u+x /tmp/pwd + SSH_ASKPASS_REQUIRE=force SSH_ASKPASS=/tmp/pwd ssh-add ~/.ssh/id_bastion + rm /tmp/pwd + ssh-add -l + + # run container + podman load -i {self.vm_tmpdir}/cockpit-ws.tar + podman run -d --rm --name cockpit-bastion -p 9090:9090 \ + -v ~/.ssh/known_hosts:/etc/ssh/ssh_known_hosts:ro \ + -v $XDG_RUNTIME_DIR/ssh-agent:/ssh-agent \ + -e SSH_AUTH_SOCK=/ssh-agent \ + --security-opt=label=disable \ + -e COCKPIT_DEBUG=all localhost/cockpit/ws + + until curl --fail --head -k https://localhost:9090/; do sleep 1; done + """) + + # login works without a password, using the external agent + b.open("/", tls=True) + b.set_val("#server-field", HOST) + b.try_login(password="") + b.wait_visible('#content') + @testlib.onlyImage("no cockpit/ws container on this image", "fedora-coreos") @testlib.nondestructive