0
0
Fork 0
mirror of https://github.com/atmoz/sftp.git synced 2024-11-17 12:51:33 -05:00
atmoz-sftp/tests/run

390 lines
11 KiB
Text
Raw Normal View History

2015-11-23 07:39:17 -05:00
#!/bin/bash
# See: https://github.com/kward/shunit2
2024-07-12 17:25:23 -04:00
# Usage: tests/run [OPTION]... IMAGE_NAME
# Options: --verbose --no-cleanup
# Example: tests/run atmoz/sftp:alpine
# Booleans
OPTION_TRUE=0
OPTION_FALSE=1
# Options
OPTION_VERBOSE="${OPTION_VERBOSE:-"$OPTION_FALSE"}"
OPTION_CLEANUP="${OPTION_CLEANUP:-"$OPTION_TRUE"}"
# ARGUMENTS:
while [ "$#" -ge 1 ]; do
case "$1" in
--verbose) OPTION_VERBOSE="$OPTION_TRUE"; shift ;;
--no-cleanup) OPTION_VERBOSE="$OPTION_FALSE"; shift ;;
--) break ;; # rest of arguments goes to shunit2
--*) echo "Unknown argument: $1"; exit 2 ;;
*) imageName="$1"; shift ;;
esac
done
2015-11-23 07:39:17 -05:00
testDir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
2020-08-19 17:25:27 -04:00
tmpDir="$(mktemp -d /tmp/atmoz_sftp_XXXX)"
sshKeyPri="$tmpDir/rsa"
sshKeyPub="$tmpDir/rsa.pub"
sshHostEd25519Key="$tmpDir/ssh_host_ed25519_key"
sshHostKeyMountArg="--volume=$sshHostEd25519Key:/etc/ssh/ssh_host_ed25519_key"
sshKnownHosts="$tmpDir/known_hosts"
2024-07-12 17:25:23 -04:00
runArgs=("-P" "--network=private" "$sshHostKeyMountArg")
# podman or docker
if [ -z "$CONTAINER_ENGINE" ]; then
if type podman &>/dev/null; then
CONTAINER_ENGINE="podman"
else
CONTAINER_ENGINE="docker"
fi
2015-12-07 04:10:24 -05:00
fi
if [ ! -f "$testDir/shunit2/shunit2" ]; then
2024-07-12 17:25:23 -04:00
echo "Could not find shunit2 in $testDir/shunit2"
2020-07-16 19:29:36 -04:00
echo "Run 'git submodule update --init'"
exit 2
fi
2024-07-12 17:25:23 -04:00
if [ -z "$imageName" ]; then
echo "Missing name of image you want to run tests against"
exit 3
fi
2024-07-12 17:25:23 -04:00
if [ "$OPTION_VERBOSE" == "$OPTION_TRUE" ]; then
redirect="/dev/stdout"
2024-07-12 17:25:23 -04:00
else
redirect="/dev/null"
fi
##############################################################################
2024-07-12 17:25:23 -04:00
## Setup: shunit2 functions
2015-12-07 04:10:24 -05:00
##############################################################################
function oneTimeSetUp() {
# Generate temporary ssh keys for testing
2020-07-12 16:08:12 -04:00
if [ ! -f "$sshKeyPri" ]; then
2024-07-12 17:25:23 -04:00
ssh-keygen -t rsa -f "$sshKeyPri" -N '' < /dev/null > "$redirect" 2>&1
fi
# Private key can not be read by others (sshd will complain)
2020-07-12 16:08:12 -04:00
chmod go-rw "$sshKeyPri"
2020-08-19 17:25:27 -04:00
# Generate host key
2024-07-12 17:25:23 -04:00
ssh-keygen -t ed25519 -f "$sshHostEd25519Key" -N '' < /dev/null
2015-11-23 07:39:17 -05:00
}
function setUp() {
# shellcheck disable=SC2154
containerName="atmoz_sftp_${_shunit_test_}"
containerTmpDir="$(mktemp -d "/tmp/${containerName}_XXXX")"
export containerName containerTmpDir
retireContainer "$containerName" # clean up leftover container
}
function tearDown() {
retireContainer "$containerName"
2024-07-12 17:25:23 -04:00
if [ "$OPTION_CLEANUP" == "$OPTION_TRUE" ] && [ -d "$containerTmpDir" ]; then
2020-07-16 19:38:38 -04:00
rm -rf "$containerTmpDir" || true # Can fail on GitHub Actions
fi
}
2015-12-07 04:10:24 -05:00
2024-07-12 17:25:23 -04:00
##############################################################################
## Helper functions
##############################################################################
function container() {
"$CONTAINER_ENGINE" "$@"
}
function retireContainer() {
2024-07-12 17:25:23 -04:00
if [ "$(container ps -qaf name="$1")" ]; then
if [ "$OPTION_VERBOSE" == "$OPTION_TRUE" ]; then
echo "container log for $1:"
container logs "$1"
fi
2024-07-12 17:25:23 -04:00
if [ "$OPTION_CLEANUP" == "$OPTION_TRUE" ]; then
container rm -fv "$1" > "$redirect" 2>&1
fi
2015-12-07 04:10:24 -05:00
fi
2015-11-23 07:39:17 -05:00
}
2024-07-12 17:25:23 -04:00
function getSftpPort() {
container container port "$1" | cut -d: -f2 | head -1
2015-11-23 07:39:17 -05:00
}
function runSftpCommands() {
2024-07-12 17:25:23 -04:00
port="$(getSftpPort "$1")"
user="$2"
shift 2
2015-12-07 04:10:24 -05:00
2024-07-12 17:25:23 -04:00
echo "127.0.0.1 $(cat "$sshHostEd25519Key.pub")" >> "$sshKnownHosts"
2020-08-19 17:25:27 -04:00
2015-12-07 04:10:24 -05:00
commands=""
for cmd in "$@"; do
commands="$commands$cmd"$'\n'
done
echo "$commands" | sftp \
2020-07-12 16:08:12 -04:00
-i "$sshKeyPri" \
2020-08-19 17:25:27 -04:00
-oUserKnownHostsFile="$sshKnownHosts" \
2024-07-12 17:25:23 -04:00
-b - -P "$port" "$user@127.0.0.1" \
2015-12-07 04:10:24 -05:00
> "$redirect" 2>&1
2016-06-02 08:56:30 -04:00
status=$?
sleep 1 # wait for commands to finish
return $status
}
function waitForServer() {
2024-07-12 17:25:23 -04:00
local containerName="$1"
local port
echo -n "Waiting for $containerName to open a port ..."
for _ in {1..30}; do
echo -n "."
2024-07-12 17:25:23 -04:00
port="$(getSftpPort "$containerName")"
if [ -n "$port" ] && ssh-keyscan -4 -T 1 -p "$port" "127.0.0.1" &>/dev/null; then
echo " PORT $port OPEN"
return 0;
fi
2024-07-12 17:25:23 -04:00
sleep 0.5
done
echo " TIMEOUT"
return 1
2015-11-23 07:39:17 -05:00
}
##############################################################################
## Tests
2015-12-07 04:10:24 -05:00
##############################################################################
function testSmallestUserConfig() {
2024-07-12 17:25:23 -04:00
container run --name "$containerName" "${runArgs[@]}" \
--entrypoint="/bin/sh" \
"$imageName" \
-c "create-sftp-user u: && id u" \
> "$redirect" 2>&1
assertTrue "user created" $?
}
function testCreateUserWithDot() {
2024-07-12 17:25:23 -04:00
container run --name "$containerName" "${runArgs[@]}" \
--entrypoint="/bin/sh" \
"$imageName" \
-c "create-sftp-user user.with.dot: && id user.with.dot" \
> "$redirect" 2>&1
assertTrue "user created" $?
}
function testUserCustomUidAndGid() {
2024-07-12 17:25:23 -04:00
id="$(container run --name "$containerName" "${runArgs[@]}" \
--entrypoint="/bin/sh" \
"$imageName" \
-c "create-sftp-user u::1234:4321: > /dev/null && id u" )"
2017-06-25 09:16:41 -04:00
echo "$id" | grep -q 'uid=1234('
assertTrue "custom UID" $?
2017-06-25 09:16:41 -04:00
echo "$id" | grep -q 'gid=4321('
assertTrue "custom GID" $?
# Here we also check group name
assertEquals "uid=1234(u) gid=4321(group_4321) groups=4321(group_4321)" "$id"
}
function testCommandPassthrough() {
2024-07-12 17:25:23 -04:00
container run --name "$containerName" "${runArgs[@]}" \
"$imageName" test 1 -eq 1 \
> "$redirect" 2>&1
assertTrue "command passthrough" $?
}
function testUsersConf() {
2024-07-12 17:25:23 -04:00
container run --name "$containerName" "${runArgs[@]}" -d \
-v "$testDir/files/users.conf:/etc/sftp/users.conf:ro" \
"$imageName" \
> "$redirect" 2>&1
waitForServer "$containerName"
assertTrue "waitForServer" $?
2015-12-20 17:45:28 -05:00
2024-07-12 17:25:23 -04:00
container exec "$containerName" id user-from-conf > /dev/null
assertTrue "user-from-conf" $?
2015-12-20 17:45:28 -05:00
2024-07-12 17:25:23 -04:00
container exec "$containerName" id test > /dev/null
assertTrue "test" $?
2015-12-20 17:45:28 -05:00
2024-07-12 17:25:23 -04:00
container exec "$containerName" id user.with.dot > /dev/null
assertTrue "user.with.dot" $?
2024-07-12 17:25:23 -04:00
container exec "$containerName" test -d /home/test/dir1 -a -d /home/test/dir2
assertTrue "dirs exists" $?
}
2015-12-20 17:45:28 -05:00
function testLegacyUsersConf() {
2024-07-12 17:25:23 -04:00
container run --name "$containerName" "${runArgs[@]}" -d \
-v "$testDir/files/users.conf:/etc/sftp-users.conf:ro" \
"$imageName" \
> "$redirect" 2>&1
2015-12-20 17:45:28 -05:00
waitForServer "$containerName"
assertTrue "waitForServer" $?
2015-12-20 17:45:28 -05:00
2024-07-12 17:25:23 -04:00
container exec "$containerName" id user-from-conf > /dev/null
assertTrue "user-from-conf" $?
2015-12-20 17:45:28 -05:00
}
function testCreateUsersUsingEnv() {
2024-07-12 17:25:23 -04:00
container run --name "$containerName" "${runArgs[@]}" -d \
-e "SFTP_USERS=user-from-env: user-from-env-2:" \
"$imageName" \
> "$redirect" 2>&1
waitForServer "$containerName"
assertTrue "waitForServer" $?
2024-07-12 17:25:23 -04:00
container exec "$containerName" id user-from-env > /dev/null
assertTrue "user-from-env" $?
2024-07-12 17:25:23 -04:00
container exec "$containerName" id user-from-env-2 > /dev/null
assertTrue "user-from-env-2" $?
}
function testCreateUsersUsingCombo() {
2024-07-12 17:25:23 -04:00
container run --name "$containerName" "${runArgs[@]}" -d \
-v "$testDir/files/users.conf:/etc/sftp-users.conf:ro" \
-e "SFTP_USERS=user-from-env:" \
"$imageName" \
user-from-cmd: \
> "$redirect" 2>&1
waitForServer "$containerName"
assertTrue "waitForServer" $?
2024-07-12 17:25:23 -04:00
container exec "$containerName" id user-from-conf > /dev/null
assertTrue "user-from-conf" $?
2024-07-12 17:25:23 -04:00
container exec "$containerName" id user-from-env > /dev/null
assertTrue "user-from-env" $?
2024-07-12 17:25:23 -04:00
container exec "$containerName" id user-from-cmd > /dev/null
assertTrue "user-from-cmd" $?
}
function testWriteAccessToAutocreatedDirs() {
2024-07-12 17:25:23 -04:00
container run --name "$containerName" "${runArgs[@]}" -d \
2020-07-12 16:08:12 -04:00
-v "$sshKeyPub":/home/test/.ssh/keys/id_rsa.pub:ro \
2018-11-16 10:04:28 -05:00
"$imageName" "test::::testdir,dir with spaces" \
> "$redirect" 2>&1
waitForServer "$containerName"
assertTrue "waitForServer" $?
runSftpCommands "$containerName" "test" \
2018-11-16 10:04:28 -05:00
"cd testdir" \
"mkdir test" \
2018-11-16 10:04:28 -05:00
"cd '../dir with spaces'" \
"mkdir test" \
"exit"
assertTrue "runSftpCommands" $?
2024-07-12 17:25:23 -04:00
container exec "$containerName" test -d /home/test/testdir/test
2018-11-16 10:04:28 -05:00
assertTrue "testdir write access" $?
2024-07-12 17:25:23 -04:00
container exec "$containerName" test -d "/home/test/dir with spaces/test"
2018-11-16 10:04:28 -05:00
assertTrue "dir with spaces write access" $?
}
function testWriteAccessToLimitedChroot() {
# Modified sshd_config with chrooted home subdir
tmpConfig="$(mktemp)"
2024-07-12 17:25:23 -04:00
container run --rm --entrypoint=bash "$imageName" -c "cat /etc/ssh/sshd_config" |
sed 's/^ChrootDirectory.*/ChrootDirectory %h\/sftp/' \
> "$tmpConfig"
# Set correct permissions on chroot
tmpScript="$(mktemp)"
cat > "$tmpScript" <<EOF
mkdir -p /home/*/sftp
chown root:root /home/*/sftp
chmod 755 /home/*/sftp
EOF
chmod +x "$tmpScript"
2024-07-12 17:25:23 -04:00
container run --name "$containerName" "${runArgs[@]}" -d \
-v "$sshKeyPub":/home/test/.ssh/keys/id_rsa.pub:ro \
-v "$tmpConfig:/etc/ssh/sshd_config" \
-v "$tmpScript:/etc/sftp.d/limited_home_dir" \
"$imageName" "test::::sftp/upload" \
> "$redirect" 2>&1
waitForServer "$containerName"
assertTrue "waitForServer" $?
runSftpCommands "$containerName" "test" \
"cd upload" \
"mkdir test" \
"exit"
assertTrue "runSftpCommands" $?
2024-07-12 17:25:23 -04:00
container exec "$containerName" test -d /home/test/sftp/upload/test
assertTrue "limited chroot write access" $?
}
function testBindmountDirScript() {
mkdir -p "$containerTmpDir/custom/bindmount"
echo "mkdir -p /home/custom/bindmount && \
chown custom /custom /home/custom/bindmount && \
mount --bind /custom /home/custom/bindmount" \
> "$containerTmpDir/mount.sh"
chmod +x "$containerTmpDir/mount.sh"
2024-07-12 17:25:23 -04:00
container run --name "$containerName" "${runArgs[@]}" -d \
--privileged=true \
2020-07-12 16:08:12 -04:00
-v "$sshKeyPub":/home/custom/.ssh/keys/id_rsa.pub:ro \
-v "$containerTmpDir/custom/bindmount":/custom \
-v "$containerTmpDir/mount.sh":/etc/sftp.d/mount.sh \
"$imageName" custom:123 \
> "$redirect" 2>&1
waitForServer "$containerName"
assertTrue "waitForServer" $?
runSftpCommands "$containerName" "custom" \
"cd bindmount" \
"mkdir test" \
"exit"
assertTrue "runSftpCommands" $?
2024-07-12 17:25:23 -04:00
container exec "$containerName" test -d /home/custom/bindmount/test
assertTrue "directory exist" $?
}
2020-07-12 16:08:12 -04:00
function testDuplicateSshKeys() {
2024-07-12 17:25:23 -04:00
container run --name "$containerName" "${runArgs[@]}" -d \
2020-07-12 16:08:12 -04:00
-v "$sshKeyPub":/home/user/.ssh/keys/key1.pub:ro \
-v "$sshKeyPub":/home/user/.ssh/keys/key2.pub:ro \
"$imageName" "user:" \
> "$redirect" 2>&1
waitForServer "$containerName"
assertTrue "waitForServer" $?
2024-07-12 17:25:23 -04:00
lines="$(container exec "$containerName" sh -c \
2020-07-12 16:08:12 -04:00
"wc -l < /home/user/.ssh/authorized_keys")"
assertEquals "1" "$lines"
}
##############################################################################
## Run
2015-12-07 04:10:24 -05:00
##############################################################################
2021-05-15 14:59:49 -04:00
# shellcheck disable=SC1091
source "$testDir/shunit2/shunit2"
2015-11-23 07:39:17 -05:00
# Nothing happens after this