0
0
Fork 0
mirror of https://github.com/atmoz/sftp.git synced 2024-11-17 12:51:33 -05:00
atmoz-sftp/entrypoint

191 lines
5.2 KiB
Text
Raw Normal View History

2014-10-07 15:34:24 -04:00
#!/bin/bash
set -e
2014-10-07 15:34:24 -04:00
# Paths
userConfPath="/etc/sftp/users.conf"
userConfPathLegacy="/etc/sftp-users.conf"
userConfFinalPath="/var/run/sftp/users.conf"
2015-12-07 04:10:24 -05:00
# 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)?$"
reArgsMaybe="^[^:[:space:]]+:.*$" # Smallest indication of attempt to use argument
2017-10-08 13:08:53 -04:00
reArgSkip='^([[:blank:]]*#.*|[[:blank:]]*)$' # comment or empty line
function log() {
echo "[entrypoint] $@"
2015-07-25 08:00:24 -04:00
}
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
2015-07-25 08:00:24 -04:00
}
2015-07-25 07:55:33 -04:00
2015-07-25 08:00:24 -04:00
function createUser() {
log "Parsing user data: \"$@\""
IFS=':' read -a args <<< $@
2018-01-04 13:22:15 -05:00
skipIndex=0
chpasswdOptions=""
useraddOptions="--no-user-group"
2014-10-07 15:34:24 -04:00
user="${args[0]}"; validateArg "username" "$user" "$reUser" || return 1
pass="${args[1]}"; validateArg "password" "$pass" "$rePass" || return 1
if [ "${args[2]}" == "e" ]; then
2015-01-03 07:10:38 -05:00
chpasswdOptions="-e"
2018-01-04 13:22:15 -05:00
skipIndex=1
fi
2018-01-04 13:22:15 -05:00
uid="${args[$[$skipIndex+2]]}"; validateArg "UID" "$uid" "$reUid" || return 1
gid="${args[$[$skipIndex+3]]}"; validateArg "GID" "$gid" "$reGid" || return 1
dir="${args[$[$skipIndex+4]]}"; validateArg "dirs" "$dir" "$reDir" || return 1
2015-12-20 19:37:42 -05:00
if getent passwd $user > /dev/null; then
log "WARNING: User \"$user\" already exists. Skipping."
return 0
fi
if [ -n "$uid" ]; then
2015-01-03 07:10:38 -05:00
useraddOptions="$useraddOptions --non-unique --uid $uid"
fi
if [ -n "$gid" ]; then
if ! getent group $gid > /dev/null; then
2016-09-02 19:02:47 -04:00
groupadd --gid $gid "group_$gid"
2015-12-07 04:10:24 -05:00
fi
2015-12-20 19:37:42 -05:00
useraddOptions="$useraddOptions --gid $gid"
fi
2015-01-03 07:10:38 -05:00
useradd $useraddOptions $user
2015-12-20 18:55:32 -05:00
mkdir -p /home/$user
2014-10-07 15:34:24 -04:00
chown root:root /home/$user
chmod 755 /home/$user
2014-10-20 21:21:53 -04:00
# 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 '.'
2017-10-13 17:39:04 -04:00
uid="$(id -u $user)"
if [ -n "$pass" ]; then
echo "$user:$pass" | chpasswd $chpasswdOptions
else
usermod -p "*" $user # disabled password
2014-10-20 21:21:53 -04:00
fi
2015-12-20 18:55:32 -05:00
# Add SSH keys to authorized_keys with valid permissions
if [ -d /home/$user/.ssh/keys ]; then
for publickey in /home/$user/.ssh/keys/*; do
cat $publickey >> /home/$user/.ssh/authorized_keys
done
chown $uid /home/$user/.ssh/authorized_keys
2015-12-20 18:55:32 -05:00
chmod 600 /home/$user/.ssh/authorized_keys
fi
# Make sure dirs exists
if [ -n "$dir" ]; then
IFS=',' read -a 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
2016-08-12 14:45:21 -04:00
done
fi
2015-07-25 08:00:24 -04:00
}
# Allow running other programs, e.g. bash
if [[ -z "$1" || "$1" =~ $reArgsMaybe ]]; then
startSshd=true
else
startSshd=false
2015-07-25 08:00:24 -04:00
fi
# Backward compatibility with legacy config path
if [ ! -f "$userConfPath" -a -f "$userConfPathLegacy" ]; then
mkdir -p "$(dirname $userConfPath)"
ln -s "$userConfPathLegacy" "$userConfPath"
fi
2015-12-20 19:37:42 -05:00
# Create users only on first run
if [ ! -f "$userConfFinalPath" ]; then
mkdir -p "$(dirname $userConfFinalPath)"
2015-12-07 04:10:24 -05:00
# Append mounted config to final config
if [ -f "$userConfPath" ]; then
2017-10-08 13:08:53 -04:00
cat "$userConfPath" | grep -v -E "$reArgSkip" > "$userConfFinalPath"
fi
2015-12-07 04:10:24 -05:00
if $startSshd; then
# Append users from arguments to final config
for user in "$@"; do
echo "$user" >> "$userConfFinalPath"
done
fi
2015-12-07 04:10:24 -05:00
if [ -n "$SFTP_USERS" ]; then
# Append users from environment variable to final config
usersFromEnv=($SFTP_USERS) # as array
for user in "${usersFromEnv[@]}"; do
echo "$user" >> "$userConfFinalPath"
done
fi
2015-12-20 19:37:42 -05:00
# Check that we have users in config
if [[ -f "$userConfFinalPath" && "$(cat "$userConfFinalPath" | wc -l)" > 0 ]]; then
# Import users from final conf file
while IFS= read -r user || [[ -n "$user" ]]; do
createUser "$user"
done < "$userConfFinalPath"
elif $startSshd; then
log "FATAL: No users provided!"
2015-12-20 19:37:42 -05:00
exit 3
fi
2016-06-02 08:56:30 -04:00
# Generate unique ssh keys for this container, if needed
if [ ! -f /etc/ssh/ssh_host_ed25519_key ]; then
2016-11-15 09:32:03 -05:00
ssh-keygen -t ed25519 -f /etc/ssh/ssh_host_ed25519_key -N ''
2016-06-02 08:56:30 -04:00
fi
if [ ! -f /etc/ssh/ssh_host_rsa_key ]; then
2016-11-15 09:32:03 -05:00
ssh-keygen -t rsa -b 4096 -f /etc/ssh/ssh_host_rsa_key -N ''
2016-06-02 08:56:30 -04:00
fi
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