Should work now

master
Meliurwen 4 years ago
parent fef1685786
commit b4264bccfa
Signed by: meliurwen
GPG Key ID: 818A8B35E9F1CE10
  1. 15
      Dockerfile
  2. 3
      docker-compose.yml
  3. 22
      root/config/sshd_config
  4. 97
      root/entrypoint.sh
  5. 113
      root/usr/local/bin/create-sftp-user.sh

@ -0,0 +1,15 @@
FROM alpine:latest
# Steps done in one RUN layer:
# - Install packages
# - Fix default group (1000 does not exist)
# - OpenSSH needs /var/run/sshd to run
# - Remove generic host keys, entrypoint generates unique keys
RUN apk add --no-cache openssh openssh-sftp-server && \
sed -i 's/GROUP=1000/GROUP=100/' /etc/default/useradd && \
mkdir -p /var/run/sshd && \
rm -f /etc/ssh/ssh_host_*key*
COPY root/ /
ENTRYPOINT ["/entrypoint.sh"]

@ -2,7 +2,8 @@ version: "3"
services: services:
sftp: sftp:
image: ${SFTP_IMG:-atmoz/sftp}:${SFTP_TAG:-latest} #image: ${SFTP_IMG:-atmoz/sftp}:${SFTP_TAG:-latest}
build: .
container_name: ${SFTP_CONTAINER_NAME:-sftp} container_name: ${SFTP_CONTAINER_NAME:-sftp}
restart: ${SFTP_RESTART:-unless-stopped} restart: ${SFTP_RESTART:-unless-stopped}
volumes: volumes:

@ -0,0 +1,22 @@
# Secure defaults
# See: https://stribika.github.io/2015/01/04/secure-secure-shell.html
Protocol 2
HostKey /etc/ssh/ssh_host_ed25519_key
HostKey /etc/ssh/ssh_host_rsa_key
# Faster connection
# See: https://github.com/atmoz/sftp/issues/11
UseDNS no
# Limited access
PermitRootLogin no
X11Forwarding no
AllowTcpForwarding no
# Force sftp and chroot jail
Subsystem sftp internal-sftp
ForceCommand internal-sftp
ChrootDirectory %h
# Enable this for more logs
#LogLevel VERBOSE

@ -0,0 +1,97 @@
#!/bin/bash
set -Eeo pipefail
if [ ! -e /etc/openvpn/sshd_config ]; then
log "Configuration file sshd_config not found. Initializing..."
cp /config/sshd_config /etc/ssh/sshd_config
fi
# shellcheck disable=2154
trap 's=$?; echo "$0: Error on line "$LINENO": $BASH_COMMAND"; exit $s' ERR
reArgsMaybe="^[^:[:space:]]+:.*$" # Smallest indication of attempt to use argument
reArgSkip='^([[:blank:]]*#.*|[[:blank:]]*)$' # comment or empty line
# Paths
userConfPath="/etc/sftp/users.conf"
userConfFinalPath="/var/run/sftp/users.conf"
function log() {
echo "[$0] $*" >&2
}
# Allow running other programs, e.g. bash
if [[ -z "$1" || "$1" =~ $reArgsMaybe ]]; then
startSshd=true
else
startSshd=false
fi
# Create users only on first run
if [ ! -f "$userConfFinalPath" ]; then
mkdir -p "$(dirname $userConfFinalPath)"
if [ -f "$userConfPath" ]; then
# Append mounted config to final config
grep -v -E "$reArgSkip" < "$userConfPath" > "$userConfFinalPath"
fi
if $startSshd; then
# Append users from arguments to final config
for user in "$@"; do
echo "$user" >> "$userConfFinalPath"
done
fi
if [ -n "$SFTP_USERS" ]; then
# Append users from environment variable to final config
IFS=" " read -r -a usersFromEnv <<< "$SFTP_USERS"
for user in "${usersFromEnv[@]}"; do
echo "$user" >> "$userConfFinalPath"
done
fi
# Check that we have users in config
if [ -f "$userConfFinalPath" ] && [ "$(wc -l < "$userConfFinalPath")" -gt 0 ]; then
# Import users from final conf file
while IFS= read -r user || [[ -n "$user" ]]; do
create-sftp-user.sh "$user"
done < "$userConfFinalPath"
elif $startSshd; then
log "FATAL: No users provided!"
exit 3
fi
# Generate unique ssh keys for this container, if needed
if [ ! -f /etc/ssh/ssh_host_ed25519_key ]; then
ssh-keygen -t ed25519 -f /etc/ssh/ssh_host_ed25519_key -N ''
fi
if [ ! -f /etc/ssh/ssh_host_rsa_key ]; then
ssh-keygen -t rsa -b 4096 -f /etc/ssh/ssh_host_rsa_key -N ''
fi
# Restrict access from other users
chmod 600 /etc/ssh/ssh_host_ed25519_key || true
chmod 600 /etc/ssh/ssh_host_rsa_key || true
fi
# Source custom scripts, if any
if [ -d /etc/sftp.d ]; then
for f in /etc/sftp.d/*; do
if [ -x "$f" ]; then
log "Running $f ..."
$f
else
log "Could not run $f, because it's missing execute permission (+x)."
fi
done
unset f
fi
if $startSshd; then
log "Executing sshd"
exec /usr/sbin/sshd -D -e
else
log "Executing $*"
exec "$@"
fi

@ -0,0 +1,113 @@
#!/bin/bash
set -Eeo pipefail
# shellcheck disable=2154
trap 's=$?; echo "$0: Error on line "$LINENO": $BASH_COMMAND"; exit $s' ERR
# Extended regular expression (ERE) for arguments
reUser='[A-Za-z0-9._][A-Za-z0-9._-]{0,31}' # POSIX.1-2008
rePass='[^:]{0,255}'
reUid='[[:digit:]]*'
reGid='[[:digit:]]*'
reDir='[^:]*'
#reArgs="^($reUser)(:$rePass)(:e)?(:$reUid)?(:$reGid)?(:$reDir)?$"
function log() {
echo "[$0] $*"
}
function validateArg() {
name="$1"
val="$2"
re="$3"
if [[ "$val" =~ ^$re$ ]]; then
return 0
else
log "ERROR: Invalid $name \"$val\", do not match required regex pattern: $re"
return 1
fi
}
log "Parsing user data: \"$1\""
IFS=':' read -ra args <<< "$1"
skipIndex=0
chpasswdOptions=""
useraddOptions=(--no-user-group)
user="${args[0]}"; validateArg "username" "$user" "$reUser" || exit 1
pass="${args[1]}"; validateArg "password" "$pass" "$rePass" || exit 1
if [ "${args[2]}" == "e" ]; then
chpasswdOptions="-e"
skipIndex=1
fi
uid="${args[$((skipIndex+2))]}"; validateArg "UID" "$uid" "$reUid" || exit 1
gid="${args[$((skipIndex+3))]}"; validateArg "GID" "$gid" "$reGid" || exit 1
dir="${args[$((skipIndex+4))]}"; validateArg "dirs" "$dir" "$reDir" || exit 1
if getent passwd "$user" > /dev/null; then
log "WARNING: User \"$user\" already exists. Skipping."
exit 0
fi
if [ -n "$uid" ]; then
useraddOptions+=(--non-unique --uid "$uid")
fi
if [ -n "$gid" ]; then
if ! getent group "$gid" > /dev/null; then
groupadd --gid "$gid" "group_$gid"
fi
useraddOptions+=(--gid "$gid")
fi
useradd "${useraddOptions[@]}" "$user"
mkdir -p "/home/$user"
chown root:root "/home/$user"
chmod 755 "/home/$user"
# Retrieving user id to use it in chown commands instead of the user name
# to avoid problems on alpine when the user name contains a '.'
uid="$(id -u "$user")"
if [ -n "$pass" ]; then
echo "$user:$pass" | chpasswd $chpasswdOptions
else
usermod -p "*" "$user" # disabled password
fi
# Add SSH keys to authorized_keys with valid permissions
userKeysQueuedDir="/home/$user/.ssh/keys"
if [ -d "$userKeysQueuedDir" ]; then
userKeysAllowedFileTmp="$(mktemp)"
userKeysAllowedFile="/home/$user/.ssh/authorized_keys"
for publickey in "$userKeysQueuedDir"/*; do
cat "$publickey" >> "$userKeysAllowedFileTmp"
done
# Remove duplicate keys
sort < "$userKeysAllowedFileTmp" | uniq > "$userKeysAllowedFile"
chown "$uid" "$userKeysAllowedFile"
chmod 600 "$userKeysAllowedFile"
fi
# Make sure dirs exists
if [ -n "$dir" ]; then
IFS=',' read -ra dirArgs <<< "$dir"
for dirPath in "${dirArgs[@]}"; do
dirPath="/home/$user/$dirPath"
if [ ! -d "$dirPath" ]; then
log "Creating directory: $dirPath"
mkdir -p "$dirPath"
chown -R "$uid:users" "$dirPath"
else
log "Directory already exists: $dirPath"
fi
done
fi
Loading…
Cancel
Save