forked from 0k/0k-charms
Valentin Lab
6 years ago
4 changed files with 638 additions and 0 deletions
@ -0,0 +1,5 @@ |
|||||
|
FROM alpine:3.7 |
||||
|
|
||||
|
RUN apk add --no-cache vsftpd |
||||
|
|
||||
|
CMD /usr/sbin/vsftpd /etc/vsftpd/vsftpd.conf |
@ -0,0 +1,300 @@ |
|||||
|
#!/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 |
||||
|
" |
||||
|
|
@ -0,0 +1,292 @@ |
|||||
|
# -*- mode: shell-script -*- |
||||
|
|
||||
|
|
||||
|
ssl_get_plugin_fun() { |
||||
|
local cfg="$1" |
||||
|
|
||||
|
type="$(echo "$cfg" | shyaml -y get-type 2>/dev/null)" || return 1 |
||||
|
case "$type" in |
||||
|
bool) |
||||
|
err "Option ${WHITE}ssl${NORMAL} value '$cfg' is not supported." |
||||
|
return 1 |
||||
|
;; |
||||
|
str) |
||||
|
keys=("$cfg") |
||||
|
;; |
||||
|
struct) |
||||
|
keys=( $(echo "$cfg" | shyaml keys 2>/dev/null) ) |
||||
|
;; |
||||
|
*) |
||||
|
err "Invalid ${WHITE}ssl${NORMAL} value type '$type': please provide a string or a struct." |
||||
|
return 1 |
||||
|
;; |
||||
|
esac |
||||
|
|
||||
|
for key in "${keys[@]}"; do |
||||
|
target_relation="cert-provider" |
||||
|
fun="ssl_plugin_${target_relation}" |
||||
|
while read-0 relation_name target_service relation_config tech_dep; do |
||||
|
[ "$relation_name" == "${target_relation}" ] || continue |
||||
|
[ "$target_service" == "$key" ] || continue |
||||
|
verb "Corresponding plugin ${DARKGREEN}found${NORMAL}" \ |
||||
|
"in ${DARKBLUE}$relation_name${NORMAL}/${DARKYELLOW}$key${NORMAL}" |
||||
|
ssl_cfg=$(printf "%s" "$cfg" | shyaml get-value "$key" 2>/dev/null) || true |
||||
|
merged_config=$(merge_yaml_str "$relation_config" "$ssl_cfg") || return 1 |
||||
|
printf "%s\0" "$fun" "$key" "$merged_config" |
||||
|
return 0 |
||||
|
done < <(get_service_relations "$SERVICE_NAME") || return 1 |
||||
|
case "$key" in |
||||
|
cert|ca-cert|key) |
||||
|
: |
||||
|
;; |
||||
|
*) |
||||
|
err "Invalid key '$key' in ${WHITE}ssl${NORMAL}:" \ |
||||
|
"no corresponding services declared in ${DARKBLUE}${target_relation}$NORMAL" |
||||
|
return 1 |
||||
|
;; |
||||
|
esac |
||||
|
done |
||||
|
} |
||||
|
|
||||
|
|
||||
|
ssl_fallback_vars() { |
||||
|
local cfg="$1" DOMAIN="$2" cert key ca_cert |
||||
|
|
||||
|
base_dir=/etc/ssl |
||||
|
print "%s\0" \ |
||||
|
"$base_dir"/certs/"${DOMAIN}".pem \ |
||||
|
"$base_dir"/private/"${DOMAIN}".key \ |
||||
|
"$base_dir"/certs/"${DOMAIN}"-ca.pem |
||||
|
|
||||
|
print "%s\0" "$base_dir"/cert.pem "$base_dir"/privkey.pem "$base_dir"/chain.pem |
||||
|
} |
||||
|
|
||||
|
|
||||
|
ssl_fallback_prepare() { |
||||
|
local cfg="$1" service="$2" l_cert l_key l_ca_cert |
||||
|
|
||||
|
shift 2 |
||||
|
read-0 l_cert l_key l_ca_cert < <(ssl_fallback_vars "$cfg" "$@") |
||||
|
|
||||
|
dst="$CONFIGSTORE/$BASE_SERVICE_NAME" |
||||
|
volumes="" |
||||
|
for label in cert key ca-cert; do |
||||
|
if content=$(echo "$cfg" | shyaml get-value "$label" 2>/dev/null); then |
||||
|
location="$(eval echo "\$l_${label//-/_}")" |
||||
|
echo "$content" | file_put "$dst$location" |
||||
|
config_hash=$(printf "%s\0" "$config_hash" "$label" "$content" | md5_compat) |
||||
|
volumes="$volumes |
||||
|
- $dst$location:$location:ro" |
||||
|
fi |
||||
|
done |
||||
|
|
||||
|
if [ "$volumes" ]; then |
||||
|
init-config-add "\ |
||||
|
$MASTER_TARGET_SERVICE_NAME: |
||||
|
volumes: |
||||
|
$volumes |
||||
|
" |
||||
|
fi |
||||
|
|
||||
|
} |
||||
|
|
||||
|
ssl_plugin_cert-provider_vars() { |
||||
|
local cfg="$1" DOMAIN="$2" |
||||
|
|
||||
|
base_dir="/etc/letsencrypt/live/$DOMAIN" |
||||
|
|
||||
|
print "%s\0" "$base_dir"/cert.pem "$base_dir"/privkey.pem "$base_dir"/chain.pem |
||||
|
} |
||||
|
|
||||
|
ssl_plugin_cert-provider_prepare() { |
||||
|
local cfg="$1" service="$2" options |
||||
|
shift 2 |
||||
|
|
||||
|
options=$(yaml_key_val_str "options" "$cfg") || return 1 |
||||
|
service_config=$(yaml_key_val_str "$service" "$options") |
||||
|
compose --debug --add-compose-content "$service_config" run --rm --service-ports "$service" \ |
||||
|
crt create "$@" || { |
||||
|
err "Failed to launch letsencrypt for certificate creation." |
||||
|
return 1 |
||||
|
} |
||||
|
init-config-add "\ |
||||
|
$MASTER_TARGET_SERVICE_NAME: |
||||
|
volumes: |
||||
|
- $DATASTORE/$service/etc/letsencrypt:/etc/letsencrypt:ro |
||||
|
" || return 1 |
||||
|
} |
||||
|
|
||||
|
|
||||
|
make_pasv_options() { |
||||
|
local pasv="$1" |
||||
|
if [[ "${pasv,,}" =~ ^(false|no|n|0|disable|disabled)$ ]]; then |
||||
|
echo "pasv_enable=no" |
||||
|
return 0 |
||||
|
fi |
||||
|
|
||||
|
ports="$(printf "%s" "$pasv" | shyaml get-value -q "ports")" |
||||
|
if [ "$ports" ]; then |
||||
|
if [[ "$ports" =~ ^[0-9]+-[0-9]+$ ]]; then |
||||
|
port_min=${ports##*-} |
||||
|
port_max=${ports%%-*} |
||||
|
if [ "$port_min" -gt "$port_max" ]; then |
||||
|
die "Invalid value for ${WHITE}ports${NORMAL}: first port in range has to be lesser than second." |
||||
|
fi |
||||
|
else |
||||
|
die "Invalid value for ${WHITE}ports${NORMAL}: please specify a port range (ie: '123-345')." |
||||
|
fi |
||||
|
fi |
||||
|
|
||||
|
port_min=${port_min:-21100} |
||||
|
port_max=${port_max:-21110} |
||||
|
|
||||
|
host_address="$(printf "%s" "$pasv" | shyaml get-value -q "address")" |
||||
|
if [ -z "$host_address" ]; then |
||||
|
if [[ "$SERVICE_NAME" =~ ^([a-z0-9]+(-[a-z0-9]+)*\.)+[a-z]{2,}$ ]]; then |
||||
|
host_address="$SERVICE_NAME" |
||||
|
fi |
||||
|
fi |
||||
|
|
||||
|
if [ -z "$host_address" ]; then |
||||
|
echo "## Could not find appropriate host return address" |
||||
|
echo "pasv_enable=no" |
||||
|
return 0 |
||||
|
fi |
||||
|
|
||||
|
if ! str_is_ipv4 "$host_address"; then |
||||
|
host_address="$(get_ip_from_hostname "$host_address")" || { |
||||
|
err "Can't resolve given hostname '$host_address'" |
||||
|
return 1 |
||||
|
} |
||||
|
else |
||||
|
err "You should NOT provide a direct IP for ${WHITE}pasv.address${NORMAL}," \ |
||||
|
"try a resolvable address." |
||||
|
return 1 |
||||
|
fi |
||||
|
cat <<EOF |
||||
|
pasv_address=$host_address |
||||
|
pasv_enable=yes |
||||
|
pasv_min_port=$port_min |
||||
|
pasv_max_port=$port_max |
||||
|
EOF |
||||
|
|
||||
|
init-config-add " |
||||
|
$SERVICE_NAME: |
||||
|
ports: |
||||
|
- \"$port_min-$port_max:$port_min-$port_max\" |
||||
|
" |
||||
|
|
||||
|
} |
||||
|
|
||||
|
|
||||
|
make_ssl_options() { |
||||
|
local ssl="$1" |
||||
|
if [ -z "$ssl" ]; then |
||||
|
target_relation="cert-provider" |
||||
|
ssl=no |
||||
|
while read-0 rn ts rc td; do |
||||
|
[ "$rn" == "${target_relation}" ] || continue |
||||
|
info "A ${DARKBLUE}$target_relation${NORMAL} ${DARKYELLOW}$ts${NORMAL} declared as 'ssl' value" |
||||
|
ssl="$ts" |
||||
|
break |
||||
|
done < <(get_service_relations "$SERVICE_NAME") |
||||
|
fi |
||||
|
if [[ "${ssl,,}" =~ false|no|n|0|disable|disabled ]]; then |
||||
|
echo "ssl_enable=no" |
||||
|
return 0 |
||||
|
fi |
||||
|
|
||||
|
cat <<EOF |
||||
|
## |
||||
|
## SSL conf |
||||
|
## |
||||
|
|
||||
|
ssl_enable=yes |
||||
|
ssl_tlsv1=yes |
||||
|
ssl_sslv2=no |
||||
|
ssl_sslv3=no |
||||
|
ssl_ciphers=HIGH |
||||
|
implicit_ssl=no |
||||
|
|
||||
|
EOF |
||||
|
read-0 SSL_PLUGIN_FUN SSL_CFG_VALUE SSL_CFG_OPTIONS < <(ssl_get_plugin_fun "$ssl") || return 1 |
||||
|
read-0 cert key ca_cert < <("$SSL_PLUGIN_FUN"_vars "$SSL_CFG_OPTIONS" "$SSL_CFG_VALUE") || return 1 |
||||
|
"$SSL_PLUGIN_FUN"_prepare "$SSL_CFG_OPTIONS" "$SSL_CFG_VALUE" || return 1 |
||||
|
|
||||
|
cat <<EOF |
||||
|
|
||||
|
rsa_cert_file=$cert |
||||
|
rsa_private_key_file=$key |
||||
|
ca_certs_file=$ca_cert |
||||
|
|
||||
|
EOF |
||||
|
|
||||
|
} |
||||
|
|
||||
|
|
||||
|
make_build_script() { |
||||
|
local users_def="$1" allow_writeable_chroot="$2" |
||||
|
|
||||
|
if [ -z "$users_def" ]; then |
||||
|
return 0 |
||||
|
fi |
||||
|
|
||||
|
fixed_groups_code="" |
||||
|
groups_code="" |
||||
|
|
||||
|
declare -A created_groups |
||||
|
while read-0 user user_def; do |
||||
|
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 |
||||
|
echo "X" >&2 |
||||
|
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) |
||||
|
password=$(echo "$user_def" | shyaml get-value password 2>/dev/null) || |
||||
|
password=$(gen_password 14) |
||||
|
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' |
||||
|
code+="mkdir -p \"/home/$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 |
||||
|
code+="echo '$user:$password' | chpasswd"$'\n' |
||||
|
for group in "${remaining_groups[@]}"; do |
||||
|
code+="adduser \"$user\" \"$group\""$'\n' |
||||
|
done |
||||
|
done < <(echo "$users_def" | shyaml key-values-0) |
||||
|
echo -n "$fixed_groups_code" |
||||
|
echo -n "$groups_code" |
||||
|
echo -n "$code" |
||||
|
} |
@ -0,0 +1,41 @@ |
|||||
|
config-resources: |
||||
|
- /etc/vsftpd/vsftpd.conf |
||||
|
data-resources: |
||||
|
- /home |
||||
|
- /var/log/vsftp |
||||
|
|
||||
|
default-options: |
||||
|
ftpd-banner: "Welcome to FTP Server" |
||||
|
dirmessage-enable: yes |
||||
|
delay-failed-login: 2 |
||||
|
max-clients: 10 |
||||
|
max-per-ip: 5 |
||||
|
max-login-fails: 3 |
||||
|
|
||||
|
## to check what these are |
||||
|
write-enable: yes |
||||
|
local-umask: "022" ## remember to send a string here |
||||
|
|
||||
|
users: |
||||
|
|
||||
|
docker-compose: |
||||
|
ports: |
||||
|
- "21:21" |
||||
|
|
||||
|
provides: |
||||
|
ftp-access: |
||||
|
tech-dep: reversed |
||||
|
|
||||
|
|
||||
|
uses: |
||||
|
log-rotate: |
||||
|
constraint: recommended |
||||
|
auto: pair |
||||
|
solves: |
||||
|
disk-leak: "/var/log/vsftp" |
||||
|
cert-provider: |
||||
|
constraint: optional |
||||
|
auto: pair |
||||
|
limit: n |
||||
|
solves: |
||||
|
feature: "SSL certificate generation" |
Write
Preview
Loading…
Cancel
Save
Reference in new issue