Skip to content

Commit ba450ea

Browse files
committed
make shell scripts posix compliant for better portability and fix problems with env vars containing spaces or special chars like "!"
1 parent 423e7d6 commit ba450ea

File tree

4 files changed

+78
-78
lines changed

4 files changed

+78
-78
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
* allow partial export of redis data
2323
* add function to rename existing keys, #378
2424
* update dependencies to fix vulnerabilities in multiple packages
25+
* better handle special chars and spaces inside env vars given to docker container
2526

2627
## Version 0.7.0
2728
#### Bugfixes

docker/entrypoint.sh

+73-74
Original file line numberDiff line numberDiff line change
@@ -20,26 +20,35 @@ K8S_SIGTERM=${K8S_SIGTERM:-0}
2020
# seconds to wait before sending sigterm to app on exit
2121
# only used if K8S_SIGTERM=1
2222
GRACE_PERIOD=6
23-
NODE=$(which node)
23+
NODE=$(command -v node)
2424

2525
# this function checks all arguments given and outputs them. All parameter pairs where key is ending with "password"
2626
# are replaced with string "<set>" instead of real password (e.g. "--redis-password XYZ" => "--redis-password <set>")
2727
safe_print_args() {
28-
echo "$@" | tr ' ' '\n' | while read item; do
28+
echo "$@" | tr ' ' '\n' | while read -r item; do
2929
if [ "${item%password}" != "${item}" ]; then
30-
echo $item" <set>"
31-
read item;
30+
printf "%s <set> " "$item"
31+
read -r item;
3232
else
33-
echo $item
33+
printf "%s " "$item"
3434
fi
3535
done
3636
}
3737

38+
parse_boolean() {
39+
# shell true/false values returned here
40+
if [ "$1" = "1" ] || [ "$1" = "true" ] || [ "$1" = "yes" ] || [ "$1" = "on" ]; then
41+
return 0
42+
else
43+
return 1
44+
fi
45+
}
46+
3847
writeDefaultConfigBeginning() {
3948
echo "Creating custom redis-commander config '${CONFIG_FILE}'."
4049

4150
# =============== generate beginning of redis-commander config =============== #
42-
cat > ${CONFIG_FILE} <<EOF
51+
cat > "${CONFIG_FILE}" <<EOF
4352
{
4453
EOF
4554
# ============= end generate beginning of redis-commander config ============= #
@@ -48,7 +57,7 @@ EOF
4857

4958
writeDefaultConfigEnd() {
5059
# ================== generate end of redis-commander config ================== #
51-
cat >> ${CONFIG_FILE} <<EOF
60+
cat >> "${CONFIG_FILE}" <<EOF
5261
}
5362
EOF
5463
# ================ end generate end of redis-commander config ================ #
@@ -61,15 +70,15 @@ parseRedisHosts() {
6170
# split REDIS_HOSTS on comma (,)
6271
# local:localhost:6379,custom-label:my.hostname
6372
# -> local:localhost:6379 custom-label:my.hostname
64-
redis_hosts_split="$(echo ${REDIS_HOSTS} | sed "s/,/ /g")"
73+
redis_hosts_split="$(echo "${REDIS_HOSTS}" | sed "s/,/ /g")"
6574

6675
# get hosts count
67-
num_redis_hosts="$(echo ${redis_hosts_split} | wc -w)"
76+
num_redis_hosts="$(echo "${redis_hosts_split}" | wc -w)"
6877

6978
echo "Parsing $num_redis_hosts REDIS_HOSTS into custom redis-commander config '${CONFIG_FILE}'."
7079

71-
if [ $num_redis_hosts -gt 0 ]; then
72-
cat >> ${CONFIG_FILE} <<EOF
80+
if [ "$num_redis_hosts" -gt 0 ]; then
81+
cat >> "${CONFIG_FILE}" <<EOF
7382
"connections": [
7483
EOF
7584
fi
@@ -92,7 +101,7 @@ EOF
92101
# split redis_host on colon (:)
93102
# local:localhost:6379
94103
# -> local localhost 6379
95-
host_split="$(echo ${redis_host} | sed "s/:/ /g")"
104+
host_split="$(echo "${redis_host}" | sed "s/:/ /g")"
96105

97106
# get host param count
98107
num_host_params="$(echo "${host_split}" | wc -w)"
@@ -105,31 +114,31 @@ EOF
105114

106115
if [ "${num_host_params}" -eq 1 ]; then
107116
label=default
108-
host="$(echo ${host_split} | cut -d" " -f1)"
117+
host="$(echo "${host_split}" | cut -d" " -f1)"
109118
else
110-
label="$(echo ${host_split} | cut -d" " -f1)"
111-
host="$(echo ${host_split} | cut -d" " -f2)"
119+
label="$(echo "${host_split}" | cut -d" " -f1)"
120+
host="$(echo "${host_split}" | cut -d" " -f2)"
112121
fi
113122

114123
[ "${num_host_params}" -lt 3 ] \
115124
&& port=6379 \
116-
|| port="$(echo ${host_split} | cut -d" " -f3)"
125+
|| port="$(echo "${host_split}" | cut -d" " -f3)"
117126

118127
[ "${num_host_params}" -lt 4 ] \
119128
&& db_index=0 \
120-
|| db_index="$(echo ${host_split} | cut -d" " -f4)"
129+
|| db_index="$(echo "${host_split}" | cut -d" " -f4)"
121130

122131

123132
[ "${num_host_params}" -lt 5 ] \
124133
&& password='' \
125-
|| password="$(echo ${host_split} | cut -d" " -f5)"
134+
|| password="$(echo "${host_split}" | cut -d" " -f5)"
126135

127136
[ "${counter}" -eq "${num_redis_hosts}" ] \
128137
&& comma='' \
129138
|| comma=','
130139

131140
# generate host config
132-
cat >> ${CONFIG_FILE} <<EOF
141+
cat >> "${CONFIG_FILE}" <<EOF
133142
{
134143
"label":"${label}",
135144
"host":"${host}",
@@ -141,8 +150,8 @@ EOF
141150

142151
done
143152
# ================ end loop on redis hosts and generate config =============== #
144-
if [ $num_redis_hosts -gt 0 ]; then
145-
cat >> ${CONFIG_FILE} <<EOF
153+
if [ "$num_redis_hosts" -gt 0 ]; then
154+
cat >> "${CONFIG_FILE}" <<EOF
146155
]
147156
EOF
148157
fi
@@ -151,20 +160,20 @@ EOF
151160
}
152161

153162
# if REDIS_HOSTS is set parse it and create custom config
154-
[[ ! -z "${REDIS_HOSTS}" ]] && parseRedisHosts
163+
[ -n "${REDIS_HOSTS}" ] && parseRedisHosts
155164

156165
# Fallback - write default config if not supplied otherwise (already exists or written by
157166
# parsing REDIS_HOSTS env var)
158-
if [[ ! -e ${CONFIG_FILE} ]]; then
167+
if [ ! -e "${CONFIG_FILE}" ]; then
159168
writeDefaultConfigBeginning
160169
writeDefaultConfigEnd
161170
fi
162171

163172
# load HTTP password from a file (e.g. a Docker secret mounted in the container)
164173
HTTP_PASSWORD_FILE=${HTTP_PASSWORD_FILE:-/}
165174

166-
if [ -f $HTTP_PASSWORD_FILE ]; then
167-
HTTP_PASSWORD=$(cat $HTTP_PASSWORD_FILE)
175+
if [ -f "$HTTP_PASSWORD_FILE" ]; then
176+
HTTP_PASSWORD=$(cat "$HTTP_PASSWORD_FILE")
168177
# this env var is evaluated by node-config module, not set as cli param
169178
# to not show it in process listing / write to docker logs ...
170179
export HTTP_PASSWORD
@@ -174,13 +183,13 @@ fi
174183
REDIS_PASSWORD_FILE=${REDIS_PASSWORD_FILE:-/}
175184
SENTINEL_PASSWORD_FILE=${SENTINEL_PASSWORD_FILE:-/}
176185

177-
if [ -f $REDIS_PASSWORD_FILE ]; then
178-
REDIS_PASSWORD=$(cat $REDIS_PASSWORD_FILE)
186+
if [ -f "$REDIS_PASSWORD_FILE" ]; then
187+
REDIS_PASSWORD=$(cat "$REDIS_PASSWORD_FILE")
179188
# evaluated below and added to cli params
180189
export REDIS_PASSWORD
181190
fi
182-
if [ -f $SENTINEL_PASSWORD_FILE ]; then
183-
SENTINEL_PASSWORD=$(cat $SENTINEL_PASSWORD_FILE)
191+
if [ -f "$SENTINEL_PASSWORD_FILE" ]; then
192+
SENTINEL_PASSWORD=$(cat "$SENTINEL_PASSWORD_FILE")
184193
# evaluated below and added to cli params
185194
export SENTINEL_PASSWORD
186195
fi
@@ -191,59 +200,55 @@ fi
191200
# for an complete list of all other env vars with their mapping
192201
# see file "config/custom_environment_variables.json"
193202

194-
if [[ ! -z "$REDIS_PORT" ]]; then
195-
set -- "$@" "--redis-port $REDIS_PORT"
203+
if [ -n "$REDIS_PORT" ]; then
204+
set -- "$@" "--redis-port" "$REDIS_PORT"
196205
fi
197206

198-
if [[ ! -z "$REDIS_HOST" ]]; then
199-
set -- "$@" "--redis-host $REDIS_HOST"
207+
if [ -n "$REDIS_HOST" ]; then
208+
set -- "$@" "--redis-host" "$REDIS_HOST"
200209
fi
201210

202-
if [[ ! -z "$REDIS_SOCKET" ]]; then
203-
set -- "$@" "--redis-socket $REDIS_SOCKET"
211+
if [ -n "$REDIS_SOCKET" ]; then
212+
set -- "$@" "--redis-socket" "$REDIS_SOCKET"
204213
fi
205214

206-
if [[ ! -z "$REDIS_TLS" ]]; then
207-
if [[ "$REDIS_TLS" = "1" || "$REDIS_TLS" = "true" || "$REDIS_TLS" = "yes" || "$REDIS_TLS" = "on" ]]; then
208-
set -- "$@" "--redis-tls"
209-
fi
215+
if [ -n "$REDIS_TLS" ] && parse_boolean "$REDIS_TLS"; then
216+
set -- "$@" "--redis-tls"
210217
fi
211218

212-
if [[ ! -z "$REDIS_PASSWORD" ]]; then
213-
set -- "$@" "--redis-password $REDIS_PASSWORD"
219+
if [ -n "$REDIS_PASSWORD" ]; then
220+
set -- "$@" "--redis-password" "$REDIS_PASSWORD"
214221
fi
215222

216-
if [[ ! -z "$REDIS_DB" ]]; then
217-
set -- "$@" "--redis-db $REDIS_DB"
223+
if [ -n "$REDIS_DB" ]; then
224+
set -- "$@" "--redis-db" "$REDIS_DB"
218225
fi
219226

220-
if [[ ! -z "$REDIS_OPTIONAL" ]]; then
221-
if [[ "$REDIS_OPTIONAL" = "1" || "$REDIS_OPTIONAL" = "true" || "$REDIS_OPTIONAL" = "yes" || "$REDIS_OPTIONAL" = "on" ]]; then
222-
set -- "$@" "--redis-optional"
223-
fi
227+
if [ -n "$REDIS_OPTIONAL" ] && parse_boolean "$REDIS_OPTIONAL"; then
228+
set -- "$@" "--redis-optional"
224229
fi
225230

226-
if [[ ! -z "$SENTINEL_PORT" ]]; then
227-
set -- "$@" "--sentinel-port $SENTINEL_PORT"
231+
if [ -n "$SENTINEL_PORT" ]; then
232+
set -- "$@" "--sentinel-port" "$SENTINEL_PORT"
228233
fi
229234

230-
if [[ ! -z "$SENTINEL_HOST" ]]; then
231-
set -- "$@" "--sentinel-host $SENTINEL_HOST"
235+
if [ -n "$SENTINEL_HOST" ]; then
236+
set -- "$@" "--sentinel-host" "$SENTINEL_HOST"
232237
fi
233238

234-
if [[ ! -z "$SENTINELS" ]]; then
235-
set -- "$@" "--sentinels $SENTINELS"
239+
if [ -n "$SENTINELS" ]; then
240+
set -- "$@" "--sentinels" "$SENTINELS"
236241
fi
237242

238-
if [[ ! -z "$SENTINEL_NAME" ]]; then
239-
set -- "$@" "--sentinel-name $SENTINEL_NAME"
243+
if [ -n "$SENTINEL_NAME" ]; then
244+
set -- "$@" "--sentinel-name" "$SENTINEL_NAME"
240245
fi
241246

242-
if [[ ! -z "$SENTINEL_PASSWORD" ]]; then
243-
set -- "$@" "--sentinel-password $SENTINEL_PASSWORD"
247+
if [ -n "$SENTINEL_PASSWORD" ]; then
248+
set -- "$@" "--sentinel-password" "$SENTINEL_PASSWORD"
244249
fi
245250

246-
if [[ ! -z "$REPLACE_CONFIG_ENV" ]]; then
251+
if [ -n "$REPLACE_CONFIG_ENV" ]; then
247252
# special case for more complex docker setup with multiple connections
248253
# to unix sockets, sentinels and normal redis server not configurable
249254
# via REDIS_HOSTS...
@@ -252,14 +257,14 @@ if [[ ! -z "$REPLACE_CONFIG_ENV" ]]; then
252257
# set $REPLACE_CONFIG_ENV=REDIS_PASS_1 and env REDIS_PASS_1=mypass
253258
# now search config files for string "REDIS_PASS_1" and write there "mypass" instead
254259

255-
env_vars_replace="$(echo ${REPLACE_CONFIG_ENV} | sed "s/,/ /g")"
260+
env_vars_replace="$(echo "${REPLACE_CONFIG_ENV}" | sed "s/,/ /g")"
256261
echo "Going to replace this env vars inside config files: $env_vars_replace"
257262

258263
for env_var in ${env_vars_replace}; do
259264
for json_conf in config/*.json; do
260-
if [ $json_conf != "config/custom-environment-variables.json" ]; then
265+
if [ "$json_conf" != "config/custom-environment-variables.json" ]; then
261266
# need to replace &\/ from content of env_var var as they are special chars in sed
262-
sed -i 's/"'$env_var'"/"'$(printenv $env_var | sed 's/\\/\\\\/g; s/&/\\&/g; s#/#\\/#g;')'"/g' $json_conf
267+
sed -i 's/"'"$env_var"'"/"'"$(printenv "$env_var" | sed 's/\\/\\\\/g; s/&/\\&/g; s#/#\\/#g;')"'"/g' "$json_conf"
263268
fi
264269
done
265270
done
@@ -268,36 +273,30 @@ fi
268273

269274
# syntax check of all config files to help detecting invalid ones early
270275
for i in config/*.json; do
271-
cat ${i} | jq empty
272-
if [[ $? -ne 0 ]]; then
276+
if ! jq empty < "${i}"; then
273277
echo "ERROR: config file ${i} has invalid json syntax"
274278
exit 1
275279
fi
276-
# if [ $i != "config/custom-environment-variables.json" ]; then
277-
# echo .
278-
# echo "###config file: $i"
279-
# cat $i
280-
# fi
281280
done
282281

283282
# install trap for SIGTERM to delay end of app a bit for Kubernetes
284283
# otherwise container might get requests after exiting itself
285284
exitTrap() {
286285
echo "Got signal, wait a bit before exit"
287286
sleep $GRACE_PERIOD
288-
kill -TERM $NODE_PID
287+
kill -TERM "$NODE_PID"
289288
}
290289

291-
if [[ "$K8S_SIGTERM" = "1" ]]; then
290+
if [ "$K8S_SIGTERM" = "1" ]; then
292291
trap exitTrap TERM INT
293-
echo "node ./bin/redis-commander "$(safe_print_args $@)" for k8s"
294-
setsid $NODE ./bin/redis-commander $@ &
292+
echo "node ./bin/redis-commander $(safe_print_args "$@") for k8s"
293+
setsid "$NODE" ./bin/redis-commander "$@" &
295294
NODE_PID=$!
296295
wait $NODE_PID
297296
trap - TERM INT
298297
wait $NODE_PID
299298
else
300-
echo "node ./bin/redis-commander "$(safe_print_args $@)""
301-
exec $NODE ./bin/redis-commander $@
299+
echo "node ./bin/redis-commander $(safe_print_args "$@")"
300+
exec "$NODE" ./bin/redis-commander "$@"
302301
fi
303302

docker/harden.sh

+3-3
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ set -e
66
# https://github.com/ellerbrock/docker-collection/tree/master/dockerfiles/alpine-harden
77

88
# Be informative after successful login.
9-
echo -e "\n\nApp container image built on $(date)." > /etc/motd
9+
printf "\n\nApp container image built on %s." "$(date)" > /etc/motd
1010

1111
# Improve strength of diffie-hellman-group-exchange-sha256 (Custom DH with SHA2).
1212
# See https://stribika.github.io/2015/01/04/secure-secure-shell.html
@@ -16,7 +16,7 @@ echo -e "\n\nApp container image built on $(date)." > /etc/motd
1616
#
1717
# This file is provided by the openssh package on Fedora.
1818
moduli=/etc/ssh/moduli
19-
if [[ -f ${moduli} ]]; then
19+
if [ -f ${moduli} ]; then
2020
cp ${moduli} ${moduli}.orig
2121
awk '$5 >= 2000' ${moduli}.orig > ${moduli}
2222
rm -f ${moduli}.orig
@@ -47,7 +47,7 @@ sed -i -r "/^(${SERVICE_USER}|root|sshd)/!d" /etc/group
4747
sed -i -r "/^(${SERVICE_USER}|root|sshd)/!d" /etc/passwd
4848

4949
# Remove interactive login shell for everybody but user.
50-
sed -i -r '/^'${SERVICE_USER}':/! s#^(.*):[^:]*$#\1:/sbin/nologin#' /etc/passwd
50+
sed -i -r "/^${SERVICE_USER}:/! s#^(.*):[^:]*\$#\1:/sbin/nologin#" /etc/passwd
5151

5252
sysdirs="
5353
/bin

k8s/helm-chart/release_charts

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,6 @@
22
# author Abdennour Toumi (https://github.com/abdennour)
33

44
dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )";
5-
cd ${dir}
5+
cd "${dir}" || exit
66
helm package redis-commander
77
helm repo index .

0 commit comments

Comments
 (0)