Skip to content

Commit 3da6c99

Browse files
committed
Adjust "wp-config.php" behavior to be skipped if configuration is not provided
Also, unset "secret" environment variables before starting Apache/FPM to ensure that a stray `phpinfo()` doesn't include secrets from our code.
1 parent d8e5577 commit 3da6c99

File tree

10 files changed

+1150
-880
lines changed

10 files changed

+1150
-880
lines changed

docker-entrypoint.sh

Lines changed: 115 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -24,31 +24,14 @@ file_env() {
2424
}
2525

2626
if [[ "$1" == apache2* ]] || [ "$1" == php-fpm ]; then
27-
file_env 'WORDPRESS_DB_HOST' 'mysql'
28-
# if we're linked to MySQL and thus have credentials already, let's use them
29-
file_env 'WORDPRESS_DB_USER' "${MYSQL_ENV_MYSQL_USER:-root}"
30-
if [ "$WORDPRESS_DB_USER" = 'root' ]; then
31-
file_env 'WORDPRESS_DB_PASSWORD' "${MYSQL_ENV_MYSQL_ROOT_PASSWORD:-}"
32-
else
33-
file_env 'WORDPRESS_DB_PASSWORD' "${MYSQL_ENV_MYSQL_PASSWORD:-}"
34-
fi
35-
file_env 'WORDPRESS_DB_NAME' "${MYSQL_ENV_MYSQL_DATABASE:-wordpress}"
36-
if [ -z "$WORDPRESS_DB_PASSWORD" ]; then
37-
echo >&2 'error: missing required WORDPRESS_DB_PASSWORD environment variable'
38-
echo >&2 ' Did you forget to -e WORDPRESS_DB_PASSWORD=... ?'
39-
echo >&2
40-
echo >&2 ' (Also of interest might be WORDPRESS_DB_USER and WORDPRESS_DB_NAME.)'
41-
exit 1
42-
fi
43-
4427
if ! [ -e index.php -a -e wp-includes/version.php ]; then
45-
echo >&2 "WordPress not found in $(pwd) - copying now..."
28+
echo >&2 "WordPress not found in $PWD - copying now..."
4629
if [ "$(ls -A)" ]; then
47-
echo >&2 "WARNING: $(pwd) is not empty - press Ctrl+C now if this is an error!"
30+
echo >&2 "WARNING: $PWD is not empty - press Ctrl+C now if this is an error!"
4831
( set -x; ls -A; sleep 10 )
4932
fi
5033
tar cf - --one-file-system -C /usr/src/wordpress . | tar xf -
51-
echo >&2 "Complete! WordPress has been successfully copied to $(pwd)"
34+
echo >&2 "Complete! WordPress has been successfully copied to $PWD"
5235
if [ ! -e .htaccess ]; then
5336
# NOTE: The "Indexes" option is disabled in the php:apache base image
5437
cat > .htaccess <<-'EOF'
@@ -69,54 +52,9 @@ if [[ "$1" == apache2* ]] || [ "$1" == php-fpm ]; then
6952

7053
# TODO handle WordPress upgrades magically in the same way, but only if wp-includes/version.php's $wp_version is less than /usr/src/wordpress/wp-includes/version.php's $wp_version
7154

72-
# version 4.4.1 decided to switch to windows line endings, that breaks our seds and awks
73-
# https://github.com/docker-library/wordpress/issues/116
74-
# https://github.com/WordPress/WordPress/commit/1acedc542fba2482bab88ec70d4bea4b997a92e4
75-
sed -ri -e 's/\r$//' wp-config*
76-
77-
if [ ! -e wp-config.php ]; then
78-
awk '/^\/\*.*stop editing.*\*\/$/ && c == 0 { c = 1; system("cat") } { print }' wp-config-sample.php > wp-config.php <<'EOPHP'
79-
// If we're behind a proxy server and using HTTPS, we need to alert Wordpress of that fact
80-
// see also http://codex.wordpress.org/Administration_Over_SSL#Using_a_Reverse_Proxy
81-
if (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https') {
82-
$_SERVER['HTTPS'] = 'on';
83-
}
84-
85-
EOPHP
86-
chown www-data:www-data wp-config.php
87-
fi
88-
89-
# see http://stackoverflow.com/a/2705678/433558
90-
sed_escape_lhs() {
91-
echo "$@" | sed -e 's/[]\/$*.^|[]/\\&/g'
92-
}
93-
sed_escape_rhs() {
94-
echo "$@" | sed -e 's/[\/&]/\\&/g'
95-
}
96-
php_escape() {
97-
php -r 'var_export(('$2') $argv[1]);' -- "$1"
98-
}
99-
set_config() {
100-
key="$1"
101-
value="$2"
102-
var_type="${3:-string}"
103-
start="(['\"])$(sed_escape_lhs "$key")\2\s*,"
104-
end="\);"
105-
if [ "${key:0:1}" = '$' ]; then
106-
start="^(\s*)$(sed_escape_lhs "$key")\s*="
107-
end=";"
108-
fi
109-
sed -ri -e "s/($start\s*).*($end)$/\1$(sed_escape_rhs "$(php_escape "$value" "$var_type")")\3/" wp-config.php
110-
}
111-
112-
set_config 'DB_HOST' "$WORDPRESS_DB_HOST"
113-
set_config 'DB_USER' "$WORDPRESS_DB_USER"
114-
set_config 'DB_PASSWORD' "$WORDPRESS_DB_PASSWORD"
115-
set_config 'DB_NAME' "$WORDPRESS_DB_NAME"
116-
11755
# allow any of these "Authentication Unique Keys and Salts." to be specified via
11856
# environment variables with a "WORDPRESS_" prefix (ie, "WORDPRESS_AUTH_KEY")
119-
UNIQUES=(
57+
uniqueEnvs=(
12058
AUTH_KEY
12159
SECURE_AUTH_KEY
12260
LOGGED_IN_KEY
@@ -126,41 +64,124 @@ EOPHP
12664
LOGGED_IN_SALT
12765
NONCE_SALT
12866
)
129-
for unique in "${UNIQUES[@]}"; do
130-
uniqVar="WORDPRESS_$unique"
131-
file_env "$uniqVar"
132-
if [ "${!uniqVar}" ]; then
133-
set_config "$unique" "${!uniqVar}"
134-
else
135-
# if not specified, let's generate a random value
136-
current_set="$(sed -rn -e "s/define\((([\'\"])$unique\2\s*,\s*)(['\"])(.*)\3\);/\4/p" wp-config.php)"
137-
if [ "$current_set" = 'put your unique phrase here' ]; then
138-
set_config "$unique" "$(head -c1m /dev/urandom | sha1sum | cut -d' ' -f1)"
139-
fi
67+
envs=(
68+
WORDPRESS_DB_HOST
69+
WORDPRESS_DB_USER
70+
WORDPRESS_DB_PASSWORD
71+
WORDPRESS_DB_NAME
72+
"${uniqueEnvs[@]/#/WORDPRESS_}"
73+
WORDPRESS_TABLE_PREFIX
74+
WORDPRESS_DEBUG
75+
)
76+
haveConfig=
77+
for e in "${envs[@]}"; do
78+
file_env "$e"
79+
if [ -z "$haveConfig" ] && [ -n "${!e}" ]; then
80+
haveConfig=1
14081
fi
14182
done
14283

143-
file_env 'WORDPRESS_TABLE_PREFIX'
144-
if [ "$WORDPRESS_TABLE_PREFIX" ]; then
145-
set_config '$table_prefix' "$WORDPRESS_TABLE_PREFIX"
84+
# linking backwards-compatibility
85+
if [ -n "${!MYSQL_ENV_MYSQL_*}" ]; then
86+
haveConfig=1
87+
# host defaults to "mysql" below if unspecified
88+
: "${WORDPRESS_DB_USER:=${MYSQL_ENV_MYSQL_USER:-root}}"
89+
if [ "$WORDPRESS_DB_USER" = 'root' ]; then
90+
: "${WORDPRESS_DB_PASSWORD:=${MYSQL_ENV_MYSQL_ROOT_PASSWORD:-}}"
91+
else
92+
: "${WORDPRESS_DB_PASSWORD:=${MYSQL_ENV_MYSQL_PASSWORD:-}}"
93+
fi
94+
: "${WORDPRESS_DB_NAME:=${MYSQL_ENV_MYSQL_DATABASE:-}}"
14695
fi
14796

148-
file_env 'WORDPRESS_DEBUG'
149-
if [ "$WORDPRESS_DEBUG" ]; then
150-
set_config 'WP_DEBUG' 1 boolean
151-
fi
97+
# only touch "wp-config.php" if we have environment-supplied configuration values
98+
if [ "$haveConfig" ]; then
99+
: "${WORDPRESS_DB_HOST:=mysql}"
100+
: "${WORDPRESS_DB_USER:=root}"
101+
: "${WORDPRESS_DB_PASSWORD:=}"
102+
: "${WORDPRESS_DB_NAME:=wordpress}"
152103

153-
TERM=dumb php -- "$WORDPRESS_DB_HOST" "$WORDPRESS_DB_USER" "$WORDPRESS_DB_PASSWORD" "$WORDPRESS_DB_NAME" <<'EOPHP'
104+
# version 4.4.1 decided to switch to windows line endings, that breaks our seds and awks
105+
# https://github.com/docker-library/wordpress/issues/116
106+
# https://github.com/WordPress/WordPress/commit/1acedc542fba2482bab88ec70d4bea4b997a92e4
107+
sed -ri -e 's/\r$//' wp-config*
108+
109+
if [ ! -e wp-config.php ]; then
110+
awk '/^\/\*.*stop editing.*\*\/$/ && c == 0 { c = 1; system("cat") } { print }' wp-config-sample.php > wp-config.php <<'EOPHP'
111+
// If we're behind a proxy server and using HTTPS, we need to alert Wordpress of that fact
112+
// see also http://codex.wordpress.org/Administration_Over_SSL#Using_a_Reverse_Proxy
113+
if (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https') {
114+
$_SERVER['HTTPS'] = 'on';
115+
}
116+
117+
EOPHP
118+
chown www-data:www-data wp-config.php
119+
fi
120+
121+
# see http://stackoverflow.com/a/2705678/433558
122+
sed_escape_lhs() {
123+
echo "$@" | sed -e 's/[]\/$*.^|[]/\\&/g'
124+
}
125+
sed_escape_rhs() {
126+
echo "$@" | sed -e 's/[\/&]/\\&/g'
127+
}
128+
php_escape() {
129+
php -r 'var_export(('$2') $argv[1]);' -- "$1"
130+
}
131+
set_config() {
132+
key="$1"
133+
value="$2"
134+
var_type="${3:-string}"
135+
start="(['\"])$(sed_escape_lhs "$key")\2\s*,"
136+
end="\);"
137+
if [ "${key:0:1}" = '$' ]; then
138+
start="^(\s*)$(sed_escape_lhs "$key")\s*="
139+
end=";"
140+
fi
141+
sed -ri -e "s/($start\s*).*($end)$/\1$(sed_escape_rhs "$(php_escape "$value" "$var_type")")\3/" wp-config.php
142+
}
143+
144+
set_config 'DB_HOST' "$WORDPRESS_DB_HOST"
145+
set_config 'DB_USER' "$WORDPRESS_DB_USER"
146+
set_config 'DB_PASSWORD' "$WORDPRESS_DB_PASSWORD"
147+
set_config 'DB_NAME' "$WORDPRESS_DB_NAME"
148+
149+
for unique in "${uniqueEnvs[@]}"; do
150+
uniqVar="WORDPRESS_$unique"
151+
if [ -n "${!uniqVar}" ]; then
152+
set_config "$unique" "${!uniqVar}"
153+
else
154+
# if not specified, let's generate a random value
155+
currentVal="$(sed -rn -e "s/define\((([\'\"])$unique\2\s*,\s*)(['\"])(.*)\3\);/\4/p" wp-config.php)"
156+
if [ "$currentVal" = 'put your unique phrase here' ]; then
157+
set_config "$unique" "$(head -c1m /dev/urandom | sha1sum | cut -d' ' -f1)"
158+
fi
159+
fi
160+
done
161+
162+
if [ "$WORDPRESS_TABLE_PREFIX" ]; then
163+
set_config '$table_prefix' "$WORDPRESS_TABLE_PREFIX"
164+
fi
165+
166+
if [ "$WORDPRESS_DEBUG" ]; then
167+
set_config 'WP_DEBUG' 1 boolean
168+
fi
169+
170+
TERM=dumb php -- <<'EOPHP'
154171
<?php
155172
// database might not exist, so let's try creating it (just to be safe)
156173
157174
$stderr = fopen('php://stderr', 'w');
158175
176+
$dir = getcwd();
177+
$_SERVER['SCRIPT_FILENAME'] = $dir . '/bogus.php'; // "functions.php" uses this value after we include the wp-config
178+
require_once($dir . '/wp-config.php');
179+
159180
// https://codex.wordpress.org/Editing_wp-config.php#MySQL_Alternate_Port
160181
// "hostname:port"
161182
// https://codex.wordpress.org/Editing_wp-config.php#MySQL_Sockets_or_Pipes
162183
// "hostname:unix-socket-path"
163-
list($host, $socket) = explode(':', $argv[1], 2);
184+
list($host, $socket) = explode(':', DB_HOST, 2);
164185
$port = 0;
165186
if (is_numeric($socket)) {
166187
$port = (int) $socket;
@@ -169,7 +190,7 @@ if (is_numeric($socket)) {
169190
170191
$maxTries = 10;
171192
do {
172-
$mysql = new mysqli($host, $argv[2], $argv[3], '', $port, $socket);
193+
$mysql = new mysqli($host, DB_USER, DB_PASSWORD, '', $port, $socket);
173194
if ($mysql->connect_error) {
174195
fwrite($stderr, "\n" . 'MySQL Connection Error: (' . $mysql->connect_errno . ') ' . $mysql->connect_error . "\n");
175196
--$maxTries;
@@ -180,14 +201,20 @@ do {
180201
}
181202
} while ($mysql->connect_error);
182203
183-
if (!$mysql->query('CREATE DATABASE IF NOT EXISTS `' . $mysql->real_escape_string($argv[4]) . '`')) {
204+
if (!$mysql->query('CREATE DATABASE IF NOT EXISTS `' . $mysql->real_escape_string(DB_NAME) . '`')) {
184205
fwrite($stderr, "\n" . 'MySQL "CREATE DATABASE" Error: ' . $mysql->error . "\n");
185206
$mysql->close();
186207
exit(1);
187208
}
188209
189210
$mysql->close();
190211
EOPHP
212+
fi
213+
214+
# now that we're definitely done writing configuration, let's clear out the relevant envrionment variables (so that stray "phpinfo()" calls don't leak secrets from our code)
215+
for e in "${envs[@]}"; do
216+
unset "$e"
217+
done
191218
fi
192219

193220
exec "$@"

0 commit comments

Comments
 (0)