WEBUI_NOAUTH defaults to 0, so the previous condition enabled the remote auth config for all installations, including local ones. Gate on WEBUI_REMOTE=1 as well so local installations skip the login page.
273 lines
9.9 KiB
Bash
Executable file
273 lines
9.9 KiB
Bash
Executable file
#!/usr/bin/bash
|
|
|
|
# This file is part of Cockpit.
|
|
#
|
|
# Copyright (C) 2018 Red Hat, Inc.
|
|
#
|
|
# Cockpit is free software; you can redistribute it and/or modify it
|
|
# under the terms of the GNU Lesser General Public License as published by
|
|
# the Free Software Foundation; either version 2.1 of the License, or
|
|
# (at your option) any later version.
|
|
#
|
|
# Cockpit is distributed in the hope that it will be useful, but
|
|
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
# Lesser General Public License for more details.
|
|
#
|
|
# You should have received a copy of the GNU Lesser General Public License
|
|
# along with Cockpit; If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
# Run a local bridge, web server, and browser for a particular Cockpit page.
|
|
# This is useful for integration into .desktop files, for systems which don't
|
|
# have cockpit.socket enabled. The web server and browser run in an unshared
|
|
# network namespace, and thus are totally isolated from everything else.
|
|
#
|
|
# Usage:
|
|
# cockpit-desktop /cockpit/@localhost/system/index.html -t default -r 0
|
|
# For testing purposes one can also make cockpit-ws bind to all addresses
|
|
# (this is insecure and should not be used in prodcuction):
|
|
# cockpit-desktop /cockpit/@localhost/system/index.html -t default -r 1
|
|
#
|
|
set -eu
|
|
|
|
BROWSER_HOME=""
|
|
|
|
THEME_ID="default"
|
|
WEBUI_REMOTE=0
|
|
WEBUI_NOAUTH=0
|
|
while getopts t:r:n: option
|
|
do
|
|
case "${option}"
|
|
in
|
|
t)THEME_ID=${OPTARG};;
|
|
r)WEBUI_REMOTE=${OPTARG};;
|
|
n)WEBUI_NOAUTH=${OPTARG};;
|
|
*) echo "Usage: $0 [-t THEME_ID] [-r WEBUI_REMOTE] [-n WEBUI_NOAUTH]" >&2
|
|
exit 1 ;;
|
|
esac
|
|
done
|
|
|
|
URL_PATH="/cockpit/@localhost/anaconda-webui/index.html"
|
|
REMOTE_AUTH_DROPIN="/etc/anaconda/cockpit/conf.d/50-remote-auth.conf"
|
|
REMOTE_AUTH_SOURCE="/usr/share/anaconda/cockpit/conf.d/50-remote-auth.conf"
|
|
WEBUI_AUTH=0
|
|
|
|
if [[ "$WEBUI_REMOTE" == "1" && "$WEBUI_NOAUTH" == "0" ]]; then
|
|
cp "$REMOTE_AUTH_SOURCE" "$REMOTE_AUTH_DROPIN"
|
|
WEBUI_AUTH=1
|
|
else
|
|
rm -f "$REMOTE_AUTH_DROPIN"
|
|
fi
|
|
echo "WEBUI_AUTH=$WEBUI_AUTH" > /tmp/webui-cockpit-ws.env
|
|
echo "WEBUI_REMOTE=$WEBUI_REMOTE" >> /tmp/webui-cockpit-ws.env
|
|
|
|
systemctl start webui-cockpit-ws
|
|
|
|
if [[ "$WEBUI_REMOTE" == "1" ]]; then
|
|
systemctl start webui-tls-proxy
|
|
fi
|
|
|
|
# Function to setup user-related environment
|
|
setup_user_environment() {
|
|
# PKEXEC_UID is the uid for "gnome-initial-setup" or "liveuser"
|
|
# depending on how the installer gets started.
|
|
#
|
|
# It's unset on non-live-images, so we just use the current user then (root)
|
|
if [ -n "${PKEXEC_UID:-}" ]; then
|
|
# If PKEXEC_UID is set, use the user associated with it
|
|
INSTALLER_USER=$(id -n -u "${PKEXEC_UID}")
|
|
else
|
|
# Try to find another user who is not root and has /usr/bin/bash as their shell
|
|
INSTALLER_USER=$(grep '/usr/bin/bash' /etc/passwd | grep -v '^root' | cut -d: -f1 | head -n 1)
|
|
|
|
# If no such user is found, use the current user running the script
|
|
if [ -z "${INSTALLER_USER:-}" ]; then
|
|
INSTALLER_USER=$(id -un)
|
|
fi
|
|
fi
|
|
|
|
# Get the home directory of the selected user
|
|
HOME_DIR=$(grep "^$INSTALLER_USER:" /etc/passwd | cut -d: -f6)
|
|
|
|
# Check if the home directory exists, otherwise create it
|
|
if [ ! -d "$HOME_DIR" ]; then
|
|
echo "The home directory $HOME_DIR does not exist. Creating it." >&2
|
|
mkdir -p "$HOME_DIR"
|
|
chown "$INSTALLER_USER" "$HOME_DIR"
|
|
else
|
|
echo "Home directory $HOME_DIR already exists." >&2
|
|
fi
|
|
|
|
# Return the user for further use
|
|
echo "$INSTALLER_USER"
|
|
}
|
|
|
|
get_default_browser() {
|
|
# Read the default browser from the anaconda runtime configuration file but wait till it's available
|
|
# FIXME: Related to: https://issues.redhat.com/browse/INSTALLER-4223
|
|
timeout=60
|
|
elapsed=0
|
|
|
|
while [ ! -f /run/anaconda/anaconda.conf ]; do
|
|
if [ "$elapsed" -ge "$timeout" ]; then
|
|
echo "Timed out waiting for anaconda.conf to be available." >&2
|
|
exit 1
|
|
fi
|
|
sleep 1
|
|
elapsed=$((elapsed + 1))
|
|
done
|
|
|
|
# FIXME: Should be provided as an argument to this script instead of grepping the config file
|
|
DEFAULT_BROWSER=$(grep '^webui_web_engine =' /run/anaconda/anaconda.conf | cut -d'=' -f2)
|
|
if [ -n "$DEFAULT_BROWSER" ]; then
|
|
echo "Default browser set in anaconda.conf: $DEFAULT_BROWSER" >&2
|
|
DEFAULT_BROWSER=$(echo "$DEFAULT_BROWSER" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
|
|
echo "$DEFAULT_BROWSER"
|
|
else
|
|
echo "No default browser set in anaconda.conf, using firefox." >&2
|
|
echo "firefox"
|
|
fi
|
|
}
|
|
|
|
prepare_firefox_cmd() {
|
|
INSTALLER_USER=$1
|
|
INSTALLER_XDG_RUNTIME_DIR=$2
|
|
|
|
# prepare empty firefox profile dir with theme based on the passed profile id
|
|
# INSTALLER_XDG_RUNTIME_DIR is created by the caller before this runs.
|
|
FIREFOX_THEME_DIR="/usr/share/anaconda/firefox-theme"
|
|
FIREFOX_PROFILE_PATH="${INSTALLER_XDG_RUNTIME_DIR}/anaconda/firefox-profile"
|
|
|
|
# make sure the profile directory exists and is empty
|
|
if [ -d ${FIREFOX_PROFILE_PATH} ]
|
|
then
|
|
echo "Cleaning up existing Anaconda Firefox profile directory." >&2
|
|
rm -rf ${FIREFOX_PROFILE_PATH}
|
|
fi
|
|
pkexec --user "${INSTALLER_USER}" mkdir -p ${FIREFOX_PROFILE_PATH}
|
|
|
|
# populate the profile directory with our custom Firefox theme
|
|
# - theme id is passed as the second argument of this script
|
|
THEME_PATH="${FIREFOX_THEME_DIR}/${THEME_ID}"
|
|
|
|
pkexec --user "${INSTALLER_USER}" cp -a "${THEME_PATH}/." ${FIREFOX_PROFILE_PATH}
|
|
|
|
# set environment for Firefox
|
|
BROWSER_ENV=(MOZ_APP_TITLE="" MOZ_APP_REMOTINGNAME="liveinst" MOZ_GTK_TITLEBAR_DECORATION=client)
|
|
|
|
BROWSER=(/usr/bin/env "${BROWSER_ENV[@]}" /usr/bin/firefox --new-instance --profile "${FIREFOX_PROFILE_PATH}")
|
|
|
|
declare -p BROWSER
|
|
}
|
|
|
|
|
|
if [[ "$WEBUI_REMOTE" == "1" ]]
|
|
then
|
|
/bin/sleep infinity &
|
|
BLOCK_ON_PID=$!
|
|
else
|
|
INSTALLER_USER=$(setup_user_environment)
|
|
INSTALLER_UID=$(id -u "${INSTALLER_USER}")
|
|
|
|
INSTALLER_XDG_RUNTIME_DIR="/run/user/${INSTALLER_UID}"
|
|
if [ ! -d "${INSTALLER_XDG_RUNTIME_DIR}" ]; then
|
|
mkdir -p "${INSTALLER_XDG_RUNTIME_DIR}"
|
|
chown "${INSTALLER_USER}" "${INSTALLER_XDG_RUNTIME_DIR}"
|
|
chmod 0700 "${INSTALLER_XDG_RUNTIME_DIR}"
|
|
fi
|
|
|
|
# if we have netcat, use it for waiting until ws is up
|
|
if type nc >/dev/null 2>&1; then
|
|
for _ in `seq 10`; do
|
|
nc -z 127.0.0.1 80 && break
|
|
sleep 0.5;
|
|
done
|
|
else
|
|
# otherwise, just wait a bit
|
|
sleep 3
|
|
fi
|
|
|
|
if user_env_output=$(pkexec --user "${INSTALLER_USER}" env XDG_RUNTIME_DIR="${INSTALLER_XDG_RUNTIME_DIR}" systemctl --user show-environment 2>/dev/null); then
|
|
readarray -t user_environment <<< "$user_env_output"
|
|
USER_SESSION_AVAILABLE=1
|
|
else
|
|
echo "No systemd user session available, continuing without user session environment." >&2
|
|
user_environment=()
|
|
USER_SESSION_AVAILABLE=0
|
|
fi
|
|
|
|
USER_GRAPHICAL_SESSION_AVAILABLE=0
|
|
if [ "$USER_SESSION_AVAILABLE" = "1" ] && [ -n "${PKEXEC_UID:-}" ]; then
|
|
# Live ISO only: reuse the desktop user's session when it has a display.
|
|
if printf '%s\n' "${user_environment[@]}" | grep -qE '^(WAYLAND_DISPLAY|DISPLAY)='; then
|
|
USER_GRAPHICAL_SESSION_AVAILABLE=1
|
|
fi
|
|
fi
|
|
|
|
if [ "$USER_GRAPHICAL_SESSION_AVAILABLE" = "1" ]; then
|
|
for var in DISPLAY WAYLAND_DISPLAY XDG_RUNTIME_DIR DBUS_SESSION_BUS_ADDRESS XAUTHORITY; do
|
|
if [ -n "${!var:-}" ] && ! printf '%s\n' "${user_environment[@]}" | grep -q "^${var}="; then
|
|
user_environment+=("${var}=${!var}")
|
|
fi
|
|
done
|
|
fi
|
|
|
|
DEFAULT_BROWSER_CMD=$(get_default_browser)
|
|
echo "Using default browser: ${DEFAULT_BROWSER_CMD}" >&2
|
|
if [[ "${DEFAULT_BROWSER_CMD}" == "firefox" ]]; then
|
|
eval "$(prepare_firefox_cmd "$INSTALLER_USER" "$INSTALLER_XDG_RUNTIME_DIR")"
|
|
echo "Using Firefox browser command: ${BROWSER[@]}" >&2
|
|
else
|
|
BROWSER=(${DEFAULT_BROWSER_CMD})
|
|
echo "Using default browser command: ${BROWSER[@]}" >&2
|
|
fi
|
|
|
|
# start browser in a temporary home dir, so that it does not interfere with your real one
|
|
BROWSER_HOME=$(mktemp --directory --tmpdir cockpit.desktop.XXXXXX)
|
|
chown "${INSTALLER_USER}" "${BROWSER_HOME}"
|
|
WEBUI_URL=http://127.0.0.1"$URL_PATH"
|
|
|
|
if [ -n "${DISPLAY:-}" ] || [ -n "${WAYLAND_DISPLAY:-}" ]; then
|
|
if [ "$USER_GRAPHICAL_SESSION_AVAILABLE" = "1" ]; then
|
|
HOME="$BROWSER_HOME" \
|
|
pkexec --user "$INSTALLER_USER" env XDG_CURRENT_DESKTOP=GNOME "${user_environment[@]}" "${BROWSER[@]}" "$WEBUI_URL" &
|
|
BLOCK_ON_PID=$!
|
|
else
|
|
type dbus-run-session >/dev/null 2>&1 || { echo "Error: dbus-run-session is not ready, cannot continue." >&2; exit 1; }
|
|
|
|
ROOT_XDG_RUNTIME_DIR="/run/user/0"
|
|
ROOT_WAYLAND_SOCKET="$(find "${ROOT_XDG_RUNTIME_DIR}" -maxdepth 1 -type s -name 'wl-sysinstall-*' | head -n 1)"
|
|
|
|
if [ -z "${ROOT_WAYLAND_SOCKET}" ]; then
|
|
echo "Error: root Wayland socket not found under ${ROOT_XDG_RUNTIME_DIR}" >&2
|
|
exit 1
|
|
fi
|
|
|
|
chmod 711 "${ROOT_XDG_RUNTIME_DIR}"
|
|
chmod a+rw "${ROOT_WAYLAND_SOCKET}"
|
|
|
|
HOME="$BROWSER_HOME" \
|
|
pkexec --user "$INSTALLER_USER" env \
|
|
XDG_CURRENT_DESKTOP=GNOME \
|
|
XDG_SESSION_TYPE=wayland \
|
|
XDG_RUNTIME_DIR="${INSTALLER_XDG_RUNTIME_DIR}" \
|
|
WAYLAND_DISPLAY="${ROOT_WAYLAND_SOCKET}" \
|
|
dbus-run-session -- "${BROWSER[@]}" "$WEBUI_URL" \
|
|
>/tmp/webui-browser.log 2>&1 &
|
|
BLOCK_ON_PID=$!
|
|
fi
|
|
else
|
|
echo "Error: no graphical session detected (DISPLAY and WAYLAND_DISPLAY are unset)." >&2
|
|
exit 1
|
|
fi
|
|
fi
|
|
|
|
# Cleanup function
|
|
cleanup() {
|
|
set +e
|
|
kill $BLOCK_ON_PID
|
|
[[ -n $BROWSER_HOME ]] && rm -rf $BROWSER_HOME
|
|
}
|
|
trap 'cleanup' EXIT INT QUIT PIPE
|
|
|
|
wait $BLOCK_ON_PID
|