#!/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 "