mirror of
https://github.com/atmoz/sftp.git
synced 2024-11-17 12:51:33 -05:00
Add users from STDIN or config file
This commit is contained in:
parent
bd37434f5c
commit
8d310f3af0
3 changed files with 87 additions and 24 deletions
22
README.md
22
README.md
|
@ -6,8 +6,8 @@ Easy to use SFTP ([SSH File Transfer Protocol](https://en.wikipedia.org/wiki/SSH
|
||||||
Usage
|
Usage
|
||||||
-----
|
-----
|
||||||
|
|
||||||
- Define users as last arguments to `docker run`, one user per argument
|
- Define users as command arguments, STDIN or mounted in /etc/sftp-users.conf
|
||||||
(syntax: `user:pass[:e][:[uid][:gid]]`).
|
(syntax: `user:pass[:e][:uid[:gid]]...`).
|
||||||
- You must set custom UID for your users if you want them to make changes to
|
- You must set custom UID for your users if you want them to make changes to
|
||||||
your mounted volumes with permissions matching your host filesystem.
|
your mounted volumes with permissions matching your host filesystem.
|
||||||
- Mount volumes in user's home folder.
|
- Mount volumes in user's home folder.
|
||||||
|
@ -18,7 +18,7 @@ Usage
|
||||||
Examples
|
Examples
|
||||||
--------
|
--------
|
||||||
|
|
||||||
### Single user and volume
|
### Simple example
|
||||||
|
|
||||||
```
|
```
|
||||||
docker run \
|
docker run \
|
||||||
|
@ -45,16 +45,22 @@ The OpenSSH server runs by default on port 22, and in this example, we are
|
||||||
forwarding the container's port 22 to the host's port 2222. To log in with an
|
forwarding the container's port 22 to the host's port 2222. To log in with an
|
||||||
OpenSSH client, run: `sftp -P 2222 foo@<host-ip>`
|
OpenSSH client, run: `sftp -P 2222 foo@<host-ip>`
|
||||||
|
|
||||||
### Multiple users and volumes
|
### Store users in config
|
||||||
|
|
||||||
|
/host/users.conf:
|
||||||
|
|
||||||
|
```
|
||||||
|
foo:123:1001
|
||||||
|
bar:abc:1002
|
||||||
|
```
|
||||||
|
|
||||||
```
|
```
|
||||||
docker run \
|
docker run \
|
||||||
|
-v /host/users.conf:/etc/sftp-users.conf:ro \
|
||||||
-v /host/share:/home/foo/share \
|
-v /host/share:/home/foo/share \
|
||||||
-v /host/documents:/home/foo/documents \
|
-v /host/documents:/home/foo/documents \
|
||||||
-v /host/http:/home/bar/http \
|
-v /host/http:/home/bar/http \
|
||||||
-p 2222:22 -d atmoz/sftp \
|
-p 2222:22 -d atmoz/sftp
|
||||||
foo:123:1001 \
|
|
||||||
bar:abc:1002
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### Encrypted password
|
### Encrypted password
|
||||||
|
@ -69,7 +75,7 @@ docker run \
|
||||||
```
|
```
|
||||||
|
|
||||||
Tip: you can use makepasswd to generate encrypted passwords:
|
Tip: you can use makepasswd to generate encrypted passwords:
|
||||||
`echo -n 123 | makepasswd --crypt-md5 --clearfrom -`
|
`echo -n "password" | makepasswd --crypt-md5 --clearfrom -`
|
||||||
|
|
||||||
### Using SSH key (without password)
|
### Using SSH key (without password)
|
||||||
|
|
||||||
|
|
44
entrypoint
44
entrypoint
|
@ -1,12 +1,17 @@
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
|
userConfPath="/etc/sftp-users.conf"
|
||||||
|
userConfFinalPath="/var/run/sftp-users.conf"
|
||||||
|
|
||||||
function printHelp() {
|
function printHelp() {
|
||||||
echo "Syntax: user:pass[:e][:[uid][:gid]]..."
|
echo "Add users as command arguments, STDIN or mounted in $userConfPath"
|
||||||
echo "Use --readme for information and examples."
|
echo "Syntax: user:pass[:e][:uid[:gid]]..."
|
||||||
|
echo "Use --readme for more information and examples."
|
||||||
}
|
}
|
||||||
|
|
||||||
function printReadme() {
|
function printReadme() {
|
||||||
cat /README.md
|
cat /README.md
|
||||||
|
echo "TIP: Read this in HTML format here: https://github.com/atmoz/sftp"
|
||||||
}
|
}
|
||||||
|
|
||||||
function createUser() {
|
function createUser() {
|
||||||
|
@ -14,8 +19,8 @@ function createUser() {
|
||||||
user="${param[0]}"
|
user="${param[0]}"
|
||||||
pass="${param[1]}"
|
pass="${param[1]}"
|
||||||
|
|
||||||
if [ -z "$user" -o -z "$pass" ]; then
|
if [ -z "$user" ]; then
|
||||||
echo "You must at least provide a username and a password."
|
echo "You must at least provide a username."
|
||||||
printHelp
|
printHelp
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
@ -29,7 +34,7 @@ function createUser() {
|
||||||
gid="${param[3]}"
|
gid="${param[3]}"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
useraddOptions="--create-home --no-user-group"
|
useraddOptions="--no-user-group"
|
||||||
|
|
||||||
if [ -n "$uid" ]; then
|
if [ -n "$uid" ]; then
|
||||||
useraddOptions="$useraddOptions --non-unique --uid $uid"
|
useraddOptions="$useraddOptions --non-unique --uid $uid"
|
||||||
|
@ -37,8 +42,11 @@ function createUser() {
|
||||||
|
|
||||||
if [ -n "$gid" ]; then
|
if [ -n "$gid" ]; then
|
||||||
useraddOptions="$useraddOptions --gid $gid"
|
useraddOptions="$useraddOptions --gid $gid"
|
||||||
|
|
||||||
|
if [ "$(cat /etc/group | cut -d : -f3 | grep -q "$gid")" ]; then
|
||||||
groupadd --gid $gid $gid
|
groupadd --gid $gid $gid
|
||||||
fi
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
useradd $useraddOptions $user
|
useradd $useraddOptions $user
|
||||||
chown root:root /home/$user
|
chown root:root /home/$user
|
||||||
|
@ -56,7 +64,7 @@ function createUser() {
|
||||||
chmod 600 /home/$user/.ssh/authorized_keys
|
chmod 600 /home/$user/.ssh/authorized_keys
|
||||||
}
|
}
|
||||||
|
|
||||||
if [[ -z $1 || $1 =~ ^--help$|^-h$ ]]; then
|
if [[ $1 =~ ^--help$|^-h$ ]]; then
|
||||||
printHelp
|
printHelp
|
||||||
exit 0
|
exit 0
|
||||||
fi
|
fi
|
||||||
|
@ -66,8 +74,30 @@ if [ "$1" == "--readme" ]; then
|
||||||
exit 0
|
exit 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Append mounted config to final config
|
||||||
|
if [ -f "$userConfPath" ]; then
|
||||||
|
cat "$userConfPath" >> "$userConfFinalPath"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Append users from arguments to final config
|
||||||
for user in "$@"; do
|
for user in "$@"; do
|
||||||
createUser $user
|
echo "$user" >> "$userConfFinalPath"
|
||||||
done
|
done
|
||||||
|
|
||||||
|
# Append users from STDIN to final config
|
||||||
|
while IFS= read -r user || [[ -n "$user" ]]; do
|
||||||
|
echo "$user" >> "$userConfFinalPath"
|
||||||
|
done
|
||||||
|
|
||||||
|
if [ ! -f "$userConfFinalPath" ]; then
|
||||||
|
echo "ERROR: Missing users!"
|
||||||
|
printHelp
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Import users from final conf file
|
||||||
|
while IFS= read -r user || [[ -n "$user" ]]; do
|
||||||
|
createUser "$user";
|
||||||
|
done < "$userConfFinalPath"
|
||||||
|
|
||||||
exec /usr/sbin/sshd -D
|
exec /usr/sbin/sshd -D
|
||||||
|
|
39
tests/run
39
tests/run
|
@ -6,9 +6,19 @@ buildDir="$scriptDir/.."
|
||||||
tmpDir="/tmp/atmoz_sftp_test"
|
tmpDir="/tmp/atmoz_sftp_test"
|
||||||
|
|
||||||
build=${1:-"build"}
|
build=${1:-"build"}
|
||||||
|
output=${2:-"quiet"}
|
||||||
|
cleanup=${3:-"cleanup"}
|
||||||
sftpImageName="atmoz/sftp_test"
|
sftpImageName="atmoz/sftp_test"
|
||||||
sftpContainerName="atmoz_sftp_test"
|
sftpContainerName="atmoz_sftp_test"
|
||||||
|
|
||||||
|
if [ "$output" == "quiet" ]; then
|
||||||
|
redirect="/dev/null"
|
||||||
|
else
|
||||||
|
redirect=$'&1'
|
||||||
|
fi
|
||||||
|
|
||||||
|
##############################################################################
|
||||||
|
|
||||||
function beforeTest() {
|
function beforeTest() {
|
||||||
if [ "$build" == "build" ]; then
|
if [ "$build" == "build" ]; then
|
||||||
docker build --pull=true --tag "$sftpImageName" "$buildDir"
|
docker build --pull=true --tag "$sftpImageName" "$buildDir"
|
||||||
|
@ -20,20 +30,27 @@ function beforeTest() {
|
||||||
rm -rf "$tmpDir" # clean state
|
rm -rf "$tmpDir" # clean state
|
||||||
mkdir "$tmpDir"
|
mkdir "$tmpDir"
|
||||||
|
|
||||||
|
echo "test::$(id -u):$(id -g)" >> "$tmpDir/users"
|
||||||
docker run \
|
docker run \
|
||||||
|
-v "$tmpDir/users:/etc/sftp-users.conf:ro" \
|
||||||
-v "$scriptDir/id_rsa.pub":/home/test/.ssh/keys/id_rsa.pub:ro \
|
-v "$scriptDir/id_rsa.pub":/home/test/.ssh/keys/id_rsa.pub:ro \
|
||||||
-v "$tmpDir":/home/test/share \
|
-v "$tmpDir":/home/test/share \
|
||||||
--name "$sftpContainerName" \
|
--name "$sftpContainerName" \
|
||||||
--expose 22 \
|
--expose 22 \
|
||||||
-d "$sftpImageName" \
|
-d "$sftpImageName" \
|
||||||
test:123:$(id -u):$(id -g) \
|
> "$redirect"
|
||||||
> /dev/null
|
|
||||||
sleep 1 # wait for sftp server to get ready
|
sleep 1 # wait for sftp server to get ready
|
||||||
}
|
}
|
||||||
|
|
||||||
function afterTest() {
|
function afterTest() {
|
||||||
docker rm -fv "$sftpContainerName" > /dev/null
|
if [ "$output" != "quiet" ]; then
|
||||||
|
docker logs "$sftpContainerName"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$cleanup" == "cleanup" ]; then
|
||||||
|
docker rm -fv "$sftpContainerName" > "$redirect"
|
||||||
rm -rf "$tmpDir"
|
rm -rf "$tmpDir"
|
||||||
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
function getSftpIp() {
|
function getSftpIp() {
|
||||||
|
@ -42,14 +59,22 @@ function getSftpIp() {
|
||||||
|
|
||||||
function runSftpCommands() {
|
function runSftpCommands() {
|
||||||
ip="$(getSftpIp)"
|
ip="$(getSftpIp)"
|
||||||
echo "$@" | sftp \
|
|
||||||
|
commands=""
|
||||||
|
for cmd in "$@"; do
|
||||||
|
commands="$commands$cmd"$'\n'
|
||||||
|
done
|
||||||
|
|
||||||
|
echo "$commands" | sftp \
|
||||||
-i "$scriptDir/id_rsa" \
|
-i "$scriptDir/id_rsa" \
|
||||||
-oStrictHostKeyChecking=no \
|
-oStrictHostKeyChecking=no \
|
||||||
-oUserKnownHostsFile=/dev/null \
|
-oUserKnownHostsFile=/dev/null \
|
||||||
-b - test@$ip \
|
-b - test@$ip \
|
||||||
> /dev/null 2>&1
|
> "$redirect" 2>&1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
##############################################################################
|
||||||
|
|
||||||
function testContainerIsRunning() {
|
function testContainerIsRunning() {
|
||||||
ps="$(docker ps -q -f name="$sftpContainerName")"
|
ps="$(docker ps -q -f name="$sftpContainerName")"
|
||||||
assertNotEqual "$ps" ""
|
assertNotEqual "$ps" ""
|
||||||
|
@ -61,11 +86,13 @@ function testLoginUsingSshKey() {
|
||||||
}
|
}
|
||||||
|
|
||||||
function testWritePermission() {
|
function testWritePermission() {
|
||||||
runSftpCommands $'cd share\nmkdir test'
|
runSftpCommands "cd share" "mkdir test" "exit"
|
||||||
test -d "$tmpDir/test"
|
test -d "$tmpDir/test"
|
||||||
assertReturn $? 0
|
assertReturn $? 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
##############################################################################
|
||||||
|
|
||||||
# Run tests
|
# Run tests
|
||||||
source "$scriptDir/bashunit.bash"
|
source "$scriptDir/bashunit.bash"
|
||||||
# Nothing happens after this
|
# Nothing happens after this
|
||||||
|
|
Loading…
Reference in a new issue