The sshd_container.sh
script distributed in this repository is used in
conjunction with the OpenSSH sshd
daemon to launch a Linux container for each
ssh
login from a client. This containerizes the environment of user sessions
by default. Users may specify an environment variable APPTAINER_CONTAINER
before executing ssh
login in order to select a specific container on the
login node.
File | Description |
---|---|
sshd_container | Configuration file (default path /etc/default/sshd_container ) |
sshd_container.sh | Login script (default path /etc/ssh/sshd_container.sh ) |
Copy the configuration file sshd_container
and the
sshd_container.sh
login script to the expected default locations. Add
following lines to /etc/ssh/sshd_config
and restart sshd
:
AcceptEnv APPTAINER_CONTAINER
ForceCommand /etc/ssh/sshd_container.sh
The line above configures the OpenSSH daemon to accept APPTAINER_CONTAINER
as input
environment variable using the configuration option AcceptEnv
(from the
sshd_config
manual):
AcceptEnv
Specifies what environment variables sent by the client will be copied into the session's environ(7). See
SendEnv
in ssh_config(5) for how to configure the client. Note that environment passing is only supported for protocol 2. Variables are specified by name, which may contain the wildcard characters*
and?
. Multiple environment variables may be separated by whitespace or spread across multipleAcceptEnv
directives. Be warned that some environment variables could be used to bypass restricted user environments. For this reason, care should be taken in the use of this directive. The default is not to accept any environment variables.
ForceCommand
executes the script sshd_container.sh
which reads the
APPTAINER_CONTAINER
environment variable, validates the input and launches
a container during ssh
login.
ForceCommand
Forces the execution of the command specified by
ForceCommand
, ignoring any command supplied by the client and~/.ssh/rc
if present. The command is invoked by using the user's login shell with the-c
option. This applies to shell, command, or subsystem execution. It is most useful inside a Match block. The command originally supplied by the client is available in theSSH_ORIGINAL_COMMAND
environment variable. Specifying a command of internal-sftp will force the use of an in-process SFTP server that requires no support files when used withChrootDirectory
. The default is none.
Customize the behavior of the login script via the configuration
file sshd_container
:
Variable | Description |
---|---|
SSHD_CONTAINER_DEFAULT |
Default container to start unless the user passes the environment variable APPTAINER_CONTAINER at login. |
SSHD_CONTAINER_OPTIONS |
Command-line options appended to the apptainer command at container launch (for example --bind=/srv ) |
SSHD_CONTAINER_MENU |
List of containers presented to the user for selection when requesting a menu with APPTAINER_CONTAINER=menu . |
Usage of the APPTAINER_CONTAINER
environment variable in the shell
environment on the ssh
client:
Variable | Description |
---|---|
APPTAINER_CONTAINER= |
Unset, empty of blank will launch the default container defined in SSHD_CONTAINER_DEFAULT . |
APPTAINER_CONTAINER=${path} |
Launches a container specified by a user. |
APPTAINER_CONTAINER=none |
No container is launched, effective login into the host environment |
APPTAINER_CONTAINER=menu |
Present the user a selection menu with a list of container specified in SSHD_CONTAINER_MENU |
Users need to make sure to propagate the APPTAINER_CONTAINER
environment
variable to the server using the SendEnv
configuration option (from the
ssh_config
manual):
SendEnv
Specifies what variables from the local environ(7) should be sent to the server. Note that environment passing is only supported for protocol 2. The server must also support it, and the server must be configured to accept these environment variables. Refer to
AcceptEnv
in sshd_config(5) for how to configure the server. Variables are specified by name, which may contain wildcard characters. Multiple environment variables may be separated by whitespace or spread across multipleSendEnv
directives. The default is not to send any environment variables.
Note tat the root
account will always default to APPTAINER_CONTAINER=none
.
This grantees administrative access to a node. This is particularly imported if
there is only a single sshd
instance running on the node. Either use the SSH
client option -o SendEnv=APPTAINER_CONTAINER
or append this configuration an
SSH per-user configuration file in ~/.ssh/config
or the system-wide
configuration file in /etc/ssh/ssh_config
.
Build the required singularity containers with the script containers.sh
.
(This requires the apptainer
command installed on the host). The containers
generated by the script are stored under /tmp/*.sif
.
Work on the login script using your host:
SSHD_CONTAINER_DEBUG=true \
APPTAINER_CONTAINER=menu \
SSHD_CONTAINER_CONFIG=sshd_container \
bash -x ./sshd_container.sh
Start the test environment using the included Vagrantfile
which copies
the Singularity containers to /tmp
:
vagrant up $box
# configuration for sshd
sshd_config=\
'PermitRootLogin yes
AcceptEnv APPTAINER_CONTAINER SSHD_CONTAINER_*
ForceCommand /etc/ssh/sshd_container.sh'
# configure the box
vagrant ssh $box -- "
echo 'Text from /etc/motd' | sudo tee /etc/motd
echo 'Dummy content' | sudo tee /srv/dummy.txt
sudo cp -v /vagrant/sshd_container /etc/default/sshd_container
sudo cp -v /vagrant/sshd_container.sh /etc/ssh/sshd_container.sh
echo '$sshd_config' | sudo tee -a /etc/ssh/sshd_config
sudo mkdir ~root/.ssh
sudo chmod 700 ~root/.ssh
cat ~vagrant/.ssh/authorized_keys | sudo tee -a ~root/.ssh/authorized_keys
sudo chmod 600 ~root/.ssh/authorized_keys
"
Start sshd
on port 23 in foreground for debugging:
# start a second instance of sshd in foreground on port 23
vagrant ssh $box -- sudo /sbin/sshd -o LogLevel=DEBUG -De -p 23
# connect via the forwarding port (cf. Vagrantfile)
vagrant ssh-config $box > ssh-config
ssh -F ssh-config -p 23 vagrant@$box
ssh-config
provides the default configuration from Vagrant to connect with
SSH to the box. Either alter the configuration file or use the SSH option -p
to connect with the non default port 23.
Alternatively restart sshd.service
to run on the default port 22:
vagrant ssh $box -- sudo systemctl restart sshd.service
# Note that this will influence `vagrant ssh` login and may make it difficult to
# debug any issue with SSH login.
The test.sh
script runs ssh
, scp
, rsync
and sftp
commands
against the vagrant box for testing various command configurations on multiple
different containers.
The reset of this section illustrates some examples for testing the
functionality of the login script manually. Adjust the ssh-config
for the
following example accordingly:
# propagete APPTAINER_CONTAINER to the server
echo " SendEnv=APPTAINER_CONTAINER" >> ssh-config
# change the SSH forwarding port (cf. Vagrantfile)
sed -i 's/22/23/' ssh-config
By default login launches a container specified with SSHD_CONTAINER_DEFAULT
:
# login into a containerized interactive shell
>>> ssh -F ssh-config vagrant@$box
Container launched: /tmp/debian10.sif
vagrant@centos7:~ >
# run a containerized command
>>> ssh -F ssh-config vagrant@$box -- /bin/ps -fH
UID PID PPID C STIME TTY TIME CMD
vagrant 2832 2829 0 06:01 ? 00:00:00 sshd: vagrant@notty
vagrant 2833 2832 0 06:01 ? 00:00:00 Singularity runtime parent
vagrant 2854 2833 0 06:01 ? 00:00:00 /bin/ps -fH
# test if stdin works as expected
>>> echo 1 2 3 4 | ssh -F ssh-config vagrant@$box -- cat
1 2 3 4
File transfer with scp
, rsync
and sftp
:
scp -d -F ssh-config vagrant@$box:/srv/dummy.txt /tmp
scp -d -F ssh-config /bin/bash vagrant@$box:/tmp
rsync -e 'ssh -F ssh-config' /bin/bash vagrant@$box:/tmp
rsync -e 'ssh -F ssh-config' vagrant@$box:/srv/dummy.txt /tmp
sftp -F ssh-config vagrant@$box:/srv/dummy.txt /tmp
sftp -F ssh-config vagrant@$box:/tmp <<< $'put /bin/bash'
Note that the container images require to have corresponding packages
installed cf. containers.sh
.
Users can specify a specific container with the variable APPTAINER_CONTAINER
:
>>> APPTAINER_CONTAINER=/tmp/centos7.sif \
ssh -F ssh-config -o SendEnv=APPTAINER_CONTAINER vagrant@$box
Container launched: /tmp/centos7.sif
vagrant@el7:~ >
Login into the host environment using APPTAINER_CONTAINER=none
:
>>> APPTAINER_CONTAINER=none ssh -F ssh-config vagrant@$box
[vagrant@el7 ~]$
APPTAINER_CONTAINER=menu
will present a list of available containers defined
in the sshd_container
configuration:
>>> APPTAINER_CONTAINER=menu ssh -F ssh-config vagrant@$box
Available containers
1) /tmp/debian10.sif
2) /tmp/centos7.sif
3) none
Select: 2
Container launched: /tmp/centos7.sif
vagrant@centos7:~ >