From c770f2c170dffa8147f8f302dbd704cda31bc2b2 Mon Sep 17 00:00:00 2001 From: Valentin Lab Date: Tue, 29 Jan 2019 18:26:12 +0100 Subject: [PATCH] new: [sftp] compose ready charm --- sftp/build/Dockerfile | 10 +++ sftp/build/src/etc/ssh/sshd_config | 8 ++ sftp/hooks/init | 51 ++----------- sftp/lib/common | 114 +++++++++++++++++++++++++++++ sftp/metadata.yml | 4 +- 5 files changed, 141 insertions(+), 46 deletions(-) create mode 100644 sftp/build/Dockerfile create mode 100644 sftp/build/src/etc/ssh/sshd_config create mode 100644 sftp/lib/common diff --git a/sftp/build/Dockerfile b/sftp/build/Dockerfile new file mode 100644 index 0000000..d994947 --- /dev/null +++ b/sftp/build/Dockerfile @@ -0,0 +1,10 @@ +FROM alpine:3.7 + +RUN apk add --no-cache openssh openssh-sftp-server + +RUN ssh-keygen -t rsa -b 4096 -f /etc/ssh/ssh_host_rsa_key -N '' && \ + ssh-keygen -t ed25519 -f /etc/ssh/ssh_host_ed25519_key -N '' + +COPY src/ . + +CMD /usr/sbin/sshd -D -e diff --git a/sftp/build/src/etc/ssh/sshd_config b/sftp/build/src/etc/ssh/sshd_config new file mode 100644 index 0000000..ad87462 --- /dev/null +++ b/sftp/build/src/etc/ssh/sshd_config @@ -0,0 +1,8 @@ +UseDNS no +PermitRootLogin no +Subsystem sftp internal-sftp +ChrootDirectory %h +X11Forwarding no +AllowTcpForwarding no +ForceCommand internal-sftp + diff --git a/sftp/hooks/init b/sftp/hooks/init index db74b9a..48094b0 100755 --- a/sftp/hooks/init +++ b/sftp/hooks/init @@ -11,53 +11,18 @@ ## - SERVICE_CONFIGSTORE Location on host of the CONFIGSTORE of this service +. lib/common + set -e + + service_def=$(get_compose_service_def "$SERVICE_NAME") users_def=$(echo "$service_def" | shyaml get-value options.users 2>/dev/null) || true -users_file="$SERVICE_CONFIGSTORE/etc/sftp-users.conf" -echo | file_put "$users_file" - -rm -f "$SERVICE_DATASTORE/home/"*"/.ssh/authorized_keys" - -[ "$users_def" ] || exit 0 - -rm -f "$users_file" - -volume_keys=() -while read-0 login user_def; do - key_nb=0 - local_path_key="/home/$login/.ssh/keys" - host_path_key="$SERVICE_CONFIGSTORE${local_path_key}" - while read-0 key; do - debug "Creating login key ${key_nb} for '$login'" || true - echo "$key" | file_put "$host_path_key/key_${key_nb}.pub" - ((key_nb++)) || true - done < <(echo "$user_def" | shyaml get-values-0 keys) - volume_keys+=("$host_path_key:$local_path_key:ro") - gids=() - while read-0 group; do - if ! group_ent=$(getent group "$group"); then - debug groupadd -K GID_MIN=3000 -K GID_MAX=4000 "$group" - groupadd -K GID_MIN=3000 -K GID_MAX=4000 "$group" - group_ent=$(getent group "$group") - fi - gids+=("$(echo "$group_ent" | cut -f3 -d:)") - done < <(echo "$user_def" | shyaml get-values-0 groups 2>/dev/null) - password=$(echo "$user_def" | shyaml get-value password 2>/dev/null) || - password=$(gen_password 14) - line="$login:$password::$(echo "${gids[@]}" | tr " " ",")" - debug "Adding line: $line" - echo "$line" >> "$users_file" -done < <(echo "$users_def" | shyaml key-values-0) - -init-config-add "\ -$SERVICE_NAME: - volumes: -$(for volume in "${volume_keys[@]}"; do - echo " - $volume" - done) -" +build_script="$(make_build_script "$users_def")" || exit 1 +echo "build-script:" >&2 +echo "$build_script" | prefix " $GRAY|$NORMAL " >&2 +docker_update "$SERVICE_NAME" "$build_script" -v "$SERVICE_DATASTORE/home":"/home" || exit 1 diff --git a/sftp/lib/common b/sftp/lib/common new file mode 100644 index 0000000..79f3a24 --- /dev/null +++ b/sftp/lib/common @@ -0,0 +1,114 @@ +# -*- mode: shell-script -*- + + +make_build_script() { + local users_def="$1" cache_file="$CACHEDIR/$FUNCNAME.cache.$(p0 "$@" | md5_compat)" + if [ -e "$cache_file" ]; then + #debug "$FUNCNAME: STATIC cache hit" + cat "$cache_file" && + touch "$cache_file" || return 1 + return 0 + fi + + local users_def="$1" \ + code fixed_groups_code groups_code volume_keys \ + created_groups first_group + + if [ -z "$users_def" ]; then + return 0 + fi + + e "set -eux"$'\n' + code="" + fixed_groups_code="" + groups_code="" + volume_keys=() + + declare -A created_groups + while read-0 user user_def; do + + code+="mkdir -p \"/home/$user\""$'\n' + + ## + ## Group management + ## + + first_group= + groups=() + first=1 + while read-0 group; do + [ "${created_groups[$group]}" ] && continue + if [[ "$group" == *":"* ]]; then + gid=${group##*:} + group=${group%%:*} + fixed_groups_code+="addgroup -g \"$gid\" \"$group\""$'\n' + else + groups_code+="addgroup \"$group\""$'\n' + fi + created_groups[$group]=1 + if [ "$first" ]; then + first_group="$group" + first= + else + remaining_groups+=("$group") + fi + groups+=("$group") + done < <(echo "$user_def" | shyaml get-values-0 groups 2>/dev/null) + + + ## + ## User create commands + ## + + uid=$(echo "$user_def" | shyaml get-value uid 2>/dev/null) + + useradd_options=( + "-D" ## don't assign a password + "-s" "/bin/false" ## default shell + ) + if [ "$uid" ]; then + useradd_options+=("-u" "$uid") ## force uid + fi + if [ "$first_group" ]; then + useradd_options+=("-G" "$first_group") ## force main group + fi + + code+="adduser ${useradd_options[*]} \"$user\""$'\n' + if [ "$allow_writeable_chroot" ]; then + code+="chown $user \"/home/$user\""$'\n' ## sanitize + else + code+="chown root:root \"/home/$user\""$'\n' ## sanitize + fi + code+="chmod 755 \"/home/$user\""$'\n' ## sanitize + password=$(echo "$user_def" | shyaml get-value password 2>/dev/null) || + password=$(gen_password 14) + code+="echo '$user:$password' | chpasswd"$'\n' + for group in "${remaining_groups[@]}"; do + code+="adduser \"$user\" \"$group\""$'\n' + done + + ## + ## Key managements + ## + + while read-0 key; do + keys+="$key"$'\n' + done < <(echo "$user_def" | shyaml get-values-0 -q keys) + if [ "$keys" ]; then + code+="mkdir -p \"/home/$user/.ssh\""$'\n' + code+="cat < /home/$user/.ssh/authorized_keys"$'\n' + code+="$keys" + code+="EOF"$'\n' + # code+="chown $user /home/$user/.ssh/authorized_keys"$'\n' + code+="chmod 644 /home/$user/.ssh/authorized_keys"$'\n' + code+="chmod 755 /home/$user/.ssh"$'\n' + + fi + + done < <(echo "$users_def" | shyaml key-values-0) + { + echo -n "$fixed_groups_code" + echo -n "$groups_code" + echo -n "$code" + } | tee "$cache_file" +} \ No newline at end of file diff --git a/sftp/metadata.yml b/sftp/metadata.yml index 3ee84f4..acac032 100644 --- a/sftp/metadata.yml +++ b/sftp/metadata.yml @@ -1,8 +1,6 @@ -docker-image: docker.0k.io/sftp:carif -config-resources: - - /etc/sftp-users.conf data-resources: - /home provides: sftp-access: tech-dep: False +