Skip to content

Instantly share code, notes, and snippets.

@gbraad
Last active January 13, 2022 06:19
Show Gist options
  • Save gbraad/c556d82394ca0dcc333e9609974fcaf8 to your computer and use it in GitHub Desktop.
Save gbraad/c556d82394ca0dcc333e9609974fcaf8 to your computer and use it in GitHub Desktop.
Proof of Concept to use bearer token with Cockpit

Proof of Concept to use bearer token with Cockpit

/usr/local/bin/verify-bearer-token

#!/bin/sh
# This file is part of CRC
# Note: this is a POC and should not be used in production
#
# Copyright (C) 2021 Red Hat, Inc.
set -eux
HOST="$1"
echo "Bearer auth attempt from $HOST" >&2
# FIXME: should be random
COOKIE=c1

# FIXME: compute frame length (in particular for different cookie length)
printf '61\n\n{ "command": "authorize", "cookie": "'$COOKIE'", "challenge": "*" }'
read framelen
read channel
[ "$channel" = "" ]
read -n $((framelen - 1)) response
echo "got response '$response'" >&2

# looks like '{"command":"authorize","cookie":"c1","response":"Bearer 123foo"}'
if [ "$(echo "$response" | jq -r .cookie)" != "$COOKIE" ]; then
    # FIXME: send proper "problem" JSON
    echo "bad cookie" >&2
    exit 1
fi

if [ "$(echo "$response" | jq -r .response)" != "Bearer Y29yZQ==" ]; then
    # FIXME: send proper "problem" JSON
    echo "bad password" >&2
    exit 1
fi

export XDG_RUNTIME_DIR=/run/user/$(id -u)
exec cockpit-bridge

/etc/cockpit/cockpit.conf

[bearer]
command = /usr/local/bin/verify-bearer-token
timeout = 300

app.js

const host = "172.26.158.25";

const start = async function() {
  const filter = {
    urls: [`http://${host}:9090/*`, `https://${host}:9090/*`]
  }

  session.defaultSession.webRequest.onBeforeSendHeaders(filter, (details, callback) => {
    details.requestHeaders['Authorization'] = 'Bearer Y29yZQ=='
    callback({ requestHeaders: details.requestHeaders })
  });
}

/etc/systemd/system/cockpit-core.service

[Unit]
Description=Cockpit-ws for Core user

[Service]
Environment="XDG_RUNTIME_DIR=/run/user/1000"
ExecStart=/usr/libexec/cockpit-ws --no-tls --local-session=/usr/bin/cockpit-bridge
User=core
Group=core
Restart=on-failure

[Install]
WantedBy=multi-user.target
@gbraad
Copy link
Author

gbraad commented Nov 17, 2021

This still results in issues for the user, as the unit can not access the XDG_RUNTIME_DIR that is set. After issuing setenforce 0 this works.
Running the process as 'user' does not have this problem (or as a user unit).

@gbraad
Copy link
Author

gbraad commented Nov 17, 2021

Might wanna override mount -o bind /usr/local/my/special/login.html /usr/share/cockpit/static/login.html

@martinpitt
Copy link

Just for the record: You can avoid the SELinux problems and the need for setting XDG_RUNTIME_DIR by putting the unit into /etc/systemd/user/cockpit-core.service instead (user unit), enable it for the core user, and make sure that core's user systemd service starts up at boot:

loginctl enable-linger core

@martinpitt
Copy link

With --local-session=/usr/bin/cockpit-bridge you completely circumvent the entire login process (cockpit-session etc.). This makes /usr/local/bin/verify-bearer-token and cockpit.conf entirely irrelevant. This is an option which only makes sense for things like cockpit-desktop or the flatpak, where the webserver already runs as the target user and is somehow network-confined.

The original PoC was gbraad-redhat/podman-cockpit-desktop#3 (comment) which does not use --local-session.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment