From cab9eb428b333cd992b13ff33203f8225492911c Mon Sep 17 00:00:00 2001 From: Adrian Dvergsdal Date: Sat, 6 Aug 2016 17:44:44 +0200 Subject: [PATCH 1/4] Install makepasswd --- Dockerfile | 6 +++--- README.md | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Dockerfile b/Dockerfile index 318f371..77f50ca 100644 --- a/Dockerfile +++ b/Dockerfile @@ -5,10 +5,10 @@ MAINTAINER Adrian Dvergsdal [atmoz.net] # - OpenSSH needs /var/run/sshd to run # - Remove generic host keys, entrypoint generates unique keys RUN apt-get update && \ - apt-get -y install openssh-server && \ + apt-get -y install openssh-server makepasswd && \ + rm -rf /var/lib/apt/lists/* && \ mkdir -p /var/run/sshd && \ - rm -f /etc/ssh/ssh_host_*key* && \ - rm -rf /var/lib/apt/lists/* + rm -f /etc/ssh/ssh_host_*key* COPY sshd_config /etc/ssh/sshd_config COPY entrypoint / diff --git a/README.md b/README.md index 975a137..083d8b9 100644 --- a/README.md +++ b/README.md @@ -77,8 +77,8 @@ docker run \ 'foo:$1$0G2g0GSt$ewU0t6GXG15.0hWoOX8X9.:e:1001' ``` -Tip: you can use makepasswd to generate encrypted passwords: -`echo -n "password" | makepasswd --crypt-md5 --clearfrom -` +Tip: you can use [makepasswd](https://packages.debian.org/jessie/makepasswd) (included in the debian image) to generate encrypted passwords: +`echo -n "password" | docker run -i --rm --entrypoint=makepasswd atmoz/sftp:debian --crypt-md5 --clearfrom -` ## Using SSH key (without password) From 86f20750ebd3c627602850e7ef58a31f2875d9da Mon Sep 17 00:00:00 2001 From: Adrian Dvergsdal Date: Sat, 6 Aug 2016 17:46:28 +0200 Subject: [PATCH 2/4] Update readme --- README.md | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 083d8b9..9a7a49d 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ This is an automated build linked with the [debian](https://hub.docker.com/_/deb # Usage -- Define users as command arguments, STDIN or mounted in /etc/sftp-users.conf +- Define users as command arguments, STDIN or mounted in `/etc/sftp-users.conf` (syntax: `user:pass[:e][:uid[:gid]]...`). - 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. @@ -96,18 +96,20 @@ docker run \ ## Execute custom scripts or applications -Put your programs in /etc/sftp.d/ and it will automatically run when the container starts. +Put your programs in `/etc/sftp.d/` and it will automatically run when the container starts. See next section for an example. ## Bindmount dirs from another location -If you are using --volumes-from or just want to make a custom directory -available in user's home directory, you can add a script to /etc/sftp.d/ that +If you are using `--volumes-from` or just want to make a custom directory +available in user's home directory, you can add a script to `/etc/sftp.d/` that bindmounts after container starts. ``` #!/bin/bash -# Just an example (make your own): +# File mounted as: /etc/sftp.d/bindmount.sh +# Just an example (make your own) + function bindmount() { if [ -d "$1" ]; then mkdir -p "$2" @@ -115,7 +117,7 @@ function bindmount() { mount --bind $3 "$1" "$2" } -# Remember permissions, you may have to fix it: +# Remember permissions, you may have to fix them: # chown -R :users /data/common bindmount /data/admin-tools /home/admin/tools From 382d7363367528b04e138bb9014898b3f340db9f Mon Sep 17 00:00:00 2001 From: Adrian Dvergsdal Date: Sat, 6 Aug 2016 18:30:12 +0200 Subject: [PATCH 3/4] Extract makepasswd to separate docker image --- Dockerfile | 2 +- README.md | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Dockerfile b/Dockerfile index 77f50ca..9f235a5 100644 --- a/Dockerfile +++ b/Dockerfile @@ -5,7 +5,7 @@ MAINTAINER Adrian Dvergsdal [atmoz.net] # - OpenSSH needs /var/run/sshd to run # - Remove generic host keys, entrypoint generates unique keys RUN apt-get update && \ - apt-get -y install openssh-server makepasswd && \ + apt-get -y install openssh-server && \ rm -rf /var/lib/apt/lists/* && \ mkdir -p /var/run/sshd && \ rm -f /etc/ssh/ssh_host_*key* diff --git a/README.md b/README.md index 9a7a49d..9a0c0cc 100644 --- a/README.md +++ b/README.md @@ -77,8 +77,8 @@ docker run \ 'foo:$1$0G2g0GSt$ewU0t6GXG15.0hWoOX8X9.:e:1001' ``` -Tip: you can use [makepasswd](https://packages.debian.org/jessie/makepasswd) (included in the debian image) to generate encrypted passwords: -`echo -n "password" | docker run -i --rm --entrypoint=makepasswd atmoz/sftp:debian --crypt-md5 --clearfrom -` +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 (without password) From 429d8559d247a644f49257e592367012fb1769fc Mon Sep 17 00:00:00 2001 From: Adrian Dvergsdal Date: Fri, 12 Aug 2016 16:21:07 +0200 Subject: [PATCH 4/4] Create directories and/or set permissions --- README.md | 27 +++++++++++++++----- entrypoint | 21 ++++++++++++++-- tests/run | 73 ++++++++++++++++++++++++++++++++++-------------------- 3 files changed, 86 insertions(+), 35 deletions(-) diff --git a/README.md b/README.md index 9a0c0cc..520fe73 100644 --- a/README.md +++ b/README.md @@ -11,17 +11,32 @@ This is an automated build linked with the [debian](https://hub.docker.com/_/deb # Usage - Define users as command arguments, STDIN or mounted in `/etc/sftp-users.conf` - (syntax: `user:pass[:e][:uid[:gid]]...`). - - You must set custom UID for your users if you want them to make changes to + (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. -- Mount volumes in user's home folder. + - Add directory names at the end, if you want to create them and/or set user + owership. Perfect when you just want a fast way to upload something without + mounting any directories, or you want to make sure a directory is owned by + a user. +- Mount volumes in user's home direcotry. - The users are chrooted to their home directory, so you must mount the volumes in separate directories inside the user's home directory (/home/user/**mounted-directory**). # Examples -## Simple docker run example + +## Simplest docker run example + +``` +docker run -p 22:22 -d atmoz/sftp foo:pass:::upload +``` + +No mounted directories or custom UID/GID. User "foo" with password "pass" can login with sftp and upload files to a folder called "upload". Later you can inspect the files and use `--volumes-from` to mount them somewhere else (or see next example). + +## Sharing a directory from your computer + +Let's mount a direcotry and set UID: ``` docker run \ @@ -80,9 +95,9 @@ 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 (without password) +## Using SSH key (and no password) -Mount all public keys in the user's `.ssh/keys/` folder. All keys are automatically +Mount all public keys in the user's `.ssh/keys/` direcotry. All keys are automatically appended to `.ssh/authorized_keys`. ``` diff --git a/entrypoint b/entrypoint index 5d5f81d..18d9e7b 100755 --- a/entrypoint +++ b/entrypoint @@ -7,7 +7,7 @@ userConfFinalPath="/var/run/sftp-users.conf" function printHelp() { echo "Add users as command arguments, STDIN or mounted in $userConfPath" - echo "Syntax: user:pass[:e][:uid[:gid]]..." + echo "Syntax: user:pass[:e][:uid[:gid[:dir1[,dir2]...]]] ..." echo "Use --readme for more information and examples." } @@ -25,9 +25,11 @@ function createUser() { chpasswdOptions="-e" uid="${param[3]}" gid="${param[4]}" + dir="${param[5]}" else uid="${param[2]}" gid="${param[3]}" + dir="${param[4]}" fi if [ -z "$user" ]; then @@ -72,6 +74,18 @@ function createUser() { chown $user /home/$user/.ssh/authorized_keys chmod 600 /home/$user/.ssh/authorized_keys fi + + # Make sure dirs exists and has correct permissions + if [ -n "$dir" ]; then + while IFS=',' read -ra dirParam; do + for dirPath in $dirParam; do + dirPath=/home/$user/$dirPath + echo "Creating and/or setting permissions on $dirPath" + mkdir -p $dirPath + chown -R $user:users $dirPath + done + done <<< $dir + fi } if [[ $1 =~ ^--help$|^-h$ ]]; then @@ -128,7 +142,10 @@ fi # Source custom scripts, if any if [ -d /etc/sftp.d ]; then for f in /etc/sftp.d/*; do - [ -x "$f" ] && . "$f" + if [ -x "$f" ]; then + echo "Running $f ..." + $f + fi done unset f fi diff --git a/tests/run b/tests/run index 44b74bf..246fec8 100755 --- a/tests/run +++ b/tests/run @@ -36,7 +36,7 @@ function beforeTest() { rm -rf "$tmpDir" # clean state mkdir "$tmpDir" - echo "test::$(id -u):$(id -g)" >> "$tmpDir/users" + echo "test::$(id -u):$(id -g):dir" >> "$tmpDir/users" docker run \ -v "$tmpDir/users:/etc/sftp-users.conf:ro" \ -v "$scriptDir/id_rsa.pub":/home/test/.ssh/keys/id_rsa.pub:ro \ @@ -86,6 +86,51 @@ function runSftpCommands() { ############################################################################## +function testContainerIsRunning() { + $skipAllTests && skip && return 0 + + ps="$(docker ps -q -f name="$sftpContainerName")" + assertNotEqual "$ps" "" + + if [ -z "$ps" ]; then + skipAllTests=true + fi +} + +function testLoginUsingSshKey() { + $skipAllTests && skip && return 0 + + runSftpCommands "$sftpContainerName" \ + "test" \ + "exit" + assertReturn $? 0 +} + +function testWritePermission() { + $skipAllTests && skip && return 0 + + runSftpCommands "$sftpContainerName" \ + "test" \ + "cd share" \ + "mkdir test" \ + "exit" + test -d "$tmpDir/test" + assertReturn $? 0 +} + +function testDir() { + $skipAllTests && skip && return 0 + + runSftpCommands "$sftpContainerName" \ + "test" \ + "cd dir" \ + "mkdir test2" \ + "get -rf test2 $tmpDir/" \ + "exit" + test -d "$tmpDir/test2" + assertReturn $? 0 +} + function testMinimalContainerStart() { $skipAllTests && skip && return 0 @@ -114,32 +159,6 @@ function testMinimalContainerStart() { fi } -function testContainerIsRunning() { - $skipAllTests && skip && return 0 - - ps="$(docker ps -q -f name="$sftpContainerName")" - assertNotEqual "$ps" "" - - if [ -z "$ps" ]; then - skipAllTests=true - fi -} - -function testLoginUsingSshKey() { - $skipAllTests && skip && return 0 - - runSftpCommands "$sftpContainerName" "test" "exit" - assertReturn $? 0 -} - -function testWritePermission() { - $skipAllTests && skip && return 0 - - runSftpCommands "$sftpContainerName" "test" "cd share" "mkdir test" "exit" - test -d "$tmpDir/test" - assertReturn $? 0 -} - # Bind-mount folder using script in /etc/sftp.d/ function testCustomContainerStart() { $skipAllTests && skip && return 0