Skip to content

Commit

Permalink
Merge pull request #94 from infosiftr/config-refactor
Browse files Browse the repository at this point in the history
Completely refactor configuration handling, including adding support for RABBITMQ_SSL_VERIFY and RABBITMQ_SSL_FAIL_IF_NO_PEER_CERT and better error handling
  • Loading branch information
yosifkit committed Jul 7, 2016
2 parents f1bfb7c + ab3b8b8 commit 87da33f
Show file tree
Hide file tree
Showing 2 changed files with 164 additions and 92 deletions.
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
# /usr/sbin/rabbitmq-server has some irritating behavior, and only exists to "su - rabbitmq /usr/lib/rabbitmq/bin/rabbitmq-server ..."
ENV PATH /usr/lib/rabbitmq/bin:$PATH

RUN echo '[{rabbit, [{loopback_users, []}]}].' > /etc/rabbitmq/rabbitmq.config
RUN echo '[ { rabbit, [ { loopback_users, [ ] } ] } ].' > /etc/rabbitmq/rabbitmq.config

# set home so that any `--user` knows where to put the erlang cookie
ENV HOME /var/lib/rabbitmq
Expand Down
254 changes: 163 additions & 91 deletions docker-entrypoint.sh
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,25 @@ if [[ "$1" == rabbitmq* ]] && [ "$(id -u)" = '0' ]; then
exec gosu rabbitmq "$BASH_SOURCE" "$@"
fi

# backwards compatibility for old environment variables
: "${RABBITMQ_SSL_CERTFILE:=${RABBITMQ_SSL_CERT_FILE:-}}"
: "${RABBITMQ_SSL_KEYFILE:=${RABBITMQ_SSL_KEY_FILE:-}}"
: "${RABBITMQ_SSL_CACERTFILE:=${RABBITMQ_SSL_CA_FILE:-}}"

# https://www.rabbitmq.com/configure.html
fileConfigs=(
ssl_cacertfile
ssl_certfile
ssl_keyfile
)
configs=(
# https://www.rabbitmq.com/configure.html
default_pass
default_user
default_vhost
hipe_compile
ssl_ca_file
ssl_cert_file
ssl_key_file
ssl_fail_if_no_peer_cert
ssl_verify
"${fileConfigs[@]}"
)

haveConfig=
Expand All @@ -32,6 +42,46 @@ for conf in "${configs[@]}"; do
fi
fi
done
if [ "$haveSslConfig" ]; then
missing=()
for sslConf in cacertfile certfile keyfile; do
var="RABBITMQ_SSL_${sslConf^^}"
val="${!var}"
if [ -z "$val" ]; then
missing+=( "$var" )
fi
done
if [ "${#missing[@]}" -gt 0 ]; then
{
echo
echo 'error: SSL requested, but missing required configuration'
for miss in "${missing[@]}"; do
echo " - $miss"
done
echo
} >&2
exit 1
fi
fi
missingFiles=()
for conf in "${fileConfigs[@]}"; do
var="RABBITMQ_${conf^^}"
val="${!var}"
if [ "$val" ] && [ ! -f "$val" ]; then
missingFiles+=( "$val ($var)" )
fi
done
if [ "${#missingFiles[@]}" -gt 0 ]; then
{
echo
echo 'error: files specified, but missing'
for miss in "${missingFiles[@]}"; do
echo " - $miss"
done
echo
} >&2
exit 1
fi

# If long & short hostnames are not the same, use long hostnames
if [ "$(hostname)" != "$(hostname -s)" ]; then
Expand All @@ -52,116 +102,138 @@ if [ "$RABBITMQ_ERLANG_COOKIE" ]; then
fi
fi

if [ "$1" = 'rabbitmq-server' ]; then
if [ "$haveConfig" ]; then
cat > /etc/rabbitmq/rabbitmq.config <<-'EOH'
[
{rabbit,
[
EOH

if [ "$haveSslConfig" ]; then
cat >> /etc/rabbitmq/rabbitmq.config <<-EOS
{ tcp_listeners, [ ] },
{ ssl_listeners, [ 5671 ] },
{ ssl_options, [
{ certfile, "$RABBITMQ_SSL_CERT_FILE" },
{ keyfile, "$RABBITMQ_SSL_KEY_FILE" },
{ cacertfile, "$RABBITMQ_SSL_CA_FILE" },
{ verify, verify_peer },
{ fail_if_no_peer_cert, true } ] },
EOS
else
cat >> /etc/rabbitmq/rabbitmq.config <<-EOS
{ tcp_listeners, [ 5672 ] },
{ ssl_listeners, [ ] },
EOS
fi

# prints "$2$1$3$1...$N"
join() {
local sep="$1"; shift
local out; printf -v out "${sep//%/%%}%s" "$@"
echo "${out#$sep}"
}
indent() {
if [ "$#" -gt 0 ]; then
echo "$@"
else
cat
fi | sed 's/^/\t/g'
}
rabbit_array() {
echo -n '['
case "$#" in
0) echo -n ' ' ;;
1) echo -n " $1 " ;;
*)
local vals="$(join $',\n' "$@")"
echo
indent "$vals"
esac
echo -n ']'
}

if [ "$1" = 'rabbitmq-server' ] && [ "$haveConfig" ]; then
rabbitConfig=(
"{ loopback_users, $(rabbit_array) }"
)

rabbitSslOptions=()
if [ "$haveSslConfig" ]; then
for conf in "${configs[@]}"; do
sslConf="${conf#ssl_}"
[ "$sslConf" != "$conf" ] || continue

var="RABBITMQ_${conf^^}"
val="${!var}"

rawVal=
case "$conf" in
# SSL-related options are configured above, so should be ignored here
ssl_*) continue ;;
# default values
case "$sslConf" in
verify) : "${val:=verify_peer}" ;;
fail_if_no_peer_cert) : "${val:=true}" ;;
esac

# convert shell booleans into Erlang booleans
hipe_compile)
[ "$val" ] && rawVal='true' || rawVal='false'
;;
rawVal=
case "$sslConf" in
verify|fail_if_no_peer_cert) rawVal="$val" ;;

# otherwise, assume string-based (and skip or add appropriate decorations)
*)
[ "$val" ] || continue
rawVal='<<"'"$val"'">>'
rawVal='"'"$val"'"'
;;
esac
[ "$rawVal" ] || continue

cat >> /etc/rabbitmq/rabbitmq.config <<-EOC
{ $conf, $rawVal },
EOC
rabbitSslOptions+=( "{ $sslConf, $rawVal }" )
done

cat >> /etc/rabbitmq/rabbitmq.config <<-'EOF'
{loopback_users, []}
EOF

# If management plugin is installed, then generate config consider this
if [ "$(rabbitmq-plugins list -m -e rabbitmq_management)" ]; then
cat >> /etc/rabbitmq/rabbitmq.config <<-'EOF'
]
},
{ rabbitmq_management, [
{ listener, [
EOF

if [ "$haveSslConfig" ]; then
cat >> /etc/rabbitmq/rabbitmq.config <<-EOS
{ port, 15671 },
{ ssl, true },
{ ssl_opts, [
{ certfile, "$RABBITMQ_SSL_CERT_FILE" },
{ keyfile, "$RABBITMQ_SSL_KEY_FILE" },
{ cacertfile, "$RABBITMQ_SSL_CA_FILE" },
{ verify, verify_none },
{ fail_if_no_peer_cert, false }
]
}
EOS
else
cat >> /etc/rabbitmq/rabbitmq.config <<-EOS
{ port, 15672 },
{ ssl, false }
EOS
fi

cat >> /etc/rabbitmq/rabbitmq.config <<-EOS
]
}
EOS
fi
rabbitConfig+=(
"{ tcp_listeners, $(rabbit_array) }"
"{ ssl_listeners, $(rabbit_array 5671) }"
"{ ssl_options, $(rabbit_array "${rabbitSslOptions[@]}") }"
)
else
rabbitConfig+=(
"{ tcp_listeners, $(rabbit_array 5672) }"
"{ ssl_listeners, $(rabbit_array) }"
)
fi

cat >> /etc/rabbitmq/rabbitmq.config <<-'EOF'
]
}
].
EOF
for conf in "${configs[@]}"; do
var="RABBITMQ_${conf^^}"
val="${!var}"

rawVal=
case "$conf" in
# SSL-related options are configured above, so should be ignored here
ssl_*) continue ;;

# convert shell booleans into Erlang booleans
hipe_compile)
[ "$val" ] && rawVal='true' || rawVal='false'
;;

# otherwise, assume string-based (and skip or add appropriate decorations)
*)
[ "$val" ] || continue
rawVal='<<"'"$val"'">>'
;;
esac
[ "$rawVal" ] || continue

rabbitConfig+=( "{ $conf, $rawVal }" )
done

# If management plugin is installed, then generate config consider this
if [ "$(rabbitmq-plugins list -m -e rabbitmq_management)" ]; then
rabbitManagementListenerConfig=()
if [ "$haveSslConfig" ]; then
rabbitManagementListenerConfig+=(
'{ port, 15671 }'
'{ ssl, true }'
"{ ssl_opts, $(rabbit_array "${rabbitSslOptions[@]}") }"
)
else
rabbitManagementListenerConfig+=(
'{ port, 15672 }'
'{ ssl, false }'
)
fi
rabbitConfig+=(
"{ rabbitmq_management, $(rabbit_array "{ listener, $(rabbit_array "${rabbitManagementListenerConfig[@]}") }") }"
)
fi

echo "$(rabbit_array "{ rabbit, $(rabbit_array "${rabbitConfig[@]}") }")." > /etc/rabbitmq/rabbitmq.config
fi

if [ "$haveSslConfig" ]; then
combinedSsl='/tmp/combined.pem'
if [ "$haveSslConfig" ] && [[ "$1" == rabbitmq* ]] && [ ! -f "$combinedSsl" ]; then
# Create combined cert
cat "$RABBITMQ_SSL_CERT_FILE" "$RABBITMQ_SSL_KEY_FILE" > /tmp/combined.pem
chmod 0400 /tmp/combined.pem

cat "$RABBITMQ_SSL_CERTFILE" "$RABBITMQ_SSL_KEYFILE" > "$combinedSsl"
chmod 0400 "$combinedSsl"
fi
if [ "$haveSslConfig" ] && [ -f "$combinedSsl" ]; then
# More ENV vars for make clustering happiness
# we don't handle clustering in this script, but these args should ensure
# clustered SSL-enabled members will talk nicely
export ERL_SSL_PATH="$(erl -eval 'io:format("~p", [code:lib_dir(ssl, ebin)]),halt().' -noshell)"
export RABBITMQ_SERVER_ADDITIONAL_ERL_ARGS="-pa '$ERL_SSL_PATH' -proto_dist inet_tls -ssl_dist_opt server_certfile /tmp/combined.pem -ssl_dist_opt server_secure_renegotiate true client_secure_renegotiate true"
export RABBITMQ_SERVER_ADDITIONAL_ERL_ARGS="-pa '$ERL_SSL_PATH' -proto_dist inet_tls -ssl_dist_opt server_certfile '$combinedSsl' -ssl_dist_opt server_secure_renegotiate true client_secure_renegotiate true"
export RABBITMQ_CTL_ERL_ARGS="$RABBITMQ_SERVER_ADDITIONAL_ERL_ARGS"
fi

Expand Down

0 comments on commit 87da33f

Please sign in to comment.