300 lines
7.9 KiB

  1. #!/bin/bash
  2. ## Init is run on host
  3. ## For now it is run every time the script is launched, but
  4. ## it should be launched only once after build.
  5. ## Accessible variables are:
  6. ## - SERVICE_NAME Name of current service
  7. ## - DOCKER_BASE_IMAGE Base image from which this service might be built if any
  8. ## - SERVICE_DATASTORE Location on host of the DATASTORE of this service
  9. ## - SERVICE_CONFIGSTORE Location on host of the CONFIGSTORE of this service
  10. . lib/common || exit 1
  11. CONFIGFILE="$SERVICE_CONFIGSTORE/etc/vsftpd/vsftpd.conf"
  12. VSFTP_OPTIONS=(
  13. ##
  14. ## Feature not yet supported (and removed for simplicity's sake, and
  15. ## because implication were not though through yet), or in dire need
  16. ## of YAML simplification in the options.
  17. ##
  18. ## No support for anon user for now (for simplification purpose)
  19. #"allow_anon_ssl:bool" "anon_mkdir_write_enable:bool" "anon_other_write_enable:bool"
  20. #"anon_upload_enable:bool" "anon_world_readable_only:bool" "anonymous_enable:bool"
  21. #"force_anon_data_ssl:bool" "force_anon_logins_ssl:bool"
  22. #"no_anon_password:bool"
  23. #"anon_root:string" "chown_username:string" "ftp_username:string"
  24. #"anon_max_rate:numeric" "anon_umask:numeric"
  25. ## No support for chroot list
  26. #"chroot_list_enable:bool"
  27. #"connect_from_port_20:bool" ## port not propagated yet to host
  28. ## No support for that (requires more YAML love to list emails)
  29. #"secure_email_list_enable:bool"
  30. #"user_config_dir:string"
  31. ## To simplify usage
  32. #"userlist_deny:bool"
  33. #"userlist_enable:bool"
  34. ##
  35. ## Not sure if we need that
  36. ##
  37. #"deny_email_enable:bool"
  38. #"guest_enable:bool" "setproctitle_enable:bool"
  39. #"session_support:bool" "tcp_wrappers:bool"
  40. #"banned_email_file:string" "guest_username:string"
  41. #"pam_service_name:string" "ftp_data_port:numeric"
  42. ##
  43. ## Set by design
  44. ##
  45. ## Alway background by design (as a dockerized process)
  46. # "background:bool" "listen:bool"
  47. ## Using local user functionality
  48. #"chroot_local_user:bool"
  49. #"local_enable:bool"
  50. #"passwd_chroot_enable:bool"
  51. #"virtual_use_local_privs:bool"
  52. #"chroot_list_file:string"
  53. #"email_password_file:string"
  54. #"user_sub_token:string"
  55. #"userlist_file:string"
  56. ## Logging options are simplified
  57. #"dual_log_enable:bool" "log_ftp_protocol:bool" "no_log_lock:bool"
  58. #"syslog_enable:bool"
  59. #"xferlog_enable:bool" "xferlog_std_format:bool"
  60. #"vsftpd_log_file:string" "xferlog_file:string"
  61. ## Managed by ``ssl`` options
  62. #"implicit_ssl:bool"
  63. #"ssl_enable:bool" "ssl_request_cert:bool" "ssl_sslv2:bool" "ssl_sslv3:bool"
  64. #"ssl_tlsv1:bool"
  65. #"ca_certs_file:string"
  66. #"dsa_cert_file:string"
  67. #"dsa_private_key_file:string"
  68. #"rsa_cert_file:string"
  69. #"rsa_private_key_file:string"
  70. #"ssl_ciphers:string"
  71. ## Obscure option not really needed
  72. #"one_process_model:bool"
  73. ## Managed by ``pasv`` options
  74. #"pasv_addr_resolve:bool" "pasv_enable:bool"
  75. #"pasv_promiscuous:bool"
  76. #"pasv_max_port:numeric" "pasv_min_port:numeric"
  77. #"pasv_address:string"
  78. ## We use root user in docker to launch vsftp
  79. #"run_as_launching_user:bool"
  80. ## We don't need to change this in docker
  81. #"listen_port:numeric"
  82. #"listen_address:string" "listen_address6:string"
  83. ## Hum, should not be of charm users concern
  84. #"nopriv_user:string"
  85. #"secure_chroot_dir:string"
  86. ##
  87. ## Permitted
  88. ##
  89. ## commands
  90. "chmod_enable:bool" "dirlist_enable:bool" "download_enable:bool"
  91. "port_enable:bool" "ls_recurse_enable:bool" "write_enable:bool"
  92. ## others
  93. "dirmessage_enable:bool" "ascii_download_enable:bool"
  94. "ascii_upload_enable:bool" "async_abor_enable:bool"
  95. "check_shell:bool" "chown_uploads:bool" "debug_ssl:bool"
  96. "delete_failed_uploads:bool" "force_dot_files:bool"
  97. "hide_ids:bool" "listen_ipv6:bool" "lock_upload_files:bool"
  98. "mdtm_write:bool" "port_promiscuous:bool" "require_cert:bool"
  99. "require_ssl_reuse:bool" "strict_ssl_read_eof:bool"
  100. "strict_ssl_write_shutdown:bool" "text_userdb_names:bool"
  101. "tilde_user_enable:bool" "use_localtime:bool" "use_sendfile:bool"
  102. "validate_cert:bool"
  103. ## timeouts
  104. "accept_timeout:numeric" "connect_timeout:numeric" "data_connection_timeout:numeric"
  105. "idle_session_timeout:numeric"
  106. ## delays
  107. "delay_failed_login:numeric" "delay_successful_login:numeric"
  108. ## modes
  109. "chown_upload_mode:numeric" "file_open_mode:numeric"
  110. "local_max_rate:numeric" "local_umask:numeric"
  111. "max_clients:numeric" "max_login_fails:numeric" "max_per_ip:numeric"
  112. "trans_chunk_size:numeric"
  113. "banner_file:string"
  114. "cmds_allowed:string" "cmds_denied:string"
  115. "deny_file:string" "ftpd_banner:string" "hide_file:string"
  116. "local_root:string" "message_file:string"
  117. "force_local_data_ssl:bool" "force_local_logins_ssl:bool"
  118. "allow_writeable_chroot:bool"
  119. )
  120. VSFTP_OPTIONS_CONCAT=" ${VSFTP_OPTIONS[*]} "
  121. get_ips_from_hostname() {
  122. local hostname="$1"
  123. getent hosts "$hostname" | awk '{ print $1 }'
  124. }
  125. get_ip_from_hostname() {
  126. local hostname="$1"
  127. get_ips_from_hostname "$hostname" | head -n 1
  128. }
  129. mkdir -p "$(dirname "$CONFIGFILE")"
  130. service_def=$(get_compose_service_def "$SERVICE_NAME") || return 1
  131. domain=
  132. users=
  133. pasv=
  134. ssl=
  135. while read-0 key val; do
  136. key_option=${key//-/_}
  137. case "$VSFTP_OPTIONS_CONCAT" in
  138. *" ${key_option}:bool "*)
  139. case "${val,,}" in
  140. true|ok|yes|y)
  141. val=yes
  142. ;;
  143. false|ko|nok|no|n)
  144. val=no
  145. ;;
  146. *)
  147. die "Invalid value for ${WHITE}$key$NORMAL, please use a boolean value."
  148. ;;
  149. esac
  150. ;;
  151. *" ${key_option}:numeric "*)
  152. if ! is_int "$val"; then
  153. die "Invalid value for ${WHITE}$key$NORMAL, please use numeric value."
  154. fi
  155. ;;
  156. *" ${key_option}:string "*)
  157. :
  158. ;;
  159. *)
  160. case "${key//_/-}" in
  161. users) users="$val";;
  162. pasv) pasv="$val";;
  163. ssl) ssl="$val";;
  164. domain) domain="$val";;
  165. *) die "Unknown option ${WHITE}$key$NORMAL.";;
  166. esac
  167. continue
  168. ;;
  169. esac
  170. case "$key_option" in
  171. allow_writeable_chroot)
  172. allow_writeable_chroot=1
  173. ;;
  174. esac
  175. printf "%s=%s\n" "$key_option" "$val"
  176. done < <(printf "%s" "$service_def" | shyaml key-values-0 options) > "$CONFIGFILE"
  177. if [ -z "$domain" ]; then
  178. if [[ "$SERVICE_NAME" =~ ^([a-z0-9]+(-[a-z0-9]+)*\.)+[a-z]{2,}$ ]]; then
  179. domain="$SERVICE_NAME"
  180. fi
  181. fi
  182. make_pasv_options "$pasv" "$domain" >> "$CONFIGFILE" || exit 1
  183. make_ssl_options "$ssl" "$domain" >> "$CONFIGFILE" || exit 1
  184. ## Logs
  185. cat <<EOF >> "$CONFIGFILE"
  186. ##
  187. ## Logs
  188. ##
  189. syslog_enable=no
  190. dual_log_enable=no
  191. vsftpd_log_file=/var/log/vsftp/vsftp.log
  192. xferlog_enable=yes
  193. xferlog_std_format=no
  194. EOF
  195. ## Dockerisation means those
  196. cat <<EOF >> "$CONFIGFILE"
  197. ##
  198. ## Dockerisation
  199. ##
  200. background=no
  201. ## we don't use that feature
  202. passwd_chroot_enable=no
  203. ##
  204. ## Use local system passwd account
  205. ##
  206. local_enable=yes
  207. chroot_local_user=yes
  208. ## Seem to be required to avoid 500 OOOps child died
  209. seccomp_sandbox=no
  210. EOF
  211. ##
  212. ## Users
  213. ##
  214. ## Note: this creates a file that will be interpreted in the
  215. ## entrypoint of the docker image. It also creates group with same gid
  216. ## on host to be able to easily share files.
  217. build_script="$(make_build_script "$users" "$allow_writeable_chroot")" || exit 1
  218. echo "build-script:" >&2
  219. echo "$build_script" | prefix " $GRAY|$NORMAL " >&2
  220. docker_update "$SERVICE_NAME" "$build_script" -v "$SERVICE_DATASTORE/home":"/home" || exit 1
  221. config_hash=$(
  222. {
  223. printf "%s\0" "$build_script" "$(cat "$CONFIGFILE")"
  224. } | md5_compat) || exit 1
  225. init-config-add "
  226. $MASTER_BASE_SERVICE_NAME:
  227. labels:
  228. - compose.config_hash=$config_hash
  229. "