[X2Go-Dev] Bug#1459: X2GoMiniSSHBroker

Stefan Baur X2Go-ML-1 at baur-itcs.de
Sun Apr 19 15:47:44 CEST 2020


package: x2gobroker
priority: wishlist

Hi everyone,

A while ago, I wrote a small broker demo in bash.

I would like to get this added to X2Go's official repository, in the
x2gobroker.git tree, as a separate binpkg (maybe called
x2gobroker-ssh-mini).


Limitations:

1) This script is not suitable for a multi-server setup.
   It needs to run on the only X2GoServer there is.
   (There's an idea in the comments how to overcome this limitation,
   though.)
   This is, however, also its advantage: You don't need to mess with
   LDAP, postgres and NFS just to be able to use a central configuration
   for your X2GoClients.

2) It does not offer all the ACL options of the "big" broker
   implementations.


Problems:

1) There's currently no manpage for it.  All documentation is in the
   comments in the bash script.

2) IIRC, Alex made some changes to X2GoClient and/or X2GoServer that
   will cause this script to break - however, these changes are not part
   of our stable release yet.  So it should be possible to release this
   package right now, but it needs to be kept in mind that it will have
   to be adapted once Alex' changes make it to stable.
   This was related to more "chatter" about "Access granted" and similar
   status messages being exchanged between server/broker/client.

Script attached.

Kind Regards,
Stefan Baur

-- 
BAUR-ITCS UG (haftungsbeschränkt)
Geschäftsführer: Stefan Baur
Eichenäckerweg 10, 89081 Ulm | Registergericht Ulm, HRB 724364
Fon/Fax 0731 40 34 66-36/-35 | USt-IdNr.: DE268653243
-------------- next part --------------
#!/bin/bash

# This file is part of the  X2Go Project - http://www.x2go.org
# Copyright (C) 2018 by Stefan Baur <X2Go-ML-1 at baur-itcs.de>
#
# X2Go Mini SSH Session Broker is free software; you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# X2Go Mini SSH Session Broker 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 Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program; if not, write to the
# Free Software Foundation, Inc.,
# 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.

# Features and Limitations
# You can add sessions as for-everyone (defaultsessions), per-group, and per-user
# You cannot add sessions based on IP range
# You cannot deny sessions based on group, user, or IP range
# Checking for suspended sessions and resuming them only works if you are logged in 
#   to the broker with the same credentials that you want to use to start/resume
#   the session AND 
#   if broker and X2Go server are one and the same machine
#   (This could be expanded so it works with separate machines, as long as ssh
#   public/private key authentication and autologin is used.)

# Config goes here - always only one session per file!
# /etc/x2go/x2go-mini-sshbroker/defaultsessions/*.session
# /etc/x2go/x2go-mini-sshbroker/${USER}/*.session
# /etc/x2go/x2go-mini-sshbroker/groups/${GROUP}/*.session

### init ###
# make a list of the parameters we received on the command line
PARAMLIST=$(echo -e "$@" | sed -e 's/ --/\n--/g')

# make sure we have a directory to write our config file to
mkdir -p ~/.x2go

### main ###

# check if we were asked to list sessions
if (echo -e "$PARAMLIST" | grep -q -- '--task listsessions'); then

	# this is so we can request data for a username that is different from the one we used
	# to log in and run this script with
	REQUESTEDUSER=$(echo -e "$PARAMLIST" | awk '$1 == "--user" { print $2}')
	if [ -n "$REQUESTEDUSER" ]; then
		USER=$REQUESTEDUSER
	fi

	# fetch default sessions
	if [ -d /etc/x2go/x2go-mini-sshbroker/defaultsessions ]; then
		for SINGLESESSIONFILE in /etc/x2go/x2go-mini-sshbroker/defaultsessions/*.session ; do
			# add session file name to the list of sessionfiles
			SESSIONFILES+="$SINGLESESSIONFILE\n"
			# figure out what the name of the session should be, based on the filename
			SINGLESESSIONNAME=$(basename $SINGLESESSIONFILE | sed -e 's/\.session$//')
			# check if the session file already contains a proper header block
			if (grep -q "^\[$SINGLESESSIONNAME\]" $SINGLESESSIONFILE); then
				# if it does, all we do is replace the user name
				SESSIONLIST+="\n$(grep -v '^user=' $SINGLESESSIONFILE)\nuser=$USER\n"
			else
				# if it does not, we add a header based on the file name, and replace the user name
				SESSIONLIST+="\n[$SINGLESESSIONNAME]\n$(grep -v '^\[' $SINGLESESSIONFILE | grep -v '^user=')\nuser=$USER\n"
			fi
		done
	fi

	# fetch user-specific sessions
	if [ -d /etc/x2go/x2go-mini-sshbroker/$USER ]; then
		for SINGLESESSIONFILE in /etc/x2go/x2go-mini-sshbroker/$USER/*.session ; do
			# add session file name to the list of sessionfiles
			SESSIONFILES+="$SINGLESESSIONFILE\n"
			# figure out what the name of the session should be, based on the filename
			SINGLESESSIONNAME=$(basename $SINGLESESSIONFILE | sed -e 's/\.session$//')
			# check if the session file already contains a proper header block
			if (grep -q "^\[$SINGLESESSIONNAME\]" $SINGLESESSIONFILE); then
				# if it does, all we do is replace the user name
				SESSIONLIST+="\n$(grep -v '^user=' $SINGLESESSIONFILE)\nuser=$USER\n"
			else
				# if it does not, we add a header based on the file name, and replace the user name
				SESSIONLIST+="\n[$SINGLESESSIONNAME]\n$(grep -v '^\[' $SINGLESESSIONFILE | grep -v '^user=')\nuser=$USER\n"
			fi
		done
	fi

	# fetch group-specific sessions
	if [ -d /etc/x2go/x2go-mini-sshbroker/groups ]; then
		# determine groups for this user and work through the list
		for SINGLEGROUP in $(id -Gn $USER) ; do
			if [ -d /etc/x2go/x2go-mini-sshbroker/groups/$SINGLEGROUP ]; then
				for SINGLESESSIONFILE in /etc/x2go/x2go-mini-sshbroker/groups/$SINGLEGROUP/*.session ; do
					# add session file name to the list of sessionfiles
					SESSIONFILES+="$SINGLESESSIONFILE\n"
					# figure out what the name of the session should be, based on the filename
					SINGLESESSIONNAME=$(basename $SINGLESESSIONFILE | sed -e 's/\.session$//')
					# check if the session file already contains a proper header block
					if (grep -q "^\[$SINGLESESSIONNAME\]" $SINGLESESSIONFILE); then
						# if it does, all we do is replace the user name
						SESSIONLIST+="\n$(grep -v '^user=' $SINGLESESSIONFILE)\nuser=$USER\n"
					else
						# if it does not, we add a header based on the file name, and replace the user name
						SESSIONLIST+="\n[$SINGLESESSIONNAME]\n$(grep -v '^\[' $SINGLESESSIONFILE | grep -v '^user=')\nuser=$USER\n"
					fi
				done
			fi
		done
	fi

	# store list of session files
	TEMPBROKERSESSIONFILE=$(mktemp -p ~/.x2go)
	echo -e "$SESSIONFILES">$TEMPBROKERSESSIONFILE
	# atomic transaction, so it is always complete when accessed, even when multiple instances are run in parallel
	mv $TEMPBROKERSESSIONFILE ~/.x2go/brokersessionfile-${USER} # needs user name, in case we ssh'ed into the broker using different credentials

	# output all session data
	echo -e "Access granted"
	echo -e "START_USER_SESSIONS"
	echo -e "$SESSIONLIST"
	echo -e "END_USER_SESSIONS"

# check if we were asked to provide a server name/IP and port for a specific session
elif (echo -e "$PARAMLIST" | grep -q -- '--task selectsession'); then
		SESSIONID=$(echo -e "$PARAMLIST" | awk '$1 == "--sid" { print $2 }')
		# search for the line with the corresponding session file in our stored list of files
		SESSIONFILE=$(grep "$SESSIONID" ~/.x2go/brokersessionfile-${USER})
		# determine server name/IP and port from this file
		SERVER=$(awk -F '=' '$1 == "host" { print $2 }' $SESSIONFILE)
		PORT=$(awk -F '=' '$1 == "sshport" { print $2 }' $SESSIONFILE)
		# if this failed, set default values
		if [ -z "$SERVER" ] && [ -f /etc/x2go/x2go-mini-sshbroker/defaulthost ]; then
			# determine default hostname/IP
			read DEFAULTHOST </etc/x2go/x2go-mini-sshbroker/defaulthost
			SERVER=$DEFAULTHOST
		fi

		if [ -z "PORT" ]; then
			PORT=22
		fi

		# output all data
		echo -e "Access granted"
		echo -e "SERVER:$SERVER:$PORT"
		# check for suspended sessions
		SESSIONLIST=$(x2golistsessions)
		# NOTE: at present, this only checks for local sessions (X2GoBroker==X2GoServer)
		# to make this work with a separate X2GoServer, we would need something like
		#if [ -z "$SESSIONLIST" ] && [ -n "$SSH_AUTH_SOCK" ]; then
		#	# very hackish and not safe! Try to add hosts to a shared known_hosts file in advance, and place it in /etc/x2go/x2go-mini-sshbroker/
		#	# then point UserKnownHostsFile at that and get rid of the StrictHostKeyChecking=false
		#	SESSIONLIST=$(ssh -oStrictHostKeyChecking=false -oUserKnownHostsFile=/dev/null -p $PORT -A $USER@$SERVER x2golistsessions 2>/dev/null)
		#fi
		# but the problem is, that it seems SSH_AUTH_SOCK is not set by the broker when logging in
		# one way around this might be an ssh private key stored in /etc/x2go/x2go-mini-sshbroker/, that is added as a limited key with
		# "forced-command=x2golistsessions_root" to /root/.ssh/authorized_keys to all servers - the output would then have to be filtered for the
		# username in question, as _root shows the data of all users on that particular host
		if [ -n "$SESSIONLIST" ]; then
			echo "SESSION_INFO:$SESSIONLIST"
		fi
fi
# DEBUG echo "$@" >>/tmp/x2go-mini-sshbroker-commands


More information about the x2go-dev mailing list