Browse Source

chg: dev: [apache] rewrite internal library to avoid global vars.

framadate
Valentin Lab 5 years ago
parent
commit
3bf728e895
  1. 3
      apache/hooks/publish_dir-relation-joined
  2. 3
      apache/hooks/web_proxy-relation-joined
  3. 363
      apache/lib/common
  4. 95
      apache/test/vhost
  5. 185
      apache/test/vhost_cert_provider
  6. 107
      apache/test/vhost_files

3
apache/hooks/publish_dir-relation-joined

@ -6,7 +6,8 @@
set -e
apache_publish_dir
cfg=$(relation-get)
apache_publish_dir "$cfg"
APACHE_CORE_RULES=$(relation-get apache-core-rules 2>/dev/null) || true
if [ "$APACHE_CORE_RULES" ]; then

3
apache/hooks/web_proxy-relation-joined

@ -5,7 +5,8 @@ set -e
. lib/common
apache_proxy_dir || exit 1
cfg=$(relation-get)
apache_proxy_dir "$cfg"
APACHE_CORE_RULES=$(relation-get apache-core-rules 2>/dev/null) || true
if [ "$APACHE_CORE_RULES" ]; then

363
apache/lib/common

@ -1,10 +1,10 @@
# -*- mode: shell-script -*-
config_hash=
get_domain() {
local cfg="$1"
get_domain () {
relation-get domain 2>/dev/null && return 0
e "$cfg" | cfg-get-value domain 2>/dev/null && return 0
## is service name a regex ?
if [[ "$BASE_SERVICE_NAME" =~ ^([a-z0-9]+(-[a-z0-9]+)*\.)+[a-z]{2,}$ ]]; then
@ -12,64 +12,71 @@ get_domain () {
return 0
fi
err "You must specify a ${WHITE}domain$NORMAL option in relation."
err "You must specify a ${WHITE}domain$NORMAL option in relation. (${FUNCNAME[@]})"
return 1
}
apache_proxy_dir () {
DOMAIN=$(get_domain) || return 1
relation-set domain "$DOMAIN"
proxy=yes apache_vhost_create || return 1
info "Added $DOMAIN as a proxy to $TARGET."
}
export -f apache_proxy_dir
##
## Master entrypoints
##
apache_publish_dir () {
DOMAIN=$(get_domain) || return 1
relation-set domain "$DOMAIN"
DOCKER_SITE_PATH="/var/www/${DOMAIN}"
LOCATION=$(relation-get location 2>/dev/null) ||
LOCATION="$DATASTORE/$BASE_SERVICE_NAME$DOCKER_SITE_PATH"
apache_proxy_dir() {
local cfg="$1" domain
apache_vhost_create web_proxy "$cfg" || return 1
}
export -f apache_proxy_dir
apache_vhost_create || return 1
info "Added $DOMAIN apache config."
apache_code_dir || return 1
apache_data_dirs
apache_publish_dir() {
local cfg="$1" domain
apache_vhost_create publish_dir "$cfg" || return 1
apache_code_dir "$cfg" || return 1
apache_data_dirs "$cfg"
}
export -f apache_publish_dir
apache_vhost_create () {
local custom_rules
export APACHE_CONFIG_LOCATION="$SERVICE_CONFIGSTORE/etc/apache2/sites-enabled" vhost_statement
SERVER_ALIAS=$(relation-get server-aliases 2>/dev/null) || true
PROTOCOLS=$(__vhost_cfg_normalize_protocol) || return 1
##
## Simple functions
##
export SERVER_ALIAS PROTOCOLS SSL_PLUGIN_FUN SSL_CFG_{VALUE,OPTION}
apache_vhost_create() {
local type="$1" cfg="$2" custom_rules vhost_statement creds
if is_protocol_enabled https; then
read-0 SSL_PLUGIN_FUN SSL_CFG_VALUE SSL_CFG_OPTIONS < <(ssl_get_plugin_fun) || return 1
"$SSL_PLUGIN_FUN"_vars "$SSL_CFG_OPTIONS" "$SSL_CFG_VALUE" || return 1
redirect=$(relation-get 'redirect-to-ssl' 2>/dev/null) || true
if is_protocol_enabled http; then
export APACHE_CONFIG_LOCATION="$SERVICE_CONFIGSTORE/etc/apache2/sites-enabled"
protocols=$(__vhost_cfg_normalize_protocol "$cfg") || return 1
if is_protocol_enabled https "$protocols"; then
read-0 ssl_plugin_fun ssl_cfg_value ssl_cfg_options < <(ssl_get_plugin_fun "$cfg") || return 1
"$ssl_plugin_fun"_vars "$cfg" "$ssl_cfg_options" "$ssl_cfg_value" || return 1
redirect=$(e "$cfg" | cfg-get-value 'redirect-to-ssl' 2>/dev/null) || true
if is_protocol_enabled http "$protocols"; then
redirect=${redirect:-true}
else
redirect=false
fi
if [ "$redirect" == "true" ]; then
custom_rules=$(_get_custom_rules) || return 1
custom_rules=$(_get_custom_rules "$cfg") || return 1
if [[ "$custom_rules" != *"## Auto-redirection from http to https"* ]]; then
relation-set apache-custom-rules "- |
redirect_rule="- |
## Auto-redirection from http to https
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [R=302,L,QSA]
"
relation-set apache-custom-rules "$redirect_rule
$(if [ "$custom_rules" ]; then
echo "- |"$'\n'"$(echo "$custom_rules" | prefix " ")"
fi)"
cfg=$(merge_yaml_str "$cfg" "$(yaml_key_val_str "apache-custom-rules" "$redirect_rule
$(if [ "$custom_rules" ]; then
echo "- |"$'\n'"$(echo "$custom_rules" | prefix " ")"
fi)")")
fi
relation-set protocol https
else
@ -80,30 +87,36 @@ $(if [ "$custom_rules" ]; then
else
relation-set protocol http
fi
vhost_statement=$(apache_vhost_statement "$PROTOCOLS") || return 1
echo "$vhost_statement"| file_put "$APACHE_CONFIG_LOCATION/$prefix$DOMAIN.conf" || return 1
vhost_statement=$(apache_vhost_statement "$type" "$protocols" "$cfg") || {
err "Failed to get vhost statement for type $type on ${protocols:1:-1}"
return 1
}
domain=$(get_domain "$cfg") || return 1
relation-set domain "$domain"
__vhost_cfg_creds_enabled=$(relation-get creds 2>/dev/null) || true
if [ "$__vhost_cfg_creds_enabled" ]; then
apache_passwd_file || return 1
echo "$vhost_statement"| file_put "$APACHE_CONFIG_LOCATION/$prefix$domain.conf" || return 1
creds=$(e "$cfg" | cfg-get-value creds 2>/dev/null) || true
if [ "$creds" ]; then
apache_passwd_file "$cfg" || return 1
fi
if is_protocol_enabled https; then
"$SSL_PLUGIN_FUN"_prepare "$SSL_CFG_OPTIONS" "$SSL_CFG_VALUE" || return 1
if is_protocol_enabled https "$protocols"; then
"$ssl_plugin_fun"_prepare "$cfg" "$ssl_cfg_options" "$ssl_cfg_value" || return 1
fi
}
is_protocol_enabled() {
local protocol=$1
[[ "$PROTOCOLS" == *",$protocol,"* ]]
local protocol="$1" protocols="$2"
[[ "$protocols" == *",$protocol,"* ]]
}
export -f is_protocol_enabled
_get_ssl_option_value() {
local target_relation rn ts rc td
relation-get ssl 2>/dev/null && return 0
local cfg="$1" target_relation rn ts rc td
e "$cfg" | cfg-get-value ssl 2>/dev/null && return 0
target_relation="cert-provider"
while read-0 rn ts rc td; do
@ -118,19 +131,29 @@ _get_ssl_option_value() {
__vhost_cfg_normalize_protocol() {
local protocol
if ! protocol=$(relation-get protocol 2>/dev/null); then
protocol=auto
else
local cfg="$1" protocol
## XXXvlab: can't cache if libcharm is not able to give me some checksums
## indeed, ``_get_ssl_option_value`` depends on relations calculations...
# local cfg="$1" cache_file="$CACHEDIR/$FUNCNAME.cache.$(p0 "$@" | md5_compat)" \
# protocol
# if [ -e "$cache_file" ]; then
# #debug "$FUNCNAME: STATIC cache hit $1"
# cat "$cache_file" &&
# touch "$cache_file" || return 1
# return 0
# fi
if protocol=$(e "$cfg" | cfg-get-value protocol 2>/dev/null); then
protocol=${protocol:-auto}
else
protocol=auto
fi
case "$protocol" in
auto)
if __vhost_cfg_ssl="$(_get_ssl_option_value)"; then
if _get_ssl_option_value "$cfg" >/dev/null 2>&1; then
protocol="http,https"
export __vhost_cfg_ssl
else
protocol="http"
fi
@ -149,24 +172,22 @@ __vhost_cfg_normalize_protocol() {
return 1
esac
echo ",$protocol,"
#| tee "$cache_file"
}
## ssl_plugin_* and ssl_fallback should :
## - do anything to ensure that
## - do anything to ensure that
## - issue config-add to add volumes if necessary
## - output 3 vars of where to find the 3 files from within the docker apache
ssl_get_plugin_fun() {
# from ssl conf, return the function that should manage SSL code creation
local cfg type keys
cfg=$(_get_ssl_option_value)
if [ -z "$cfg" ]; then
return 0
else
type="$(echo "$cfg" | shyaml -y get-type 2>/dev/null)" || return 1
fi
local master_cfg="$1" cfg type keys
cfg=$(_get_ssl_option_value "$master_cfg")
[ "$cfg" ] || return 0
type="$(echo "$cfg" | shyaml -y get-type 2>/dev/null)" || return 1
if [[ "$type" == "bool" ]]; then
printf "%s\0" "ssl_fallback" "" "$cfg"
echo ssl_fallback
@ -216,18 +237,19 @@ ssl_get_plugin_fun() {
ssl_fallback_vars() {
local cfg="$1" cert key ca_cert
local cfg="$1" ssl_cfg="$2" cert key ca_cert domain
domain=$(get_domain "$cfg") || return 1
if __vhost_cfg_ssl_cert=$(echo "$cfg" | shyaml get-value cert 2>/dev/null); then
__vhost_cfg_SSL_CERT_LOCATION=/etc/ssl/certs/${DOMAIN}.pem
if __vhost_cfg_ssl_cert=$(echo "$ssl_cfg" | shyaml get-value cert 2>/dev/null); then
__vhost_cfg_SSL_CERT_LOCATION=/etc/ssl/certs/${domain}.pem
fi
if __vhost_cfg_ssl_key=$(echo "$cfg" | shyaml get-value key 2>/dev/null); then
__vhost_cfg_SSL_KEY_LOCATION=/etc/ssl/private/${DOMAIN}.key
if __vhost_cfg_ssl_key=$(echo "$ssl_cfg" | shyaml get-value key 2>/dev/null); then
__vhost_cfg_SSL_KEY_LOCATION=/etc/ssl/private/${domain}.key
fi
if __vhost_cfg_ssl_ca_cert=$(echo "$cfg" | shyaml get-value ca-cert 2>/dev/null); then
__vhost_cfg_SSL_CA_CERT_LOCATION=/etc/ssl/certs/${DOMAIN}-ca.pem
if __vhost_cfg_ssl_ca_cert=$(echo "$ssl_cfg" | shyaml get-value ca-cert 2>/dev/null); then
__vhost_cfg_SSL_CA_CERT_LOCATION=/etc/ssl/certs/${domain}-ca.pem
fi
}
@ -259,19 +281,30 @@ $volumes
}
ssl_plugin_cert-provider_vars() {
local cfg="$1" ssl_cfg="$2"
domain=$(get_domain "$cfg") || return 1
__vhost_cfg_SSL_CERT_LOCATION=/etc/letsencrypt/live/${DOMAIN}/cert.pem
__vhost_cfg_SSL_KEY_LOCATION=/etc/letsencrypt/live/${DOMAIN}/privkey.pem
__vhost_cfg_SSL_CHAIN=/etc/letsencrypt/live/${DOMAIN}/chain.pem
__vhost_cfg_SSL_CERT_LOCATION=/etc/letsencrypt/live/${domain}/cert.pem
__vhost_cfg_SSL_KEY_LOCATION=/etc/letsencrypt/live/${domain}/privkey.pem
__vhost_cfg_SSL_CHAIN=/etc/letsencrypt/live/${domain}/chain.pem
}
ssl_plugin_cert-provider_prepare() {
local cfg="$1" service="$2" options
local cfg="$1" ssl_cfg="$2" service="$3" options domain server_aliases
domain=$(get_domain "$cfg") || return 1
options=$(yaml_key_val_str "options" "$cfg") || return 1
options=$(yaml_key_val_str "options" "$ssl_cfg") || return 1
service_config=$(yaml_key_val_str "$service" "$options")
server_aliases=$(e "$cfg" | cfg-get-value server-aliases 2>/dev/null) || true
[ "$server_aliases" == None ] && server_aliases=""
if [ "$server_aliases" ]; then
server_aliases=($(echo "$server_aliases" | shyaml get-values)) || return 1
else
server_aliases=()
fi
compose --debug --add-compose-content "$service_config" run --rm --service-ports "$service" \
crt create "$DOMAIN" $(echo "$SERVER_ALIAS" | shyaml get-values 2>/dev/null) || {
crt create "$domain" "${server_aliases[@]}" || {
err "Failed to launch letsencrypt for certificate creation."
return 1
}
@ -286,22 +319,24 @@ services:
apache_passwd_file() {
local cfg="$1" creds
include parse || true
## XXXvlab: called twice... no better way to do this ?
__vhost_creds_statement >/dev/null
creds=$(e "$cfg" | cfg-get-value creds 2>/dev/null) || true
password_path=$(password-path-get "$cfg")
first=
if ! [ -e "$CONFIGSTORE/$MASTER_TARGET_SERVICE_NAME$password_file" ]; then
debug "No file $CONFIGSTORE/$MASTER_TARGET_SERVICE_NAME$password_file, creating password file." || true
if ! [ -e "$CONFIGSTORE/$MASTER_TARGET_SERVICE_NAME$password_path" ]; then
debug "No file $CONFIGSTORE/$MASTER_TARGET_SERVICE_NAME$password_path, creating password file." || true
first=c
fi
while read-0 login password; do
debug "htpasswd -b$first '${password_file}' '$login' '$password'"
echo "htpasswd -b$first '${password_file}' '$login' '$password'"
debug "htpasswd -b$first '${password_path}' '$login' '$password'"
echo "htpasswd -b$first '${password_path}' '$login' '$password'"
if [ "$first" ]; then
first=
fi
done < <(echo "$__vhost_cfg_creds_enabled" | shyaml key-values-0 2>/dev/null) |
done < <(e "$creds" | shyaml key-values-0 2>/dev/null) |
docker run -i --entrypoint "/bin/bash" \
-v "$APACHE_CONFIG_LOCATION:/etc/apache2/sites-enabled" \
"$DOCKER_BASE_IMAGE" || return 1
@ -309,16 +344,16 @@ apache_passwd_file() {
## Produce the full statements depending on relation-get informations
apache_vhost_statement() {
local vhost_statement
export SERVER_ALIAS=$(relation-get server-aliases 2>/dev/null) || true
export PROTOCOLS="$1"
local type="$1" protocols="$2" cfg="$3" \
vhost_statement
if is_protocol_enabled http; then
__vhost_full_vhost_statement http || return 1
if is_protocol_enabled http "$protocols"; then
__vhost_full_vhost_statement "$type" http "$cfg" || return 1
fi
if is_protocol_enabled https; then
"$SSL_PLUGIN_FUN"_vars "$(_get_ssl_option_value 2>/dev/null)" || return 1
vhost_statement=$(__vhost_full_vhost_statement https) || return 1
if is_protocol_enabled https "$protocols"; then
read-0 ssl_plugin_fun ssl_cfg_value ssl_cfg_options < <(ssl_get_plugin_fun "$cfg") || return 1
"$ssl_plugin_fun"_vars "$cfg" "$ssl_cfg_options" "$ssl_cfg_value" || return 1
vhost_statement=$(__vhost_full_vhost_statement "$type" https "$cfg") || return 1
cat <<EOF
<IfModule mod_ssl.c>
@ -331,37 +366,42 @@ export -f apache_vhost_statement
apache_code_dir() {
local www_data_gid
local cfg="$1" www_data_gid local_path
www_data_gid=$(cached_cmd_on_base_image apache 'id -g www-data') || {
debug "Failed to query for www-data gid in ${DARKYELLOW}apache${NORMAL} base image."
return 1
}
domain=$(get_domain "$cfg") || return 1
local_path="/var/www/${domain}"
host_path=$(e "$cfg" | cfg-get-value location 2>/dev/null) ||
host_path="$DATASTORE/$BASE_SERVICE_NAME${local_path}"
mkdir -p "$LOCATION" || return 1
setfacl -R -m g:"$www_data_gid":rx "$LOCATION"
info "Set permission for read and traversal on '$LOCATION'."
mkdir -p "$host_path" || return 1
setfacl -R -m g:"$www_data_gid":rx "$host_path"
info "Set permission for read and traversal on '$host_path'."
config-add "
$MASTER_BASE_SERVICE_NAME:
volumes:
- $LOCATION:$DOCKER_SITE_PATH
- $host_path:$local_path
"
}
apache_data_dirs() {
DATA_DIRS=$(relation-get data-dirs 2>/dev/null | shyaml get-values 2>/dev/null) || true
if [ -z "$DATA_DIRS" ]; then
local cfg="$1" data_dirs dst data dirs
data_dirs=$(e "$cfg" | cfg-get-value data-dirs 2>/dev/null | shyaml get-values 2>/dev/null) || true
if [ -z "$data_dirs" ]; then
return 0
fi
DST=$DATASTORE/$BASE_SERVICE_NAME$DOCKER_SITE_PATH
DATA=()
while IFS="," read -ra ADDR; do
for dir in "${ADDR[@]}"; do
DATA+=($dir)
domain=$(get_domain "$cfg") || return 1
local_path="/var/www/${domain}"
dst=$DATASTORE/$BASE_SERVICE_NAME$local_path
data=()
while IFS="," read -ra addr; do
for dir in "${addr[@]}"; do
data+=($dir)
done
done <<< "$DATA_DIRS"
done <<< "$data_dirs"
www_data_gid=$(cached_cmd_on_base_image apache 'id -g www-data') || {
debug "Failed to query for www-data gid in ${DARKYELLOW}apache${NORMAL} base image."
@ -370,8 +410,8 @@ apache_data_dirs() {
info "www-data gid from ${DARKYELLOW}apache${NORMAL} is '$www_data_gid'"
dirs=()
for d in "${DATA[@]}"; do
dirs+=("$DST/$d")
for d in "${data[@]}"; do
dirs+=("$dst/$d")
done
mkdir -p "${dirs[@]}"
@ -382,8 +422,8 @@ apache_data_dirs() {
$MASTER_BASE_SERVICE_NAME:
volumes:
$(
for d in "${DATA[@]}"; do
echo " - $DST/$d:$DOCKER_SITE_PATH/$d"
for d in "${data[@]}"; do
echo " - $dst/$d:$local_path/$d"
done
)"
@ -443,18 +483,24 @@ EOF
}
password-path-get() {
local cfg="$1" domain
domain=$(get_domain "$cfg") || return 1
echo /etc/apache2/sites-enabled/${domain}.passwd
}
__vhost_creds_statement() {
if ! __vhost_cfg_creds_enabled=$(relation-get creds 2>/dev/null); then
local cfg="$1" password_path
password_path=$(password-path-get "$cfg") || return 1
if ! e "$cfg" | cfg-get-value creds >/dev/null 2>&1; then
echo "Allow from all"
return 0
fi
password_file=/etc/apache2/sites-enabled/${DOMAIN}.passwd
cat <<EOF
AuthType basic
AuthName "private"
AuthUserFile ${password_file}
AuthUserFile ${password_path}
Require valid-user
EOF
@ -462,7 +508,20 @@ EOF
__vhost_head_statement() {
local protocol="$1"
local cfg="$1" protocol="$2" server_aliases admin_mail
domain=$(get_domain "$cfg") || return 1
admin_mail=$(e "$1" | cfg-get-value "admin-mail" 2>/dev/null) || true
server_aliases=$(e "$cfg" | cfg-get-value server-aliases 2>/dev/null) || true
[ "$server_aliases" == None ] && server_aliases=""
if [ "$server_aliases" ]; then
server_aliases=($(e "$server_aliases" | shyaml get-values)) || return 1
if [ -z "$domain" ]; then
err "You can't specify server aliases if you don't have a domain."
return 1
fi
else
server_aliases=()
fi
if [ "$protocol" == "https" ]; then
prefix="s-"
@ -471,16 +530,17 @@ __vhost_head_statement() {
fi
cat <<EOF
ServerAdmin ${ADMIN_MAIL:-contact@$DOMAIN}
ServerName ${DOMAIN}
ServerAdmin ${admin_mail:-contact@$domain}
ServerName ${domain}
$(
while read-0 alias; do
for alias in "${server_aliases[@]}"; do
[ "$alias" ] || continue
echo "ServerAlias $alias"
done < <(echo "$SERVER_ALIAS" | shyaml get-values-0 2>/dev/null)
done
)
ServerSignature Off
CustomLog /var/log/apache2/${prefix}${DOMAIN}_access.log combined
ErrorLog /var/log/apache2/${prefix}${DOMAIN}_error.log
CustomLog /var/log/apache2/${prefix}${domain}_access.log combined
ErrorLog /var/log/apache2/${prefix}${domain}_error.log
ErrorLog syslog:local2
EOF
@ -488,8 +548,8 @@ EOF
_get_custom_rules() {
local custom_rules type elt value first
custom_rules=$(relation-get apache-custom-rules 2>/dev/null) || true
local cfg="$1" custom_rules type elt value first
custom_rules=$(e "$cfg" | cfg-get-value apache-custom-rules 2>/dev/null) || true
if [ -z "$custom_rules" ]; then
return 0
fi
@ -527,8 +587,8 @@ _get_custom_rules() {
__vhost_custom_rules() {
local custom_rules
custom_rules=$(_get_custom_rules) || return 1
local cfg="$1" custom_rules
custom_rules=$(_get_custom_rules "$cfg") || return 1
if [ "$custom_rules" ]; then
cat <<EOF
@ -545,19 +605,23 @@ EOF
__vhost_content_statement() {
if [ "$proxy" ]; then
__vhost_proxy_statement "$@" || return 1
else
__vhost_publish_dir_statement "$@" || return 1
fi
local type="$1"
shift
case "$type" in
"web_proxy")
__vhost_proxy_statement "$@" || return 1
;;
"publish_dir")
__vhost_publish_dir_statement "$@" || return 1
;;
esac
}
__vhost_proxy_statement() {
local protocol="$1"
TARGET=$(relation-get target 2>/dev/null) || true
if [ -z "$TARGET" ]; then
target-get() {
local cfg="$1" target first_exposed_port base_image
target=$(e "$cfg" | cfg-get-value target 2>/dev/null) || true
if [ -z "$target" ]; then
## First exposed port:
base_image=$(service_base_docker_image "$BASE_SERVICE_NAME") || return 1
if ! docker_has_image "$base_image"; then
@ -568,15 +632,22 @@ __vhost_proxy_statement() {
err "Failed to get first exposed port of image '$base_image'."
return 1
fi
TARGET=$MASTER_BASE_SERVICE_NAME:$first_exposed_port
info "No target was specified, introspection found: $TARGET"
target=$MASTER_BASE_SERVICE_NAME:$first_exposed_port
info "No target was specified, introspection found: $target"
fi
echo "$target"
}
__vhost_proxy_statement() {
local protocol="$1" cfg="$2"
target=$(target-get "$cfg") || return 1
cat <<EOF
##
## Proxy declaration towards $TARGET
## Proxy declaration towards $target
##
<IfModule mod_proxy.c>
@ -586,9 +657,9 @@ __vhost_proxy_statement() {
Allow from all
</Proxy>
ProxyVia On
ProxyPass / http://$TARGET/ retry=0
ProxyPass / http://$target/ retry=0
<Location / >
$(__vhost_creds_statement | prefix " ")
$(__vhost_creds_statement "$cfg" | prefix " ")
ProxyPassReverse /
</Location>
$([ "$protocol" == "https" ] && echo " SSLProxyEngine On")
@ -603,11 +674,11 @@ EOF
}
__vhost_full_vhost_statement() {
local protocol="$1" head_statement custom_rules content_statement
local type="$1" protocol="$2" cfg="$3" head_statement custom_rules content_statement
head_statement=$(__vhost_head_statement "$protocol") || return 1
custom_rules=$(__vhost_custom_rules) || return 1
content_statement=$(__vhost_content_statement "$protocol") || return 1
head_statement=$(__vhost_head_statement "$cfg" "$protocol") || return 1
custom_rules=$(__vhost_custom_rules "$cfg") || return 1
content_statement=$(__vhost_content_statement "$type" "$protocol" "$cfg") || return 1
case "$protocol" in
https)
@ -637,22 +708,26 @@ EOF
}
__vhost_publish_dir_statement() {
local protocol="$1" cfg="$2"
domain=$(get_domain "$cfg") || return 1
local_path="/var/www/${domain}"
cat <<EOF
##
## Publish directory $DOCKER_SITE_PATH
## Publish directory $local_path
##
DocumentRoot $DOCKER_SITE_PATH
DocumentRoot $local_path
<Directory />
Options FollowSymLinks
AllowOverride None
</Directory>
<Directory $DOCKER_SITE_PATH>
<Directory $local_path>
Options Indexes FollowSymLinks MultiViews
AllowOverride all
$(__vhost_creds_statement | prefix " ")
$(__vhost_creds_statement "$cfg" | prefix " ")
</Directory>
EOF

95
apache/test/vhost

@ -12,11 +12,6 @@ include parse
"
##
## print_bytes
##
# mock
relation-get() {
local key="$1"
@ -24,10 +19,27 @@ relation-get() {
}
export -f relation-get
cfg-get-value() {
local key="$1"
shyaml get-value "$key" 2>/dev/null
}
export -f cfg-get-value
get_service_relations() {
printf "%s\0" "${RELATIONS[@]}"
}
export -f get_service_relations
##
## Tests
##
try "
DOMAIN=www.example.com
DOCKER_SITE_PATH=/var/www/\$DOMAIN
apache_vhost_statement ,http,"
apache_vhost_statement publish_dir ,http, '\
domain: www.example.com
'"
noerror
is out '<VirtualHost *:80>
@ -69,26 +81,22 @@ is out '<VirtualHost *:80>
##
try "
DOMAIN=www.example.com
DOCKER_SITE_PATH=/var/www/\$DOMAIN
CFG='
apache_vhost_statement publish_dir ,http, '
domain: www.example.com
server-aliases:
- toto
'
apache_vhost_statement ,http,"
'"
noerror
is out reg 'ServerAlias toto'
try "
DOMAIN=www.example.com
DOCKER_SITE_PATH=/var/www/\$DOMAIN
CFG='
apache_vhost_statement publish_dir ,http, '
domain: www.example.com
server-aliases:
- toto
- titi
'
apache_vhost_statement ,http,"
'"
noerror
is out reg 'ServerAlias toto'
is out reg 'ServerAlias titi'
@ -99,23 +107,22 @@ is out reg 'ServerAlias titi'
##
try "
DOMAIN=www.example.com
DOCKER_SITE_PATH=/var/www/\$DOMAIN
CFG=''
apache_vhost_statement ,http," "credentials allow all"
apache_vhost_statement publish_dir ,http, '
domain: www.example.com
'
" "credentials allow all"
noerror
is out reg 'Allow from all'
try "
DOMAIN=www.example.com
DOCKER_SITE_PATH=/var/www/\$DOMAIN
CFG='
apache_vhost_statement publish_dir ,http, '
domain: www.example.com
creds:
toto: xxx
titi: yyy
'
apache_vhost_statement ,http," "credentials with basic auth user/pass"
" "credentials with basic auth user/pass"
noerror
is out reg 'AuthType basic'
is out reg 'Require valid-user'
@ -126,14 +133,13 @@ is out reg 'Require valid-user'
##
try "
DOMAIN=www.example.com
DOCKER_SITE_PATH=/var/www/\$DOMAIN
CFG='
apache_vhost_statement web_proxy ,http, '
domain: www.example.com
target: popo:3333
creds:
toto: titi
'
proxy=yes apache_vhost_statement ,http," "proxy explicit target"
" "proxy explicit target"
noerror
is out reg 'ProxyPass / http://popo:3333/'
is out part '
@ -151,13 +157,12 @@ is out part '
##
try "
DOMAIN=www.example.com
DOCKER_SITE_PATH=/var/www/\$DOMAIN
CFG='
apache_vhost_statement web_proxy ,https, '
domain: www.example.com
ssl: true
target: popo:3333
'
SSL_PLUGIN_FUN=ssl_fallback proxy=yes apache_vhost_statement ,https," "ssl default generation (ssl-cert-snakeoil)"
" "ssl default generation (ssl-cert-snakeoil)"
noerror
is out reg 'VirtualHost \*:443'
is out reg '<IfModule mod_ssl.c>'
@ -168,16 +173,16 @@ is out reg 'CustomLog /var/log/apache2/s-www.example.com_access.log combined'
try "
DOMAIN=www.example.com
DOCKER_SITE_PATH=/var/www/\$DOMAIN
CFG='
RELATIONS=()
apache_vhost_statement web_proxy ,https, '
domain: www.example.com
ssl:
ca-cert: a
key: b
cert: c
target: popo:3333
'
SSL_PLUGIN_FUN=ssl_fallback proxy=yes apache_vhost_statement ,https," "ssl providing keys inline"
" "ssl providing keys inline"
noerror
is out reg 'SSLCertificateFile /etc/ssl/certs/www.example.com.pem'
is out reg 'SSLCertificateKeyFile /etc/ssl/private/www.example.com.key'
@ -189,9 +194,8 @@ is out reg 'SSLCACertificateFile /etc/ssl/certs/www.example.com-ca.pem'
##
try "
DOMAIN=www.example.com
DOCKER_SITE_PATH=/var/www/\$DOMAIN
CFG='
apache_vhost_statement web_proxy ,https, '
domain: www.example.com
ssl:
ca-cert: a
key: b
@ -202,7 +206,7 @@ apache-custom-rules: |
RewriteRule ^(/web/webclient/home.*)$ $1?skin=formanoo [L,QSA,R=302]
target: popo:3333
'
SSL_PLUGIN_FUN=ssl_fallback proxy=yes apache_vhost_statement ,https," "custom rules"
" "custom rules"
noerror
is out reg 'RewriteEngine On'
@ -212,9 +216,8 @@ is out reg 'RewriteEngine On'
##
try "
DOMAIN=www.example.com
DOCKER_SITE_PATH=/var/www/\$DOMAIN
CFG='
apache_vhost_statement web_proxy ,https,http, '
domain: www.example.com
ssl:
ca-cert: a
key: b
@ -225,7 +228,7 @@ apache-custom-rules: |
RewriteRule ^(/web/webclient/home.*)$ $1?skin=formanoo [L,QSA,R=302]
target: popo:3333
'
SSL_PLUGIN_FUN=ssl_fallback proxy=yes apache_vhost_statement ,https,http," "both http and https"
" "both http and https"
noerror
is out '<VirtualHost *:80>

185
apache/test/vhost_cert_provider

@ -31,12 +31,35 @@ relation-set() {
}
export -f relation-set
cfg-get-value() {
local key="$1"
shyaml get-value "$key" 2>/dev/null
}
export -f cfg-get-value
get_service_relations() {
printf "%s\0" "${RELATIONS[@]}"
}
export -f get_service_relations
merge_yaml_str() {
local arg_hash="$(H "$@" | cut -c -16)"
local i
echo "Calling: merge_yaml_str" >&2
((i=0))
for arg in "$@"; do
echo " arg$((i++)):"
echo "$arg" | prefix " | "
done >&2
echo " H> $arg_hash" >&2
while read-0 h res; do
if [[ "$arg_hash" == "$h" ]]; then
echo "Mock hash matched, returning:" >&2
echo "$res" | prefix " | " >&2
echo "$res"
return 0
fi
done < <(e "$MERGE_YAML_STR" | shyaml key-values-0)
printf "<merge_yaml_str("
printf "'%s', " "$@"
printf ")>"
@ -55,6 +78,12 @@ yaml_key_val_str() {
}
export -f yaml_key_val_str
yaml_get_interpret() {
shyaml get-value
}
export -f yaml_get_interpret
file_put() {
echo "file_put $1"
cat - | prefix " | "
@ -114,16 +143,15 @@ export SERVICE_CONFIGSTORE='\$SERVICE_CONFIGSTORE'
export CONFIGSTORE='\$CONFIGSTORE'
export BASE_SERVICE_NAME='\$BASE_SERVICE_NAME'
export MASTER_TARGET_SERVICE_NAME='\$MASTER_TARGET_SERVICE_NAME'
DOMAIN=www.example.com
DOCKER_SITE_PATH=/var/www/\$DOMAIN
CFG='
RELATIONS=()
apache_vhost_create publish_dir '
domain: www.example.com
ssl:
foo: |
a
b
'
RELATIONS=()
apache_vhost_create" "unknown cert key"
" "unknown cert key"
is errlvl 1
is err reg 'Error: .*cert-provider.*'
@ -134,14 +162,26 @@ export CONFIGSTORE='\$CONFIGSTORE'
export DATASTORE='\$DATASTORE'
export BASE_SERVICE_NAME='\$BASE_SERVICE_NAME'
export MASTER_TARGET_SERVICE_NAME='\$MASTER_TARGET_SERVICE_NAME'
DOMAIN=www.example.com
DOCKER_SITE_PATH=/var/www/\$DOMAIN
CFG='
domain: www.example.com
ssl:
foo: 12
'
ADDITION='
apache-custom-rules:
- |
## Auto-redirection from http to https
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [R=302,L,QSA]'
MERGE_YAML_STR=\"
3e417c2db15450f3: |
\$(echo \"\$CFG\" | prefix ' ')
\$(echo \"\$ADDITION\" | prefix ' ')
\"
RELATIONS=(cert-provider foo a True)
apache_vhost_create" "known cert key"
apache_vhost_create publish_dir \"\$CFG\"
" "known cert key"
is errlvl 0
is err part "\
relation-set apache-custom-rules:
@ -157,3 +197,132 @@ is out part 'config-add
| $MASTER_TARGET_SERVICE_NAME:
| volumes:
| - $DATASTORE/foo/etc/letsencrypt:/etc/letsencrypt:ro'
is out part '
| ## Auto-redirection from http to https
| RewriteEngine On
| RewriteCond %{HTTPS} off
| RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [R=302,L,QSA]
'
try "
export SERVICE_CONFIGSTORE='\$SERVICE_CONFIGSTORE'
export CONFIGSTORE='\$CONFIGSTORE'
export DATASTORE='\$DATASTORE'
export SERVICE_NAME='\$SERVICE_NAME'
export BASE_SERVICE_NAME='\$BASE_SERVICE_NAME'
export MASTER_TARGET_SERVICE_NAME='\$MASTER_TARGET_SERVICE_NAME'
RELATIONS=(cert-provider foo a True)
CFG='
domain: www.example.com
server-aliases:
ssl:
foo: 12
'
ADDITION='
apache-custom-rules:
- |
## Auto-redirection from http to https
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [R=302,L,QSA]'
MERGE_YAML_STR=\"
d186e0ae74640f6d: |
\$(echo \"\$CFG\" | prefix ' ')
\$(echo \"\$ADDITION\" | prefix ' ')
\"
apache_vhost_create publish_dir \"\$CFG\"
" "known cert key - empty server-aliases"
is errlvl 0
is err part "\
relation-set apache-custom-rules:
| - |
| ## Auto-redirection from http to https
| RewriteEngine On
| RewriteCond %{HTTPS} off
| RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [R=302,L,QSA]
|"
is out reg 'Calling: compose .*foo: options: <merge_yaml_str\(.a., .12., )>.*run --rm --service-ports foo crt create www.example.com\s*
' RTRIM
is out part 'config-add
| services:
| $MASTER_TARGET_SERVICE_NAME:
| volumes:
| - $DATASTORE/foo/etc/letsencrypt:/etc/letsencrypt:ro'
is out part 'file_put $SERVICE_CONFIGSTORE/etc/apache2/sites-enabled/www.example.com.conf
| <VirtualHost *:80>
|
| ServerAdmin contact@www.example.com
| ServerName www.example.com
|
| ServerSignature Off' RTRIM
is out part '
| ## Auto-redirection from http to https
| RewriteEngine On
| RewriteCond %{HTTPS} off
| RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [R=302,L,QSA]
'
try "
export SERVICE_CONFIGSTORE='\$SERVICE_CONFIGSTORE'
export CONFIGSTORE='\$CONFIGSTORE'
export DATASTORE='\$DATASTORE'
export SERVICE_NAME='\$SERVICE_NAME'
export BASE_SERVICE_NAME='\$BASE_SERVICE_NAME'
export MASTER_TARGET_SERVICE_NAME='\$MASTER_TARGET_SERVICE_NAME'
RELATIONS=(cert-provider foo a True)
CFG='
domain: www.example.com
server-aliases:
- example.fr
- example.de
ssl:
foo: 12
'
ADDITION='
apache-custom-rules:
- |
## Auto-redirection from http to https
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [R=302,L,QSA]'
MERGE_YAML_STR=\"
fcab3acadc661133: |
\$(echo \"\$CFG\" | prefix ' ')
\$(echo \"\$ADDITION\" | prefix ' ')
\"
apache_vhost_create publish_dir \"\$CFG\"
" "known cert key - multiple server-aliases"
is errlvl 0
is err part "\
relation-set apache-custom-rules:
| - |
| ## Auto-redirection from http to https
| RewriteEngine On
| RewriteCond %{HTTPS} off
| RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [R=302,L,QSA]
|"
is out reg 'Calling: compose .*foo: options: <merge_yaml_str\(.a., .12., )>.*run --rm --service-ports foo crt create www.example.com example.fr example.de\s+
'
is out part 'config-add
| services:
| $MASTER_TARGET_SERVICE_NAME:
| volumes:
| - $DATASTORE/foo/etc/letsencrypt:/etc/letsencrypt:ro'
is out part 'file_put $SERVICE_CONFIGSTORE/etc/apache2/sites-enabled/www.example.com.conf
| <VirtualHost *:80>
|
| ServerAdmin contact@www.example.com
| ServerName www.example.com
| ServerAlias example.fr
| ServerAlias example.de
| ServerSignature Off' RTRIM
is out part '
| ## Auto-redirection from http to https
| RewriteEngine On
| RewriteCond %{HTTPS} off
| RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [R=302,L,QSA]
'

107
apache/test/vhost_files

@ -29,6 +29,12 @@ relation-set() {
}
export -f relation-set
cfg-get-value() {
local key="$1"
shyaml get-value "$key" 2>/dev/null
}
export -f cfg-get-value
get_service_relations() {
printf "%s\0" "${RELATIONS[@]}"
}
@ -73,7 +79,39 @@ chmod() {
}
export -f chmod
merge_yaml_str() {
local arg_hash="$(H "$@" | cut -c -16)"
local i
echo "Calling: merge_yaml_str" >&2
((i=0))
for arg in "$@"; do
echo " arg$((i++)):"
echo "$arg" | prefix " | "
done >&2
echo " H> $arg_hash" >&2
while read-0 h res; do
if [[ "$arg_hash" == "$h" ]]; then
echo "Mock hash matched, returning:" >&2
echo "$res" | prefix " | " >&2
echo "$res"
return 0
fi
done < <(e "$MERGE_YAML_STR" | shyaml key-values-0)
printf "<merge_yaml_str("
printf "'%s', " "$@"
printf ")>"
}
export -f merge_yaml_str
yaml_get_interpret() {
shyaml get-value
}
export -f yaml_get_interpret
yaml_key_val_str() {
printf "%s: %s" "$1" "$2"
}
export -f yaml_key_val_str
cached_cmd_on_base_image() {
echo "called: $FUNCNAME $@" >&2
@ -91,9 +129,9 @@ export -f cached_cmd_on_base_image
try "
export SERVICE_CONFIGSTORE='\$SERVICE_CONFIGSTORE'
DOMAIN=www.example.com
DOCKER_SITE_PATH=/var/www/\$DOMAIN
apache_vhost_create"
apache_vhost_create publish_dir '
domain: www.example.com
'"
is errlvl 0
is err part "\
relation-set protocol:
@ -102,12 +140,24 @@ is out reg '^file_put \$SERVICE_CONFIGSTORE/.*/www.example.com.conf'
try "
export SERVICE_CONFIGSTORE='\$SERVICE_CONFIGSTORE'
DOMAIN=www.example.com
DOCKER_SITE_PATH=/var/www/\$DOMAIN
CFG='
domain: www.example.com
ssl: true
'
apache_vhost_create"
ADDITION='
apache-custom-rules:
- |
## Auto-redirection from http to https
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [R=302,L,QSA]'
MERGE_YAML_STR=\"
6b92a84e9d93e4a1: |
\$(echo \"\$CFG\" | prefix ' ')
\$(echo \"\$ADDITION\" | prefix ' ')
\"
apache_vhost_create publish_dir \"\$CFG\"
"
is errlvl 0
is err part "## Auto-redirection from http to https"
is err part "\
@ -121,16 +171,28 @@ export SERVICE_CONFIGSTORE='\$SERVICE_CONFIGSTORE'
export CONFIGSTORE='\$CONFIGSTORE'
export BASE_SERVICE_NAME='\$BASE_SERVICE_NAME'
export MASTER_TARGET_SERVICE_NAME='\$MASTER_TARGET_SERVICE_NAME'
DOMAIN=www.example.com
DOCKER_SITE_PATH=/var/www/\$DOMAIN
CFG='
domain: www.example.com
ssl:
key: |
a
b
cert: c
'
apache_vhost_create"
ADDITION='
apache-custom-rules:
- |
## Auto-redirection from http to https
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [R=302,L,QSA]'
MERGE_YAML_STR=\"
3b76349cfba9d3f2: |
\$(echo \"\$CFG\" | prefix ' ')
\$(echo \"\$ADDITION\" | prefix ' ')
\"
apache_vhost_create publish_dir \"\$CFG\"
"
is errlvl 0
is err part "## Auto-redirection from http to https"
is err part "\
@ -152,13 +214,13 @@ export SERVICE_CONFIGSTORE='\$SERVICE_CONFIGSTORE'
export CONFIGSTORE='\$CONFIGSTORE'
export BASE_SERVICE_NAME='\$BASE_SERVICE_NAME'
export MASTER_TARGET_SERVICE_NAME='\$MASTER_TARGET_SERVICE_NAME'
DOMAIN=www.example.com
DOCKER_SITE_PATH=/var/www/\$DOMAIN
export CFG='
CFG='
domain: www.example.com
creds:
toto: xxx
'
apache_vhost_create"
apache_vhost_create publish_dir \"\$CFG\"
"
is errlvl 0
is err part "\
relation-set protocol:
@ -168,7 +230,7 @@ is out reg 'docker run -i --entrypoint /bin/bash .* docker/apache'
##
## apache_proxy_dir
## apache_publish_dir
##
try "
@ -177,11 +239,10 @@ export SERVICE_CONFIGSTORE='\$SERVICE_CONFIGSTORE'
export CONFIGSTORE='\$CONFIGSTORE'
export BASE_SERVICE_NAME='\$BASE_SERVICE_NAME'
export MASTER_TARGET_SERVICE_NAME='\$MASTER_TARGET_SERVICE_NAME'
export CFG='
apache_publish_dir '
creds:
toto: xxx
'
apache_publish_dir"
'" "missing domain"
is errlvl 1 ## no domain
@ -192,12 +253,12 @@ export SERVICE_CONFIGSTORE='\$SERVICE_CONFIGSTORE'
export CONFIGSTORE='\$CONFIGSTORE'
export BASE_SERVICE_NAME='\$BASE_SERVICE_NAME'
export MASTER_TARGET_SERVICE_NAME='\$MASTER_TARGET_SERVICE_NAME'
export CFG='
apache_publish_dir '
domain: www.example.com
creds:
toto: xxx
'
apache_publish_dir"
"
is errlvl 0
is err reg 'setfacl -R -m g:<GID>:rx \$DATASTORE/\$BASE_SERVICE_NAME/var/www/www.example.com'
is err reg 'cached_cmd_on_base_image apache id -g www-data'
@ -210,7 +271,7 @@ export SERVICE_CONFIGSTORE='\$SERVICE_CONFIGSTORE'
export CONFIGSTORE='\$CONFIGSTORE'
export BASE_SERVICE_NAME='\$BASE_SERVICE_NAME'
export MASTER_TARGET_SERVICE_NAME='\$MASTER_TARGET_SERVICE_NAME'
export CFG='
apache_publish_dir '
domain: www.example.com
creds:
toto: xxx
@ -219,7 +280,7 @@ data-dirs:
- b
- c
'
apache_publish_dir"
"
is errlvl 0
is err reg 'setfacl -R -m g:<GID>:rwx \$DATASTORE/\$BASE_SERVICE_NAME/var/www/www.example.com/a \$DATASTORE/\$BASE_SERVICE_NAME/var/www/www.example.com/b \$DATASTORE/\$BASE_SERVICE_NAME/var/www/www.example.com/c'
is err reg 'setfacl -R -d -m g:<GID>:rwx \$DATASTORE/\$BASE_SERVICE_NAME/var/www/www.example.com/a \$DATASTORE/\$BASE_SERVICE_NAME/var/www/www.example.com/b \$DATASTORE/\$BASE_SERVICE_NAME/var/www/www.example.com/c'
@ -233,7 +294,7 @@ export CONFIGSTORE='\$CONFIGSTORE'
export BASE_SERVICE_NAME='\$BASE_SERVICE_NAME'
export MASTER_BASE_SERVICE_NAME='\$MASTER_BASE_SERVICE_NAME'
export MASTER_TARGET_SERVICE_NAME='\$MASTER_TARGET_SERVICE_NAME'
export CFG='
apache_publish_dir '
domain: www.example.com
location: /opt/apps/newlocation
creds:
@ -243,7 +304,7 @@ data-dirs:
- b
- c
'
apache_publish_dir"
"
is errlvl 0
is err reg 'mkdir -p /opt/apps/newlocation'
is err reg 'setfacl -R -m g:<GID>:rx /opt/apps/newlocation'

Loading…
Cancel
Save