2015-11-23 07:39:17 -05:00
|
|
|
#!/bin/bash
|
2018-11-15 18:57:33 -05:00
|
|
|
# See: https://github.com/kward/shunit2
|
2015-11-23 07:39:17 -05:00
|
|
|
|
2018-11-15 18:57:33 -05:00
|
|
|
if [ $UID != 0 ] && ! groups | grep -qw docker; then
|
|
|
|
echo "Run with sudo/root or add user $USER to group 'docker'"
|
|
|
|
exit 1
|
|
|
|
fi
|
2017-06-05 07:30:16 -04:00
|
|
|
|
2018-11-15 18:57:33 -05:00
|
|
|
argBuild=${1:-"build"}
|
|
|
|
argOutput=${2:-"quiet"}
|
|
|
|
argCleanup=${3:-"cleanup"}
|
|
|
|
testDir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
|
|
|
buildDir="$testDir/.."
|
|
|
|
imageName="atmoz/sftp_test"
|
|
|
|
buildOptions=(--tag "$imageName")
|
2020-07-12 16:08:12 -04:00
|
|
|
sshKeyPri="/tmp/atmoz_sftp_test_rsa"
|
|
|
|
sshKeyPub="/tmp/atmoz_sftp_test_rsa.pub"
|
2015-11-23 07:39:17 -05:00
|
|
|
|
2018-11-15 18:57:33 -05:00
|
|
|
if [ "$argOutput" == "quiet" ]; then
|
2015-12-07 04:10:24 -05:00
|
|
|
redirect="/dev/null"
|
|
|
|
else
|
2015-12-16 05:54:57 -05:00
|
|
|
redirect="/dev/stdout"
|
2015-12-07 04:10:24 -05:00
|
|
|
fi
|
|
|
|
|
2018-11-15 18:57:33 -05:00
|
|
|
if [ ! -f "$testDir/shunit2/shunit2" ]; then
|
|
|
|
echo "Could not find shunit2 in $testDir/shunit2."
|
|
|
|
echo "Run 'git submodules init && git submodules update'"
|
|
|
|
exit 2
|
|
|
|
fi
|
|
|
|
|
|
|
|
# clear argument list (or shunit2 will try to use them)
|
|
|
|
set --
|
2016-09-26 14:13:53 -04:00
|
|
|
|
2018-11-15 18:57:33 -05:00
|
|
|
##############################################################################
|
|
|
|
## Helper functions
|
2015-12-07 04:10:24 -05:00
|
|
|
##############################################################################
|
|
|
|
|
2018-11-15 18:57:33 -05:00
|
|
|
function oneTimeSetUp() {
|
|
|
|
if [ "$argBuild" == "build" ]; then
|
|
|
|
buildOptions+=("--no-cache" "--pull=true")
|
2016-09-26 14:13:53 -04:00
|
|
|
fi
|
|
|
|
|
2018-11-15 18:57:33 -05:00
|
|
|
# Build image
|
|
|
|
if ! docker build "${buildOptions[@]}" "$buildDir"; then
|
2016-09-26 14:13:53 -04:00
|
|
|
echo "Build failed"
|
|
|
|
exit 1
|
2015-11-23 07:39:17 -05:00
|
|
|
fi
|
|
|
|
|
2018-11-15 18:57:33 -05:00
|
|
|
# Generate temporary ssh keys for testing
|
2020-07-12 16:08:12 -04:00
|
|
|
if [ ! -f "$sshKeyPri" ]; then
|
|
|
|
ssh-keygen -t rsa -f "$sshKeyPri" -N '' > "$redirect" 2>&1
|
2018-11-15 18:57:33 -05:00
|
|
|
fi
|
|
|
|
|
|
|
|
# Private key can not be read by others (sshd will complain)
|
2020-07-12 16:08:12 -04:00
|
|
|
chmod go-rw "$sshKeyPri"
|
2015-11-23 07:39:17 -05:00
|
|
|
}
|
|
|
|
|
2018-11-15 18:57:33 -05:00
|
|
|
function oneTimeTearDown() {
|
|
|
|
if [ "$argCleanup" == "cleanup" ]; then
|
|
|
|
docker image rm "$imageName" > "$redirect" 2>&1
|
2015-12-07 04:10:24 -05:00
|
|
|
fi
|
2018-11-15 18:57:33 -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"
|
|
|
|
|
|
|
|
if [ "$argCleanup" == "cleanup" ] && [ -d "$containerTmpDir" ]; then
|
|
|
|
rm -rf "$containerTmpDir"
|
|
|
|
fi
|
|
|
|
}
|
2015-12-07 04:10:24 -05:00
|
|
|
|
2018-11-15 18:57:33 -05:00
|
|
|
function retireContainer() {
|
|
|
|
if [ "$(docker ps -qaf name="$1")" ]; then
|
|
|
|
if [ "$argOutput" != "quiet" ]; then
|
|
|
|
echo "Docker log for $1:"
|
|
|
|
docker logs "$1"
|
|
|
|
fi
|
|
|
|
|
|
|
|
if [ "$argCleanup" == "cleanup" ]; then
|
|
|
|
docker rm -fv "$1" > "$redirect" 2>&1
|
|
|
|
fi
|
2015-12-07 04:10:24 -05:00
|
|
|
fi
|
2015-11-23 07:39:17 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
function getSftpIp() {
|
2018-11-15 18:57:33 -05:00
|
|
|
docker inspect -f "{{.NetworkSettings.IPAddress}}" "$1"
|
2015-11-23 07:39:17 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
function runSftpCommands() {
|
2018-11-15 18:57:33 -05:00
|
|
|
ip="$(getSftpIp "$1")"
|
2016-03-17 16:27:41 -04:00
|
|
|
user="$2"
|
|
|
|
shift 2
|
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" \
|
2015-11-23 07:39:17 -05:00
|
|
|
-oStrictHostKeyChecking=no \
|
|
|
|
-oUserKnownHostsFile=/dev/null \
|
2018-11-15 18:57:33 -05:00
|
|
|
-b - "$user@$ip" \
|
2015-12-07 04:10:24 -05:00
|
|
|
> "$redirect" 2>&1
|
2016-06-02 08:56:30 -04:00
|
|
|
|
2017-06-05 07:30:16 -04:00
|
|
|
status=$?
|
|
|
|
sleep 1 # wait for commands to finish
|
|
|
|
return $status
|
|
|
|
}
|
|
|
|
|
|
|
|
function waitForServer() {
|
|
|
|
containerName="$1"
|
2017-06-25 08:05:22 -04:00
|
|
|
echo -n "Waiting for $containerName to open port 22 ..."
|
2017-06-05 07:30:16 -04:00
|
|
|
|
2018-11-15 18:57:33 -05:00
|
|
|
for _ in {1..30}; do
|
2017-06-05 07:30:16 -04:00
|
|
|
sleep 1
|
2018-11-15 18:57:33 -05:00
|
|
|
ip="$(getSftpIp "$containerName")"
|
2017-06-05 07:30:16 -04:00
|
|
|
echo -n "."
|
2018-11-15 18:57:33 -05:00
|
|
|
if [ -n "$ip" ] && nc -z "$ip" 22; then
|
2017-06-25 08:05:22 -04:00
|
|
|
echo " OPEN"
|
2017-06-05 07:30:16 -04:00
|
|
|
return 0;
|
|
|
|
fi
|
|
|
|
done
|
|
|
|
|
2017-06-25 08:05:22 -04:00
|
|
|
echo " TIMEOUT"
|
2017-06-05 07:30:16 -04:00
|
|
|
return 1
|
2015-11-23 07:39:17 -05:00
|
|
|
}
|
|
|
|
|
2018-11-15 18:57:33 -05:00
|
|
|
##############################################################################
|
|
|
|
## Tests
|
2015-12-07 04:10:24 -05:00
|
|
|
##############################################################################
|
|
|
|
|
2018-11-15 18:57:33 -05:00
|
|
|
function testSmallestUserConfig() {
|
|
|
|
docker run --name "$containerName" \
|
|
|
|
--entrypoint="/bin/sh" \
|
|
|
|
"$imageName" \
|
|
|
|
-c "create-sftp-user u: && id u" \
|
|
|
|
> "$redirect" 2>&1
|
|
|
|
assertTrue "user created" $?
|
2016-08-12 10:21:07 -04:00
|
|
|
}
|
|
|
|
|
2018-11-15 18:57:33 -05:00
|
|
|
function testCreateUserWithDot() {
|
|
|
|
docker run --name "$containerName" \
|
|
|
|
--entrypoint="/bin/sh" \
|
|
|
|
"$imageName" \
|
|
|
|
-c "create-sftp-user user.with.dot: && id user.with.dot" \
|
|
|
|
> "$redirect" 2>&1
|
|
|
|
assertTrue "user created" $?
|
2016-08-12 10:21:07 -04:00
|
|
|
}
|
|
|
|
|
2018-11-15 18:57:33 -05:00
|
|
|
function testUserCustomUidAndGid() {
|
|
|
|
id="$(docker run --name "$containerName" \
|
|
|
|
--entrypoint="/bin/sh" \
|
|
|
|
"$imageName" \
|
|
|
|
-c "create-sftp-user u::1234:4321: > /dev/null && id u" )"
|
2017-06-25 09:16:41 -04:00
|
|
|
|
2018-11-15 18:57:33 -05:00
|
|
|
echo "$id" | grep -q 'uid=1234('
|
|
|
|
assertTrue "custom UID" $?
|
2017-06-25 09:16:41 -04:00
|
|
|
|
2018-11-15 18:57:33 -05:00
|
|
|
echo "$id" | grep -q 'gid=4321('
|
|
|
|
assertTrue "custom GID" $?
|
2018-01-04 13:32:05 -05:00
|
|
|
|
2018-11-15 18:57:33 -05:00
|
|
|
# Here we also check group name
|
|
|
|
assertEquals "uid=1234(u) gid=4321(group_4321) groups=4321(group_4321)" "$id"
|
2018-01-04 13:32:05 -05:00
|
|
|
}
|
|
|
|
|
2018-11-15 18:57:33 -05:00
|
|
|
function testCommandPassthrough() {
|
|
|
|
docker run --name "$containerName" \
|
|
|
|
"$imageName" test 1 -eq 1 \
|
|
|
|
> "$redirect" 2>&1
|
|
|
|
assertTrue "command passthrough" $?
|
2016-08-12 10:21:07 -04:00
|
|
|
}
|
|
|
|
|
2018-11-15 18:57:33 -05:00
|
|
|
function testUsersConf() {
|
|
|
|
docker run --name "$containerName" -d \
|
|
|
|
-v "$testDir/files/users.conf:/etc/sftp/users.conf:ro" \
|
|
|
|
"$imageName" \
|
|
|
|
> "$redirect" 2>&1
|
2016-08-12 10:21:07 -04:00
|
|
|
|
2018-11-15 18:57:33 -05:00
|
|
|
waitForServer "$containerName"
|
|
|
|
assertTrue "waitForServer" $?
|
2015-12-20 17:45:28 -05:00
|
|
|
|
2018-11-15 18:57:33 -05:00
|
|
|
docker exec "$containerName" id user-from-conf > /dev/null
|
|
|
|
assertTrue "user-from-conf" $?
|
2015-12-20 17:45:28 -05:00
|
|
|
|
2018-11-15 18:57:33 -05:00
|
|
|
docker exec "$containerName" id test > /dev/null
|
|
|
|
assertTrue "test" $?
|
2015-12-20 17:45:28 -05:00
|
|
|
|
2018-11-15 18:57:33 -05:00
|
|
|
docker exec "$containerName" id user.with.dot > /dev/null
|
|
|
|
assertTrue "user.with.dot" $?
|
2017-06-05 07:30:16 -04:00
|
|
|
|
2018-11-15 18:57:33 -05:00
|
|
|
docker exec "$containerName" test -d /home/test/dir1 -a -d /home/test/dir2
|
|
|
|
assertTrue "dirs exists" $?
|
|
|
|
}
|
2015-12-20 17:45:28 -05:00
|
|
|
|
2018-11-15 18:57:33 -05:00
|
|
|
function testLegacyUsersConf() {
|
|
|
|
docker run --name "$containerName" -d \
|
|
|
|
-v "$testDir/files/users.conf:/etc/sftp-users.conf:ro" \
|
|
|
|
"$imageName" \
|
|
|
|
> "$redirect" 2>&1
|
2015-12-20 17:45:28 -05:00
|
|
|
|
2018-11-15 18:57:33 -05:00
|
|
|
waitForServer "$containerName"
|
|
|
|
assertTrue "waitForServer" $?
|
2015-12-20 17:45:28 -05:00
|
|
|
|
2018-11-15 18:57:33 -05:00
|
|
|
docker exec "$containerName" id user-from-conf > /dev/null
|
|
|
|
assertTrue "user-from-conf" $?
|
2015-12-20 17:45:28 -05:00
|
|
|
}
|
|
|
|
|
2018-11-15 18:57:33 -05:00
|
|
|
function testCreateUsersUsingEnv() {
|
|
|
|
docker run --name "$containerName" -d \
|
|
|
|
-e "SFTP_USERS=user-from-env: user-from-env-2:" \
|
|
|
|
"$imageName" \
|
|
|
|
> "$redirect" 2>&1
|
|
|
|
|
|
|
|
waitForServer "$containerName"
|
|
|
|
assertTrue "waitForServer" $?
|
2017-06-25 08:05:22 -04:00
|
|
|
|
2018-11-15 18:57:33 -05:00
|
|
|
docker exec "$containerName" id user-from-env > /dev/null
|
|
|
|
assertTrue "user-from-env" $?
|
2017-06-25 08:05:22 -04:00
|
|
|
|
2018-11-15 18:57:33 -05:00
|
|
|
docker exec "$containerName" id user-from-env-2 > /dev/null
|
|
|
|
assertTrue "user-from-env-2" $?
|
|
|
|
}
|
2017-06-25 08:05:22 -04:00
|
|
|
|
2018-11-15 18:57:33 -05:00
|
|
|
function testCreateUsersUsingCombo() {
|
|
|
|
docker run --name "$containerName" -d \
|
|
|
|
-v "$testDir/files/users.conf:/etc/sftp-users.conf:ro" \
|
|
|
|
-e "SFTP_USERS=user-from-env:" \
|
|
|
|
"$imageName" \
|
|
|
|
user-from-cmd: \
|
|
|
|
> "$redirect" 2>&1
|
2017-06-25 08:05:22 -04:00
|
|
|
|
2018-11-15 18:57:33 -05:00
|
|
|
waitForServer "$containerName"
|
|
|
|
assertTrue "waitForServer" $?
|
2017-06-25 08:05:22 -04:00
|
|
|
|
2018-11-15 18:57:33 -05:00
|
|
|
docker exec "$containerName" id user-from-conf > /dev/null
|
|
|
|
assertTrue "user-from-conf" $?
|
2017-06-25 08:05:22 -04:00
|
|
|
|
2018-11-15 18:57:33 -05:00
|
|
|
docker exec "$containerName" id user-from-env > /dev/null
|
|
|
|
assertTrue "user-from-env" $?
|
|
|
|
|
|
|
|
docker exec "$containerName" id user-from-cmd > /dev/null
|
|
|
|
assertTrue "user-from-cmd" $?
|
2017-06-25 08:05:22 -04:00
|
|
|
}
|
|
|
|
|
2018-11-15 18:57:33 -05:00
|
|
|
function testWriteAccessToAutocreatedDirs() {
|
|
|
|
docker run --name "$containerName" -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" \
|
2018-11-15 18:57:33 -05:00
|
|
|
> "$redirect" 2>&1
|
|
|
|
|
|
|
|
waitForServer "$containerName"
|
|
|
|
assertTrue "waitForServer" $?
|
2017-06-25 08:05:22 -04:00
|
|
|
|
2018-11-15 18:57:33 -05:00
|
|
|
runSftpCommands "$containerName" "test" \
|
2018-11-16 10:04:28 -05:00
|
|
|
"cd testdir" \
|
2018-11-15 18:57:33 -05:00
|
|
|
"mkdir test" \
|
2018-11-16 10:04:28 -05:00
|
|
|
"cd '../dir with spaces'" \
|
2018-11-15 18:57:33 -05:00
|
|
|
"mkdir test" \
|
|
|
|
"exit"
|
|
|
|
assertTrue "runSftpCommands" $?
|
2016-03-17 16:27:41 -04:00
|
|
|
|
2018-11-16 10:04:28 -05:00
|
|
|
docker exec "$containerName" test -d /home/test/testdir/test
|
|
|
|
assertTrue "testdir write access" $?
|
|
|
|
|
|
|
|
docker exec "$containerName" test -d "/home/test/dir with spaces/test"
|
|
|
|
assertTrue "dir with spaces write access" $?
|
2018-11-15 18:57:33 -05:00
|
|
|
}
|
2016-03-17 16:27:41 -04:00
|
|
|
|
2018-11-15 18:57:33 -05:00
|
|
|
function testBindmountDirScript() {
|
|
|
|
mkdir -p "$containerTmpDir/custom/bindmount"
|
2016-03-17 16:27:41 -04:00
|
|
|
echo "mkdir -p /home/custom/bindmount && \
|
2018-11-15 18:57:33 -05:00
|
|
|
chown custom /custom /home/custom/bindmount && \
|
2016-03-17 16:27:41 -04:00
|
|
|
mount --bind /custom /home/custom/bindmount" \
|
2018-11-15 18:57:33 -05:00
|
|
|
> "$containerTmpDir/mount.sh"
|
|
|
|
chmod +x "$containerTmpDir/mount.sh"
|
2016-03-17 16:27:41 -04:00
|
|
|
|
2018-11-15 18:57:33 -05:00
|
|
|
docker run --name "$containerName" -d \
|
2016-03-17 16:27:41 -04:00
|
|
|
--privileged=true \
|
2020-07-12 16:08:12 -04:00
|
|
|
-v "$sshKeyPub":/home/custom/.ssh/keys/id_rsa.pub:ro \
|
2018-11-15 18:57:33 -05:00
|
|
|
-v "$containerTmpDir/custom/bindmount":/custom \
|
|
|
|
-v "$containerTmpDir/mount.sh":/etc/sftp.d/mount.sh \
|
|
|
|
"$imageName" custom:123 \
|
|
|
|
> "$redirect" 2>&1
|
2017-06-05 07:30:16 -04:00
|
|
|
|
2018-11-15 18:57:33 -05:00
|
|
|
waitForServer "$containerName"
|
|
|
|
assertTrue "waitForServer" $?
|
2016-03-17 16:27:41 -04:00
|
|
|
|
2018-11-15 18:57:33 -05:00
|
|
|
runSftpCommands "$containerName" "custom" \
|
2017-06-05 07:30:16 -04:00
|
|
|
"cd bindmount" \
|
|
|
|
"mkdir test" \
|
|
|
|
"exit"
|
2018-11-15 18:57:33 -05:00
|
|
|
assertTrue "runSftpCommands" $?
|
2017-06-05 07:30:16 -04:00
|
|
|
|
2018-11-15 18:57:33 -05:00
|
|
|
docker exec "$containerName" test -d /home/custom/bindmount/test
|
|
|
|
assertTrue "directory exist" $?
|
2016-03-17 16:27:41 -04:00
|
|
|
}
|
|
|
|
|
2020-07-12 16:08:12 -04:00
|
|
|
function testDuplicateSshKeys() {
|
|
|
|
docker run --name "$containerName" -d \
|
|
|
|
-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" $?
|
|
|
|
|
|
|
|
lines="$(docker exec "$containerName" sh -c \
|
|
|
|
"wc -l < /home/user/.ssh/authorized_keys")"
|
|
|
|
assertEquals "1" "$lines"
|
|
|
|
}
|
|
|
|
|
2018-11-15 18:57:33 -05:00
|
|
|
##############################################################################
|
|
|
|
## Run
|
2015-12-07 04:10:24 -05:00
|
|
|
##############################################################################
|
|
|
|
|
2018-11-15 18:57:33 -05:00
|
|
|
# shellcheck disable=SC1090
|
|
|
|
source "$testDir/shunit2/shunit2"
|
2015-11-23 07:39:17 -05:00
|
|
|
# Nothing happens after this
|