300 lines
7.9 KiB
300 lines
7.9 KiB
#!/bin/bash
|
|
|
|
## Init is run on host
|
|
## For now it is run every time the script is launched, but
|
|
## it should be launched only once after build.
|
|
|
|
## Accessible variables are:
|
|
## - SERVICE_NAME Name of current service
|
|
## - DOCKER_BASE_IMAGE Base image from which this service might be built if any
|
|
## - SERVICE_DATASTORE Location on host of the DATASTORE of this service
|
|
## - SERVICE_CONFIGSTORE Location on host of the CONFIGSTORE of this service
|
|
|
|
|
|
. lib/common || exit 1
|
|
|
|
|
|
CONFIGFILE="$SERVICE_CONFIGSTORE/etc/vsftpd/vsftpd.conf"
|
|
|
|
|
|
VSFTP_OPTIONS=(
|
|
|
|
##
|
|
## Feature not yet supported (and removed for simplicity's sake, and
|
|
## because implication were not though through yet), or in dire need
|
|
## of YAML simplification in the options.
|
|
##
|
|
|
|
## No support for anon user for now (for simplification purpose)
|
|
#"allow_anon_ssl:bool" "anon_mkdir_write_enable:bool" "anon_other_write_enable:bool"
|
|
#"anon_upload_enable:bool" "anon_world_readable_only:bool" "anonymous_enable:bool"
|
|
#"force_anon_data_ssl:bool" "force_anon_logins_ssl:bool"
|
|
#"no_anon_password:bool"
|
|
#"anon_root:string" "chown_username:string" "ftp_username:string"
|
|
#"anon_max_rate:numeric" "anon_umask:numeric"
|
|
|
|
## No support for chroot list
|
|
#"chroot_list_enable:bool"
|
|
|
|
#"connect_from_port_20:bool" ## port not propagated yet to host
|
|
|
|
## No support for that (requires more YAML love to list emails)
|
|
#"secure_email_list_enable:bool"
|
|
#"user_config_dir:string"
|
|
|
|
## To simplify usage
|
|
#"userlist_deny:bool"
|
|
#"userlist_enable:bool"
|
|
|
|
|
|
##
|
|
## Not sure if we need that
|
|
##
|
|
|
|
#"deny_email_enable:bool"
|
|
#"guest_enable:bool" "setproctitle_enable:bool"
|
|
#"session_support:bool" "tcp_wrappers:bool"
|
|
#"banned_email_file:string" "guest_username:string"
|
|
#"pam_service_name:string" "ftp_data_port:numeric"
|
|
|
|
|
|
##
|
|
## Set by design
|
|
##
|
|
|
|
## Alway background by design (as a dockerized process)
|
|
# "background:bool" "listen:bool"
|
|
|
|
## Using local user functionality
|
|
#"chroot_local_user:bool"
|
|
#"local_enable:bool"
|
|
#"passwd_chroot_enable:bool"
|
|
#"virtual_use_local_privs:bool"
|
|
#"chroot_list_file:string"
|
|
#"email_password_file:string"
|
|
#"user_sub_token:string"
|
|
#"userlist_file:string"
|
|
|
|
## Logging options are simplified
|
|
#"dual_log_enable:bool" "log_ftp_protocol:bool" "no_log_lock:bool"
|
|
#"syslog_enable:bool"
|
|
#"xferlog_enable:bool" "xferlog_std_format:bool"
|
|
#"vsftpd_log_file:string" "xferlog_file:string"
|
|
|
|
## Managed by ``ssl`` options
|
|
#"implicit_ssl:bool"
|
|
#"ssl_enable:bool" "ssl_request_cert:bool" "ssl_sslv2:bool" "ssl_sslv3:bool"
|
|
#"ssl_tlsv1:bool"
|
|
#"ca_certs_file:string"
|
|
#"dsa_cert_file:string"
|
|
#"dsa_private_key_file:string"
|
|
#"rsa_cert_file:string"
|
|
#"rsa_private_key_file:string"
|
|
#"ssl_ciphers:string"
|
|
|
|
## Obscure option not really needed
|
|
#"one_process_model:bool"
|
|
|
|
## Managed by ``pasv`` options
|
|
#"pasv_addr_resolve:bool" "pasv_enable:bool"
|
|
#"pasv_promiscuous:bool"
|
|
#"pasv_max_port:numeric" "pasv_min_port:numeric"
|
|
#"pasv_address:string"
|
|
|
|
## We use root user in docker to launch vsftp
|
|
#"run_as_launching_user:bool"
|
|
|
|
## We don't need to change this in docker
|
|
#"listen_port:numeric"
|
|
#"listen_address:string" "listen_address6:string"
|
|
|
|
## Hum, should not be of charm users concern
|
|
#"nopriv_user:string"
|
|
#"secure_chroot_dir:string"
|
|
|
|
|
|
##
|
|
## Permitted
|
|
##
|
|
|
|
## commands
|
|
"chmod_enable:bool" "dirlist_enable:bool" "download_enable:bool"
|
|
"port_enable:bool" "ls_recurse_enable:bool" "write_enable:bool"
|
|
|
|
## others
|
|
"dirmessage_enable:bool" "ascii_download_enable:bool"
|
|
"ascii_upload_enable:bool" "async_abor_enable:bool"
|
|
"check_shell:bool" "chown_uploads:bool" "debug_ssl:bool"
|
|
"delete_failed_uploads:bool" "force_dot_files:bool"
|
|
"hide_ids:bool" "listen_ipv6:bool" "lock_upload_files:bool"
|
|
"mdtm_write:bool" "port_promiscuous:bool" "require_cert:bool"
|
|
"require_ssl_reuse:bool" "strict_ssl_read_eof:bool"
|
|
"strict_ssl_write_shutdown:bool" "text_userdb_names:bool"
|
|
"tilde_user_enable:bool" "use_localtime:bool" "use_sendfile:bool"
|
|
"validate_cert:bool"
|
|
|
|
## timeouts
|
|
"accept_timeout:numeric" "connect_timeout:numeric" "data_connection_timeout:numeric"
|
|
"idle_session_timeout:numeric"
|
|
|
|
## delays
|
|
"delay_failed_login:numeric" "delay_successful_login:numeric"
|
|
|
|
## modes
|
|
"chown_upload_mode:numeric" "file_open_mode:numeric"
|
|
|
|
"local_max_rate:numeric" "local_umask:numeric"
|
|
|
|
"max_clients:numeric" "max_login_fails:numeric" "max_per_ip:numeric"
|
|
"trans_chunk_size:numeric"
|
|
|
|
"banner_file:string"
|
|
|
|
"cmds_allowed:string" "cmds_denied:string"
|
|
|
|
"deny_file:string" "ftpd_banner:string" "hide_file:string"
|
|
"local_root:string" "message_file:string"
|
|
|
|
"force_local_data_ssl:bool" "force_local_logins_ssl:bool"
|
|
|
|
"allow_writeable_chroot:bool"
|
|
)
|
|
|
|
VSFTP_OPTIONS_CONCAT=" ${VSFTP_OPTIONS[*]} "
|
|
|
|
get_ips_from_hostname() {
|
|
local hostname="$1"
|
|
getent hosts "$hostname" | awk '{ print $1 }'
|
|
}
|
|
|
|
|
|
get_ip_from_hostname() {
|
|
local hostname="$1"
|
|
get_ips_from_hostname "$hostname" | head -n 1
|
|
}
|
|
|
|
|
|
mkdir -p "$(dirname "$CONFIGFILE")"
|
|
|
|
service_def=$(get_compose_service_def "$SERVICE_NAME") || return 1
|
|
domain=
|
|
users=
|
|
pasv=
|
|
ssl=
|
|
while read-0 key val; do
|
|
key_option=${key//-/_}
|
|
case "$VSFTP_OPTIONS_CONCAT" in
|
|
*" ${key_option}:bool "*)
|
|
case "${val,,}" in
|
|
true|ok|yes|y)
|
|
val=yes
|
|
;;
|
|
false|ko|nok|no|n)
|
|
val=no
|
|
;;
|
|
*)
|
|
die "Invalid value for ${WHITE}$key$NORMAL, please use a boolean value."
|
|
;;
|
|
esac
|
|
;;
|
|
*" ${key_option}:numeric "*)
|
|
if ! is_int "$val"; then
|
|
die "Invalid value for ${WHITE}$key$NORMAL, please use numeric value."
|
|
fi
|
|
;;
|
|
*" ${key_option}:string "*)
|
|
:
|
|
;;
|
|
*)
|
|
case "${key//_/-}" in
|
|
users) users="$val";;
|
|
pasv) pasv="$val";;
|
|
ssl) ssl="$val";;
|
|
domain) domain="$val";;
|
|
*) die "Unknown option ${WHITE}$key$NORMAL.";;
|
|
esac
|
|
continue
|
|
;;
|
|
esac
|
|
case "$key_option" in
|
|
allow_writeable_chroot)
|
|
allow_writeable_chroot=1
|
|
;;
|
|
esac
|
|
printf "%s=%s\n" "$key_option" "$val"
|
|
done < <(printf "%s" "$service_def" | shyaml key-values-0 options) > "$CONFIGFILE"
|
|
|
|
if [ -z "$domain" ]; then
|
|
if [[ "$SERVICE_NAME" =~ ^([a-z0-9]+(-[a-z0-9]+)*\.)+[a-z]{2,}$ ]]; then
|
|
domain="$SERVICE_NAME"
|
|
fi
|
|
fi
|
|
|
|
make_pasv_options "$pasv" "$domain" >> "$CONFIGFILE" || exit 1
|
|
make_ssl_options "$ssl" "$domain" >> "$CONFIGFILE" || exit 1
|
|
|
|
|
|
## Logs
|
|
|
|
cat <<EOF >> "$CONFIGFILE"
|
|
##
|
|
## Logs
|
|
##
|
|
|
|
syslog_enable=no
|
|
dual_log_enable=no
|
|
vsftpd_log_file=/var/log/vsftp/vsftp.log
|
|
xferlog_enable=yes
|
|
xferlog_std_format=no
|
|
EOF
|
|
|
|
## Dockerisation means those
|
|
|
|
cat <<EOF >> "$CONFIGFILE"
|
|
|
|
##
|
|
## Dockerisation
|
|
##
|
|
|
|
background=no
|
|
## we don't use that feature
|
|
passwd_chroot_enable=no
|
|
|
|
##
|
|
## Use local system passwd account
|
|
##
|
|
|
|
local_enable=yes
|
|
chroot_local_user=yes
|
|
|
|
## Seem to be required to avoid 500 OOOps child died
|
|
seccomp_sandbox=no
|
|
|
|
EOF
|
|
|
|
|
|
|
|
##
|
|
## Users
|
|
##
|
|
|
|
## Note: this creates a file that will be interpreted in the
|
|
## entrypoint of the docker image. It also creates group with same gid
|
|
## on host to be able to easily share files.
|
|
|
|
build_script="$(make_build_script "$users" "$allow_writeable_chroot")" || 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
|
|
|
|
config_hash=$(
|
|
{
|
|
printf "%s\0" "$build_script" "$(cat "$CONFIGFILE")"
|
|
} | md5_compat) || exit 1
|
|
|
|
init-config-add "
|
|
$MASTER_BASE_SERVICE_NAME:
|
|
labels:
|
|
- compose.config_hash=$config_hash
|
|
"
|
|
|