-
-
Notifications
You must be signed in to change notification settings - Fork 33
/
20-set-app-defaults
318 lines (294 loc) · 12.8 KB
/
20-set-app-defaults
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
#!/usr/bin/with-contenv bash
#---------------------------------------------------------------------------------------------------------------------------
# VARIABLES
#---------------------------------------------------------------------------------------------------------------------------
: "${DEBUG:=false}"
#---------------------------------------------------------------------------------------------------------------------------
# FUNCTIONS
#---------------------------------------------------------------------------------------------------------------------------
function _info() { printf "\\r[ \\033[00;34mINFO\\033[0m ] %s\\n" "$@"; }
function _warn() { printf "\\r\\033[2K[ \\033[0;33mWARN\\033[0m ] %s\\n" "$@"; }
function _error() { printf "\\r\\033[2K[ \\033[0;31mFAIL\\033[0m ] %s\\n" "$@"; }
function _debug() { printf "\\r[ \\033[00;37mDBUG\\033[0m ] %s\\n" "$@"; }
function _pre_reqs() {
_info "DSMR Reader release: ${DSMR_VERSION}"
_info "DSMR Reader Docker release: ${DOCKER_TARGET_RELEASE}"
_info "Ensure permissions..."
chown -R app:app /app
chown -R app:app /config
chown -R app:app /defaults
_info "Setting architecture requirements..."
_detect_architecture
}
function _detect_architecture() {
arch=$(uname -m)
# _info "uname -m output: ${arch}"
longbit=$(getconf LONG_BIT)
if [[ "$arch" == 'x86_64' ]]; then
if [[ "$longbit" = '32' ]]; then
arch="i386"
_info "X32 Architecture"
else
arch="amd64"
_info "X64 Architecture"
fi
fi
if [[ "$arch" == 'x86_32' ]]; then
arch="i386"
_info "X32 Architecture"
fi
if [[ "$arch" == 'armv7l' ]]; then
arch="ARM"
_info "ARM Architecture"
fi
if [[ "$arch" == 'aarch64' ]]; then
arch="ARM64"
_info "ARM Architecture"
fi
if [ "$arch" == 'unknown' ]; then
#Assuming amd64, need to address certain distros uname giving "unknown"
arch="amd64"
_info "X64 Architecture"
fi
}
function _dsmr_datalogger_mode() {
if [[ "${DSMRREADER_REMOTE_DATALOGGER_MODE}" = standalone ]]; then
_info "Configuring DSMR in standlone datalogger mode...."
elif [[ "${DSMRREADER_REMOTE_DATALOGGER_MODE}" = sender ]]; then
_info "Configuring DSMR in sender datalogger mode...."
__dsmr_client_installation
elif [[ "${DSMRREADER_REMOTE_DATALOGGER_MODE}" = receiver ]]; then
_info "Configuring DSMR in receiver datalogger mode...."
else
_error "Invalid value of the DSMRREADER_REMOTE_DATALOGGER_MODE has been set. Exiting..."
exit 1
fi
}
function __dsmr_client_installation() {
_info "Installing the DSMR remote datalogger client..."
touch /app/.env
if [[ -z "${DSMRREADER_REMOTE_DATALOGGER_API_HOSTS}" || -z "${DSMRREADER_REMOTE_DATALOGGER_API_KEYS}" || -z "${DSMRREADER_REMOTE_DATALOGGER_INPUT_METHOD}" ]]; then
_error "DSMRREADER_REMOTE_DATALOGGER_API_HOSTS and/or DSMRREADER_REMOTE_DATALOGGER_API_KEYS and/or DSMRREADER_REMOTE_DATALOGGER_INPUT_METHOD required values are not set. Exiting..."
exit 1
else
if [[ "${DSMRREADER_REMOTE_DATALOGGER_INPUT_METHOD}" = ipv4 ]]; then
_info "Using a network socket for the DSMR remote datalogger..."
if [[ -z "${DSMRREADER_REMOTE_DATALOGGER_NETWORK_HOST}" || -z "${DSMRREADER_REMOTE_DATALOGGER_NETWORK_PORT}" ]]; then
_error "DSMRREADER_REMOTE_DATALOGGER_NETWORK_HOST and/or DSMRREADER_REMOTE_DATALOGGER_NETWORK_PORT required values are not set. Exiting..."
exit 1
else
_info "Adding DSMRREADER_REMOTE_DATALOGGER_NETWORK_HOST and DSMRREADER_REMOTE_DATALOGGER_NETWORK_PORT to the DSMR remote datalogger configuration..."
{
echo DSMRREADER_REMOTE_DATALOGGER_NETWORK_HOST="${DSMRREADER_REMOTE_DATALOGGER_NETWORK_HOST}"
echo DSMRREADER_REMOTE_DATALOGGER_NETWORK_PORT="${DSMRREADER_REMOTE_DATALOGGER_NETWORK_PORT}"
} >>/app/.env
fi
elif [[ "${DSMRREADER_REMOTE_DATALOGGER_INPUT_METHOD}" = serial ]]; then
_info "Using a serial connection for the DSMR remote datalogger..."
if [[ -z "${DSMRREADER_REMOTE_DATALOGGER_SERIAL_PORT}" || -z "${DSMRREADER_REMOTE_DATALOGGER_SERIAL_BAUDRATE}" ]]; then
_error "DSMRREADER_REMOTE_DATALOGGER_SERIAL_PORT and/or DSMRREADER_REMOTE_DATALOGGER_SERIAL_BAUDRATE required values are not set. Exiting..."
exit 1
else
_info "Adding DSMRREADER_REMOTE_DATALOGGER_SERIAL_PORT and DSMRREADER_REMOTE_DATALOGGER_SERIAL_PORT to the DSMR remote datalogger configuration..."
{
echo DSMRREADER_REMOTE_DATALOGGER_SERIAL_PORT="${DSMRREADER_REMOTE_DATALOGGER_SERIAL_PORT}"
echo DSMRREADER_REMOTE_DATALOGGER_SERIAL_PORT="${DSMRREADER_REMOTE_DATALOGGER_SERIAL_PORT}"
} >>/app/.env
fi
else
_error "Incorrect configuration of the DSMRREADER_REMOTE_DATALOGGER_INPUT_METHOD value. Exiting..."
exit 1
fi
_info "Adding DSMRREADER_REMOTE_DATALOGGER_API_HOSTS, DSMRREADER_REMOTE_DATALOGGER_API_KEYS and DSMRREADER_REMOTE_DATALOGGER_INPUT_METHOD to the DSMR remote datalogger configuration..."
{
echo DSMRREADER_REMOTE_DATALOGGER_API_HOSTS="${DSMRREADER_REMOTE_DATALOGGER_API_HOSTS}"
echo DSMRREADER_REMOTE_DATALOGGER_API_KEYS="${DSMRREADER_REMOTE_DATALOGGER_API_KEYS}"
echo DSMRREADER_REMOTE_DATALOGGER_INPUT_METHOD="${DSMRREADER_REMOTE_DATALOGGER_INPUT_METHOD}"
} >>/app/.env
fi
if [[ -n "${DSMRREADER_REMOTE_DATALOGGER_TIMEOUT}" ]]; then
_info "Adding DSMRREADER_REMOTE_DATALOGGER_TIMEOUT to the DSMR remote datalogger configuration..."
echo DSMRREADER_REMOTE_DATALOGGER_TIMEOUT="${DSMRREADER_REMOTE_DATALOGGER_TIMEOUT}" >>/app/.env
fi
if [[ -n "${DSMRREADER_REMOTE_DATALOGGER_SLEEP}" ]]; then
_info "Adding DSMRREADER_REMOTE_DATALOGGER_SLEEP to the DSMR remote datalogger configuration..."
echo DSMRREADER_REMOTE_DATALOGGER_SLEEP="${DSMRREADER_REMOTE_DATALOGGER_SLEEP}" >>/app/.env
fi
if [[ -n "${DSMRREADER_REMOTE_DATALOGGER_DEBUG_LOGGING}" ]]; then
_info "Adding DSMRREADER_REMOTE_DATALOGGER_DEBUG_LOGGING to the DSMR remote datalogger configuration..."
echo DSMRREADER_REMOTE_DATALOGGER_DEBUG_LOGGING="${DSMRREADER_REMOTE_DATALOGGER_DEBUG_LOGGING}" >>/app/.env
fi
}
function _check_device() {
_info "Fixing /dev/ttyUSB* security..."
if ls /dev/ttyUSB* 1>/dev/null 2>&1; then
chmod 666 /dev/ttyUSB*
fi
}
function _check_db_availability() {
_info "Verifying if the DSMR web credential variables have been set..."
if [[ -z "${DSMRREADER_ADMIN_USER}" ]] || [[ -z "${DSMRREADER_ADMIN_PASSWORD}" ]]; then
_error "DSMR web credentials not set. Exiting..."
exit 1
fi
if [[ -n "${DJANGO_DATABASE_ENGINE}" ]]; then
_info "Verifying database connectivity to host: ${DJANGO_DATABASE_HOST} with port: ${DJANGO_DATABASE_PORT}..."
for i in {1..30}; do
if ! nc -z "${DJANGO_DATABASE_HOST}" "${DJANGO_DATABASE_PORT}"; then
sleep 1
printf "\\rTesting database connectivity: %s second(s) of 30 seconds..." "$i"
if [[ $i == 30 ]]; then
_error "Database connectivity couldn't be verified! Please verify your settings. Exiting..."
exit 1
fi
else
_info "Database connectivity successfully verified!"
if [[ "${VACUUM_DB_ON_STARTUP}" = true ]]; then
_cleandb
fi
break
fi
done
fi
}
function _run_post_config() {
_info "Running post configuration..."
/usr/local/bin/python3 /app/manage.py migrate --noinput
/usr/local/bin/python3 /app/manage.py collectstatic --noinput
/usr/local/bin/python3 /app/manage.py dsmr_superuser
}
function _nginx_change_listen_port() {
if [[ -z "${ENABLE_NGINX_SSL}" ]]; then
if [[ -n "${NGINX_LISTEN_PORT}" ]]; then
_info "Changing the default internal NGINX listen port to ${NGINX_LISTEN_PORT}..."
sed -i "s/listen\s*80/listen ${NGINX_LISTEN_PORT}/g" /etc/nginx/http.d/dsmr-webinterface.conf
fi
fi
}
function _nginx_ssl_configuration() {
_info "Checking for NGINX SSL configuration..."
if [[ -z "${NGINX_LISTEN_PORT}" ]]; then
if [[ -n "${ENABLE_NGINX_SSL}" ]]; then
if [[ "${ENABLE_NGINX_SSL}" = true ]]; then
if [[ ! -f "/etc/ssl/private/fullchain.pem" ]] && [[ ! -f "/etc/ssl/private/fullchain.pem" ]]; then
_error "Make sure /etc/ssl/private/fullchain.pem and /etc/ssl/private/privkey.pem are mounted in the Docker container and exist!"
exit 1
else
_info "Required files /etc/ssl/private/fullchain.pem and /etc/ssl/private/privkey.pem exists."
fi
if grep -q "443" /etc/nginx/http.d/dsmr-webinterface.conf; then
_info "SSL has already been enabled..."
else
sed -i '/listen\s*80/r '<(
cat <<-END_HEREDOC
listen 443 ssl;
ssl_certificate /etc/ssl/private/fullchain.pem;
ssl_certificate_key /etc/ssl/private/privkey.pem;
END_HEREDOC
) /etc/nginx/http.d/dsmr-webinterface.conf
fi
if nginx -c /etc/nginx/nginx.conf -t 2>/dev/null; then
_info "NGINX SSL configured and enabled"
return
else
_error "NGINX configuration error"
exit 1
fi
fi
fi
fi
_info "ENABLE_NGINX_SSL is disabled, nothing to see here. Continuing..."
}
function _generate_auth_configuration() {
_info "Checking for HTTP AUTHENTICATION configuration..."
if [[ -n "${ENABLE_HTTP_AUTH}" ]]; then
if [[ "${ENABLE_HTTP_AUTH}" = true ]]; then
_info "ENABLE_HTTP_AUTH is enabled, let's secure this!"
canWeContinue=true
if [[ -z "${HTTP_AUTH_USERNAME}" ]]; then
_warn "Please provide a HTTP_AUTH_USERNAME"
canWeContinue=false
fi
if [[ -z "${HTTP_AUTH_PASSWORD}" ]]; then
_warn "Please provide a HTTP_AUTH_PASSWORD"
canWeContinue=false
fi
if [[ "${canWeContinue}" = false ]]; then
_error "Cannot generate a valid .htpasswd file, please check above warnings."
exit 1
fi
_info "Generating htpasswd..."
HTTP_AUTH_CRYPT_PASSWORD=$(openssl passwd -apr1 "${HTTP_AUTH_PASSWORD}")
printf "%s:%s\n" "${HTTP_AUTH_USERNAME}" "${HTTP_AUTH_CRYPT_PASSWORD}" >/etc/nginx/htpasswd
_info "Done! Enabling the configuration in NGINX..."
sed -i "s/## auth_basic/ auth_basic/" /etc/nginx/http.d/dsmr-webinterface.conf
if nginx -c /etc/nginx/nginx.conf -t 2>/dev/null; then
_info "HTTP AUTHENTICATION configured and enabled"
return
else
_error "NGINX configuration error"
exit 1
fi
fi
fi
_info "ENABLE_HTTP_AUTH is disabled, nothing to see here. Continuing..."
}
function _generate_clientcert_auth_configuration() {
_info "Checking for CLIENT CERTIFICATE AUTHENTICATION configuration..."
if [[ -n "${ENABLE_CLIENTCERT_AUTH}" ]]; then
if [[ "${ENABLE_CLIENTCERT_AUTH}" = true ]]; then
_info "ENABLE_CLIENTCERT_AUTH is enabled, let's secure this!"
canWeContinue=true
if [[ ! -f /etc/nginx/client_cert/cacert.pem ]]; then
_warn "Please map a CA.pem file to /etc/nginx/client_cert/cacert.pem"
canWeContinue=false
fi
if [[ "${canWeContinue}" = false ]]; then
_error "Sorry, something failed. Please check above warnings."
exit 1
fi
_info "Enabling the configuration in NGINX..."
sed -i '/server_name _;/a\\tssl_client_certificate /etc/nginx/client_cert/cacert.pem;\n\tssl_verify_client on;' /etc/nginx/http.d/dsmr-webinterface.conf
if [[ -f /etc/nginx/client_cert/ca.crl ]]; then
_info "Found CRL file, adding to configuration..."
sed -i '/server_name _;/a\\tssl_crl /etc/nginx/client_cert/ca.crl;' /etc/nginx/http.d/dsmr-webinterface.conf
fi
if nginx -c /etc/nginx/nginx.conf -t 2>/dev/null; then
_info "CLIENT CERT AUTHENTICATION configured and enabled"
return
else
_error "NGINX configuration error"
exit 1
fi
fi
fi
_info "ENABLE_CLIENTCERT_AUTH is disabled, nothing to see here. Continuing..."
}
function _iframe {
if [[ "${ENABLE_IFRAME}" = true ]]; then
_info "Enabling IFrame..."
sed -i "/^from dsmrreader.*/a X_FRAME_OPTIONS = 'ALLOWALL'" /app/dsmrreader/settings.py
fi
}
function _cleandb {
_info "Vacuum cleaning enabled. Vacuming database..."
/app/cleandb.sh
}
#---------------------------------------------------------------------------------------------------------------------------
# MAIN
#---------------------------------------------------------------------------------------------------------------------------
[[ "${DEBUG}" = true ]] && set -o xtrace
_pre_reqs
_iframe
if [[ "${DSMRREADER_REMOTE_DATALOGGER_MODE}" = standalone || "${DSMRREADER_REMOTE_DATALOGGER_MODE}" = sender ]]; then
_check_device
fi
if [[ "${DSMRREADER_REMOTE_DATALOGGER_MODE}" = standalone || "${DSMRREADER_REMOTE_DATALOGGER_MODE}" = receiver ]]; then
_check_db_availability
_run_post_config
_nginx_change_listen_port
_generate_clientcert_auth_configuration
_nginx_ssl_configuration
_generate_auth_configuration
fi
_dsmr_datalogger_mode