forked from 0k/0k-charms
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
292 lines
8.4 KiB
292 lines
8.4 KiB
# -*- 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"
|
|
}
|