Skip to content

Commit ab3b8b8

Browse files
committed
Completely refactor configuration handling, including adding support for RABBITMQ_SSL_VERIFY and RABBITMQ_SSL_FAIL_IF_NO_PEER_CERT and better error handling
1 parent f1bfb7c commit ab3b8b8

File tree

2 files changed

+164
-92
lines changed

2 files changed

+164
-92
lines changed

Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
5959
# /usr/sbin/rabbitmq-server has some irritating behavior, and only exists to "su - rabbitmq /usr/lib/rabbitmq/bin/rabbitmq-server ..."
6060
ENV PATH /usr/lib/rabbitmq/bin:$PATH
6161

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

6464
# set home so that any `--user` knows where to put the erlang cookie
6565
ENV HOME /var/lib/rabbitmq

docker-entrypoint.sh

Lines changed: 163 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,25 @@ if [[ "$1" == rabbitmq* ]] && [ "$(id -u)" = '0' ]; then
99
exec gosu rabbitmq "$BASH_SOURCE" "$@"
1010
fi
1111

12+
# backwards compatibility for old environment variables
13+
: "${RABBITMQ_SSL_CERTFILE:=${RABBITMQ_SSL_CERT_FILE:-}}"
14+
: "${RABBITMQ_SSL_KEYFILE:=${RABBITMQ_SSL_KEY_FILE:-}}"
15+
: "${RABBITMQ_SSL_CACERTFILE:=${RABBITMQ_SSL_CA_FILE:-}}"
16+
17+
# https://www.rabbitmq.com/configure.html
18+
fileConfigs=(
19+
ssl_cacertfile
20+
ssl_certfile
21+
ssl_keyfile
22+
)
1223
configs=(
13-
# https://www.rabbitmq.com/configure.html
1424
default_pass
1525
default_user
1626
default_vhost
1727
hipe_compile
18-
ssl_ca_file
19-
ssl_cert_file
20-
ssl_key_file
28+
ssl_fail_if_no_peer_cert
29+
ssl_verify
30+
"${fileConfigs[@]}"
2131
)
2232

2333
haveConfig=
@@ -32,6 +42,46 @@ for conf in "${configs[@]}"; do
3242
fi
3343
fi
3444
done
45+
if [ "$haveSslConfig" ]; then
46+
missing=()
47+
for sslConf in cacertfile certfile keyfile; do
48+
var="RABBITMQ_SSL_${sslConf^^}"
49+
val="${!var}"
50+
if [ -z "$val" ]; then
51+
missing+=( "$var" )
52+
fi
53+
done
54+
if [ "${#missing[@]}" -gt 0 ]; then
55+
{
56+
echo
57+
echo 'error: SSL requested, but missing required configuration'
58+
for miss in "${missing[@]}"; do
59+
echo " - $miss"
60+
done
61+
echo
62+
} >&2
63+
exit 1
64+
fi
65+
fi
66+
missingFiles=()
67+
for conf in "${fileConfigs[@]}"; do
68+
var="RABBITMQ_${conf^^}"
69+
val="${!var}"
70+
if [ "$val" ] && [ ! -f "$val" ]; then
71+
missingFiles+=( "$val ($var)" )
72+
fi
73+
done
74+
if [ "${#missingFiles[@]}" -gt 0 ]; then
75+
{
76+
echo
77+
echo 'error: files specified, but missing'
78+
for miss in "${missingFiles[@]}"; do
79+
echo " - $miss"
80+
done
81+
echo
82+
} >&2
83+
exit 1
84+
fi
3585

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

55-
if [ "$1" = 'rabbitmq-server' ]; then
56-
if [ "$haveConfig" ]; then
57-
cat > /etc/rabbitmq/rabbitmq.config <<-'EOH'
58-
[
59-
{rabbit,
60-
[
61-
EOH
62-
63-
if [ "$haveSslConfig" ]; then
64-
cat >> /etc/rabbitmq/rabbitmq.config <<-EOS
65-
{ tcp_listeners, [ ] },
66-
{ ssl_listeners, [ 5671 ] },
67-
{ ssl_options, [
68-
{ certfile, "$RABBITMQ_SSL_CERT_FILE" },
69-
{ keyfile, "$RABBITMQ_SSL_KEY_FILE" },
70-
{ cacertfile, "$RABBITMQ_SSL_CA_FILE" },
71-
{ verify, verify_peer },
72-
{ fail_if_no_peer_cert, true } ] },
73-
EOS
74-
else
75-
cat >> /etc/rabbitmq/rabbitmq.config <<-EOS
76-
{ tcp_listeners, [ 5672 ] },
77-
{ ssl_listeners, [ ] },
78-
EOS
79-
fi
80-
105+
# prints "$2$1$3$1...$N"
106+
join() {
107+
local sep="$1"; shift
108+
local out; printf -v out "${sep//%/%%}%s" "$@"
109+
echo "${out#$sep}"
110+
}
111+
indent() {
112+
if [ "$#" -gt 0 ]; then
113+
echo "$@"
114+
else
115+
cat
116+
fi | sed 's/^/\t/g'
117+
}
118+
rabbit_array() {
119+
echo -n '['
120+
case "$#" in
121+
0) echo -n ' ' ;;
122+
1) echo -n " $1 " ;;
123+
*)
124+
local vals="$(join $',\n' "$@")"
125+
echo
126+
indent "$vals"
127+
esac
128+
echo -n ']'
129+
}
130+
131+
if [ "$1" = 'rabbitmq-server' ] && [ "$haveConfig" ]; then
132+
rabbitConfig=(
133+
"{ loopback_users, $(rabbit_array) }"
134+
)
135+
136+
rabbitSslOptions=()
137+
if [ "$haveSslConfig" ]; then
81138
for conf in "${configs[@]}"; do
139+
sslConf="${conf#ssl_}"
140+
[ "$sslConf" != "$conf" ] || continue
141+
82142
var="RABBITMQ_${conf^^}"
83143
val="${!var}"
84144

85-
rawVal=
86-
case "$conf" in
87-
# SSL-related options are configured above, so should be ignored here
88-
ssl_*) continue ;;
145+
# default values
146+
case "$sslConf" in
147+
verify) : "${val:=verify_peer}" ;;
148+
fail_if_no_peer_cert) : "${val:=true}" ;;
149+
esac
89150

90-
# convert shell booleans into Erlang booleans
91-
hipe_compile)
92-
[ "$val" ] && rawVal='true' || rawVal='false'
93-
;;
151+
rawVal=
152+
case "$sslConf" in
153+
verify|fail_if_no_peer_cert) rawVal="$val" ;;
94154

95-
# otherwise, assume string-based (and skip or add appropriate decorations)
96155
*)
97156
[ "$val" ] || continue
98-
rawVal='<<"'"$val"'">>'
157+
rawVal='"'"$val"'"'
99158
;;
100159
esac
101160
[ "$rawVal" ] || continue
102161

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

108-
cat >> /etc/rabbitmq/rabbitmq.config <<-'EOF'
109-
{loopback_users, []}
110-
EOF
111-
112-
# If management plugin is installed, then generate config consider this
113-
if [ "$(rabbitmq-plugins list -m -e rabbitmq_management)" ]; then
114-
cat >> /etc/rabbitmq/rabbitmq.config <<-'EOF'
115-
]
116-
},
117-
{ rabbitmq_management, [
118-
{ listener, [
119-
EOF
120-
121-
if [ "$haveSslConfig" ]; then
122-
cat >> /etc/rabbitmq/rabbitmq.config <<-EOS
123-
{ port, 15671 },
124-
{ ssl, true },
125-
{ ssl_opts, [
126-
{ certfile, "$RABBITMQ_SSL_CERT_FILE" },
127-
{ keyfile, "$RABBITMQ_SSL_KEY_FILE" },
128-
{ cacertfile, "$RABBITMQ_SSL_CA_FILE" },
129-
{ verify, verify_none },
130-
{ fail_if_no_peer_cert, false }
131-
]
132-
}
133-
EOS
134-
else
135-
cat >> /etc/rabbitmq/rabbitmq.config <<-EOS
136-
{ port, 15672 },
137-
{ ssl, false }
138-
EOS
139-
fi
140-
141-
cat >> /etc/rabbitmq/rabbitmq.config <<-EOS
142-
]
143-
}
144-
EOS
145-
fi
165+
rabbitConfig+=(
166+
"{ tcp_listeners, $(rabbit_array) }"
167+
"{ ssl_listeners, $(rabbit_array 5671) }"
168+
"{ ssl_options, $(rabbit_array "${rabbitSslOptions[@]}") }"
169+
)
170+
else
171+
rabbitConfig+=(
172+
"{ tcp_listeners, $(rabbit_array 5672) }"
173+
"{ ssl_listeners, $(rabbit_array) }"
174+
)
175+
fi
146176

147-
cat >> /etc/rabbitmq/rabbitmq.config <<-'EOF'
148-
]
149-
}
150-
].
151-
EOF
177+
for conf in "${configs[@]}"; do
178+
var="RABBITMQ_${conf^^}"
179+
val="${!var}"
180+
181+
rawVal=
182+
case "$conf" in
183+
# SSL-related options are configured above, so should be ignored here
184+
ssl_*) continue ;;
185+
186+
# convert shell booleans into Erlang booleans
187+
hipe_compile)
188+
[ "$val" ] && rawVal='true' || rawVal='false'
189+
;;
190+
191+
# otherwise, assume string-based (and skip or add appropriate decorations)
192+
*)
193+
[ "$val" ] || continue
194+
rawVal='<<"'"$val"'">>'
195+
;;
196+
esac
197+
[ "$rawVal" ] || continue
198+
199+
rabbitConfig+=( "{ $conf, $rawVal }" )
200+
done
201+
202+
# If management plugin is installed, then generate config consider this
203+
if [ "$(rabbitmq-plugins list -m -e rabbitmq_management)" ]; then
204+
rabbitManagementListenerConfig=()
205+
if [ "$haveSslConfig" ]; then
206+
rabbitManagementListenerConfig+=(
207+
'{ port, 15671 }'
208+
'{ ssl, true }'
209+
"{ ssl_opts, $(rabbit_array "${rabbitSslOptions[@]}") }"
210+
)
211+
else
212+
rabbitManagementListenerConfig+=(
213+
'{ port, 15672 }'
214+
'{ ssl, false }'
215+
)
216+
fi
217+
rabbitConfig+=(
218+
"{ rabbitmq_management, $(rabbit_array "{ listener, $(rabbit_array "${rabbitManagementListenerConfig[@]}") }") }"
219+
)
152220
fi
221+
222+
echo "$(rabbit_array "{ rabbit, $(rabbit_array "${rabbitConfig[@]}") }")." > /etc/rabbitmq/rabbitmq.config
153223
fi
154224

155-
if [ "$haveSslConfig" ]; then
225+
combinedSsl='/tmp/combined.pem'
226+
if [ "$haveSslConfig" ] && [[ "$1" == rabbitmq* ]] && [ ! -f "$combinedSsl" ]; then
156227
# Create combined cert
157-
cat "$RABBITMQ_SSL_CERT_FILE" "$RABBITMQ_SSL_KEY_FILE" > /tmp/combined.pem
158-
chmod 0400 /tmp/combined.pem
159-
228+
cat "$RABBITMQ_SSL_CERTFILE" "$RABBITMQ_SSL_KEYFILE" > "$combinedSsl"
229+
chmod 0400 "$combinedSsl"
230+
fi
231+
if [ "$haveSslConfig" ] && [ -f "$combinedSsl" ]; then
160232
# More ENV vars for make clustering happiness
161233
# we don't handle clustering in this script, but these args should ensure
162234
# clustered SSL-enabled members will talk nicely
163235
export ERL_SSL_PATH="$(erl -eval 'io:format("~p", [code:lib_dir(ssl, ebin)]),halt().' -noshell)"
164-
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"
236+
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"
165237
export RABBITMQ_CTL_ERL_ARGS="$RABBITMQ_SERVER_ADDITIONAL_ERL_ARGS"
166238
fi
167239

0 commit comments

Comments
 (0)