From c16739bba646f7eabcf8fc35f2bf580237a225d9 Mon Sep 17 00:00:00 2001 From: Peter Becker Date: Sun, 11 Sep 2016 10:55:33 +0200 Subject: [PATCH 1/8] Add description for pinned server ssh-keys --- README.md | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/README.md b/README.md index 268e9cc..b93522d 100644 --- a/README.md +++ b/README.md @@ -109,6 +109,31 @@ docker run \ foo::1001 ``` +## Using custom SSH key for server + +This container will generate an ssh-key for OpenSSH at first run. To avoid this, you can map Ed25519 or RSA keys from the host inside the container. + +### Ed25519 key +``` +docker run \ + -v /host/ssh_host_ed25519_key:/etc/ssh/ssh_host_ed25519_key \ + -v /host/share:/home/foo/share \ + -p 2222:22 -d atmoz/sftp \ + foo::1001 +``` +Tip: you can generate an Ed25519 key with this command: `ssh-keygen -t ed25519 -f /host/ssh_host_ed25519_key < /dev/null` + +### RSA key +``` +docker run \ + -v /host/ssh_host_rsa_key:/etc/ssh/ssh_host_rsa_key \ + -v /host/share:/home/foo/share \ + -p 2222:22 -d atmoz/sftp \ + foo::1001 +``` +Tip: you can generate an Ed25519 key with this command: `ssh-keygen -t rsa -b 4096 -f /etc/ssh/ssh_host_rsa_key < /dev/null` + + ## Execute custom scripts or applications Put your programs in `/etc/sftp.d/` and it will automatically run when the container starts. From 34f6dc601bb892fc2c7f223fefb4839e1321096e Mon Sep 17 00:00:00 2001 From: Peter Becker Date: Wed, 28 Sep 2016 11:59:43 +0200 Subject: [PATCH 2/8] Update README.md --- README.md | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index b93522d..613350e 100644 --- a/README.md +++ b/README.md @@ -113,26 +113,23 @@ docker run \ This container will generate an ssh-key for OpenSSH at first run. To avoid this, you can map Ed25519 or RSA keys from the host inside the container. -### Ed25519 key ``` +#for ed25519 keys: docker run \ -v /host/ssh_host_ed25519_key:/etc/ssh/ssh_host_ed25519_key \ -v /host/share:/home/foo/share \ -p 2222:22 -d atmoz/sftp \ foo::1001 -``` -Tip: you can generate an Ed25519 key with this command: `ssh-keygen -t ed25519 -f /host/ssh_host_ed25519_key < /dev/null` - -### RSA key -``` +#Tip: you can generate an Ed25519 key with this command: `ssh-keygen -t ed25519 -f /host/ssh_host_ed25519_key < /dev/null` + +#for rsa keys: docker run \ -v /host/ssh_host_rsa_key:/etc/ssh/ssh_host_rsa_key \ -v /host/share:/home/foo/share \ -p 2222:22 -d atmoz/sftp \ foo::1001 +#Tip: you can generate an rsa key with this command: `ssh-keygen -t rsa -b 4096 -f /etc/ssh/ssh_host_rsa_key < /dev/null` ``` -Tip: you can generate an Ed25519 key with this command: `ssh-keygen -t rsa -b 4096 -f /etc/ssh/ssh_host_rsa_key < /dev/null` - ## Execute custom scripts or applications From f6d43026b91b6a3a65edc16d540080702ff6701b Mon Sep 17 00:00:00 2001 From: Peter Becker Date: Wed, 28 Sep 2016 12:47:13 +0200 Subject: [PATCH 3/8] Add description for pinned server ssh-keys --- README.md | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 613350e..3ff091a 100644 --- a/README.md +++ b/README.md @@ -114,21 +114,18 @@ docker run \ This container will generate an ssh-key for OpenSSH at first run. To avoid this, you can map Ed25519 or RSA keys from the host inside the container. ``` -#for ed25519 keys: docker run \ -v /host/ssh_host_ed25519_key:/etc/ssh/ssh_host_ed25519_key \ - -v /host/share:/home/foo/share \ - -p 2222:22 -d atmoz/sftp \ - foo::1001 -#Tip: you can generate an Ed25519 key with this command: `ssh-keygen -t ed25519 -f /host/ssh_host_ed25519_key < /dev/null` - -#for rsa keys: -docker run \ -v /host/ssh_host_rsa_key:/etc/ssh/ssh_host_rsa_key \ -v /host/share:/home/foo/share \ -p 2222:22 -d atmoz/sftp \ foo::1001 -#Tip: you can generate an rsa key with this command: `ssh-keygen -t rsa -b 4096 -f /etc/ssh/ssh_host_rsa_key < /dev/null` +``` + +Tip: you can generate keys with this commands: +``` +ssh-keygen -t ed25519 -f /host/ssh_host_ed25519_key < /dev/null +ssh-keygen -t rsa -b 4096 -f /etc/ssh/ssh_host_rsa_key < /dev/null ``` ## Execute custom scripts or applications From efa7f88ff24fb3c5a444ca536b9a6fbb2fa20e17 Mon Sep 17 00:00:00 2001 From: Jason Murray Date: Wed, 8 Mar 2017 11:25:40 +0100 Subject: [PATCH 4/8] Move user file to /etc/sftp/ directory This allows for mounting with ConfigMap or Secrets in Kubernetes --- entrypoint | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/entrypoint b/entrypoint index 861a328..b8b40a6 100755 --- a/entrypoint +++ b/entrypoint @@ -2,8 +2,8 @@ set -e export DEBIAN_FRONTEND=noninteractive -userConfPath="/etc/sftp-users.conf" -userConfFinalPath="/var/run/sftp-users.conf" +userConfPath="/etc/sftp/sftp-users.conf" +userConfFinalPath="/var/run/sftp/sftp-users.conf" function printHelp() { echo "Add users as command arguments, STDIN or mounted in $userConfPath" From af9de40554922682023fc85f197a824b25bd7119 Mon Sep 17 00:00:00 2001 From: Jason Murray Date: Wed, 8 Mar 2017 11:28:26 +0100 Subject: [PATCH 5/8] Update user file path in README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 49d74c3..653aee5 100644 --- a/README.md +++ b/README.md @@ -73,7 +73,7 @@ OpenSSH client, run: `sftp -P 2222 foo@` ``` docker run \ - -v /host/users.conf:/etc/sftp-users.conf:ro \ + -v /host/users.conf:/etc/sftp/sftp-users.conf:ro \ -v mySftpVolume:/home \ -v /host/ssh_host_rsa_key:/etc/ssh/ssh_host_rsa_key \ -v /host/ssh_host_rsa_key.pub:/etc/ssh/ssh_host_rsa_key.pub \ From fe107107af0e186578e0e10b51dd2074b805811a Mon Sep 17 00:00:00 2001 From: Adrian Dvergsdal Date: Sun, 25 Jun 2017 01:42:02 +0200 Subject: [PATCH 6/8] Update README.md --- README.md | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 2616b57..041b6be 100644 --- a/README.md +++ b/README.md @@ -103,10 +103,13 @@ docker run \ Tip: you can use [atmoz/makepasswd](https://hub.docker.com/r/atmoz/makepasswd/) to generate encrypted passwords: `echo -n "your-password" | docker run -i --rm atmoz/makepasswd --crypt-md5 --clearfrom=-` -## Using SSH key (and no password) +## Logging in with SSH keys -Mount all public keys in the user's `.ssh/keys/` directory. All keys are automatically -appended to `.ssh/authorized_keys`. +Mount public keys in the user's `.ssh/keys/` directory. All keys are +automatically appended to `.ssh/authorized_keys` (you can't mount this file +directly, because OpenSSH requires limited file permissions). In this example, +we do not provide any password, so the user `foo` can only login with his SSH +key. ``` docker run \ @@ -117,9 +120,11 @@ docker run \ foo::1001 ``` -## Using custom SSH key for server +## Providing your own SSH host key -This container will generate an ssh-key for OpenSSH at first run. To avoid this, you can map Ed25519 or RSA keys from the host inside the container. +This container will generate new SSH host keys at first run. To avoid that your +users get a MITM warning when you recreate your container (and the host keys +changes), you can mount your own host keys. ``` docker run \ @@ -130,7 +135,8 @@ docker run \ foo::1001 ``` -Tip: you can generate keys with this commands: +Tip: you can generate your keys with these commands: + ``` ssh-keygen -t ed25519 -f /host/ssh_host_ed25519_key < /dev/null ssh-keygen -t rsa -b 4096 -f /etc/ssh/ssh_host_rsa_key < /dev/null From c4fd217a7ed19c9782d0d15ea3cbcbc1c3ec15fa Mon Sep 17 00:00:00 2001 From: Adrian Dvergsdal Date: Sun, 25 Jun 2017 14:05:22 +0200 Subject: [PATCH 7/8] Backward compatibility with legacy config path --- README.md | 4 ++-- entrypoint | 12 ++++++++++-- tests/run | 38 +++++++++++++++++++++++++++++++++----- 3 files changed, 45 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 45d3723..132d366 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ This is an automated build linked with the [debian](https://hub.docker.com/_/deb # Usage -- Required: define users as command arguments, STDIN or mounted in `/etc/sftp-users.conf` +- Required: define users as command arguments, STDIN or mounted in `/etc/sftp/users.conf` (syntax: `user:pass[:e][:uid[:gid[:dir1[,dir2]...]]]...`). - Set UID/GID manually for your users if you want them to make changes to your mounted volumes with permissions matching your host filesystem. @@ -74,7 +74,7 @@ OpenSSH client, run: `sftp -P 2222 foo@` ``` docker run \ - -v /host/users.conf:/etc/sftp/sftp-users.conf:ro \ + -v /host/users.conf:/etc/sftp/users.conf:ro \ -v mySftpVolume:/home \ -v /host/ssh_host_rsa_key:/etc/ssh/ssh_host_rsa_key \ -v /host/ssh_host_rsa_key.pub:/etc/ssh/ssh_host_rsa_key.pub \ diff --git a/entrypoint b/entrypoint index b8b40a6..1216bed 100755 --- a/entrypoint +++ b/entrypoint @@ -2,8 +2,9 @@ set -e export DEBIAN_FRONTEND=noninteractive -userConfPath="/etc/sftp/sftp-users.conf" -userConfFinalPath="/var/run/sftp/sftp-users.conf" +userConfPath="/etc/sftp/users.conf" +userConfPathLegacy="/etc/sftp-users.conf" +userConfFinalPath="/var/run/sftp/users.conf" function printHelp() { echo "Add users as command arguments, STDIN or mounted in $userConfPath" @@ -96,8 +97,15 @@ if [ "$1" == "--readme" ]; then exit 0 fi +# Backward compatibility with legacy config path +if [ ! -f "$userConfPath" -a -f "$userConfPathLegacy" ]; then + mkdir -p "$(dirname $userConfPath)" + ln -s "$userConfPathLegacy" "$userConfPath" +fi + # Create users only on first run if [ ! -f "$userConfFinalPath" ]; then + mkdir -p "$(dirname $userConfFinalPath)" # Append mounted config to final config if [ -f "$userConfPath" ]; then diff --git a/tests/run b/tests/run index cc2897a..6dc1171 100755 --- a/tests/run +++ b/tests/run @@ -45,7 +45,7 @@ function beforeTest() { echo "test::$(id -u):$(id -g):dir1,dir2" >> "$tmpDir/users" $sudo docker run \ - -v "$tmpDir/users:/etc/sftp-users.conf:ro" \ + -v "$tmpDir/users:/etc/sftp/users.conf:ro" \ -v "$scriptDir/id_rsa.pub":/home/test/.ssh/keys/id_rsa.pub:ro \ -v "$tmpDir":/home/test/share \ --name "$sftpContainerName" \ @@ -96,19 +96,19 @@ function runSftpCommands() { function waitForServer() { containerName="$1" - echo -n "Waiting for $containerName to open port 22 " + echo -n "Waiting for $containerName to open port 22 ..." for i in {1..30}; do sleep 1 ip="$(getSftpIp $containerName)" echo -n "." - if nc -z $ip 22; then - echo " OK" + if [ -n "$ip" ] && nc -z $ip 22; then + echo " OPEN" return 0; fi done - echo " FAIL" + echo " TIMEOUT" return 1 } @@ -189,6 +189,34 @@ function testMinimalContainerStart() { fi } +function testLegacyConfigPath() { + $skipAllTests && skip && return 0 + + tmpContainerName="$sftpContainerName""_legacy" + + echo "test::$(id -u):$(id -g)" >> "$tmpDir/legacy_users" + $sudo docker run \ + -v "$tmpDir/legacy_users:/etc/sftp-users.conf:ro" \ + --name "$tmpContainerName" \ + --expose 22 \ + -d "$sftpImageName" \ + > "$redirect" + + waitForServer $tmpContainerName + + ps="$($sudo docker ps -q -f name="$tmpContainerName")" + assertNotEqual "$ps" "" + + if [ "$output" != "quiet" ]; then + $sudo docker logs "$tmpContainerName" + fi + + if [ "$cleanup" == "cleanup" ]; then + $sudo docker rm -fv "$tmpContainerName" > "$redirect" + fi +} + + # Bind-mount folder using script in /etc/sftp.d/ function testCustomContainerStart() { $skipAllTests && skip && return 0 From 2891aab052f7cf967da9fa24ed63da8c5c5427bf Mon Sep 17 00:00:00 2001 From: Adrian Dvergsdal Date: Sun, 25 Jun 2017 15:16:41 +0200 Subject: [PATCH 8/8] Test usernames with dots --- tests/run | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/tests/run b/tests/run index 6dc1171..f02540f 100755 --- a/tests/run +++ b/tests/run @@ -44,9 +44,11 @@ function beforeTest() { mkdir "$tmpDir" echo "test::$(id -u):$(id -g):dir1,dir2" >> "$tmpDir/users" + echo "user.with.dot::$(id -u):$(id -g)" >> "$tmpDir/users" $sudo 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/user.with.dot/.ssh/keys/id_rsa.pub:ro \ -v "$tmpDir":/home/test/share \ --name "$sftpContainerName" \ --expose 22 \ @@ -132,6 +134,13 @@ function testLoginUsingSshKey() { assertReturn $? 0 } +function testUserWithDotLogin() { + $skipAllTests && skip && return 0 + + runSftpCommands "$sftpContainerName" "user.with.dot" "exit" + assertReturn $? 0 +} + function testWritePermission() { $skipAllTests && skip && return 0