-
Notifications
You must be signed in to change notification settings - Fork 8
/
cloud-init.sh
422 lines (365 loc) · 14 KB
/
cloud-init.sh
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
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
#!/bin/bash
set -x
%{ for config_key, config_value in proxy_config ~}
%{ if config_value != null ~}
export ${config_key}="${config_value}"
%{ endif ~}
%{ endfor ~}
# Proxy Setting
echo "Checking and setting Proxy configuration..."
# Checking if HTTP Proxy(s) provided and setting
%{ if proxy_config.http_proxy != null ~}
echo "http_proxy=${proxy_config.http_proxy}" >> /etc/environment
touch /etc/apt/apt.conf.d/proxy.conf
echo "Acquire::http::Proxy \"${proxy_config.http_proxy}\";" >> /etc/apt/apt.conf.d/proxy.conf
echo "HTTP Proxy configured"
%{ else ~}
echo "No HTTP Proxy configuration found. Skipping"
%{ endif ~}
# Checking if HTTPS Proxy(s) provided and setting
%{ if proxy_config.https_proxy != null ~}
echo "https_proxy=${proxy_config.https_proxy}" >> /etc/environment
touch /etc/apt/apt.conf.d/proxy.conf
echo "Acquire::https::Proxy \"${proxy_config.https_proxy}\";" >> /etc/apt/apt.conf.d/proxy.conf
echo "HTTPS Proxy configured"
%{ else ~}
echo "No HTTPS Proxy configuration found. Skipping"
%{ endif ~}
# Checking if No Proxy configuration provided and setting
%{ if proxy_config.no_proxy != null ~}
echo "no_proxy=${proxy_config.no_proxy}" >> /etc/environment
echo "No-Proxy settings configured"
%{ else ~}
echo "No No-Proxy configuration found. Skipping"
%{ endif ~}
exec &> /tmp/cloud-init.log
# Pause: in testing we need this
# to make sure we wait to be routed out
# the internet before trying to get
# packages
for ((i=1;i<=300;i++)); do
curl ubuntu.com/security/notices
if [ $? -eq 0 ]; then
break
fi
sleep 1
done
# Function to grab SSM parameters
aws_get_parameter() {
aws ssm --region ${region} get-parameter \
--name $1 \
--with-decryption \
--output text \
--query Parameter.Value 2>/dev/null
}
apt-get update
apt-get upgrade -y
apt-get install -y apt-listchanges unattended-upgrades \
ntp runit runit-systemd dnsutils curl telnet pwgen \
postgresql-client perl libpcre3 awscli jq
# Enable auto updates
echo "Enabling auto updates"
echo unattended-upgrades unattended-upgrades/enable_auto_updates boolean true \
| debconf-set-selections
dpkg-reconfigure -f noninteractive unattended-upgrades
# Installing decK
# https://github.com/hbagdi/deck
curl -sL https://github.com/hbagdi/deck/releases/download/v${deck_version}/deck_${deck_version}_linux_amd64.tar.gz \
-o deck.tar.gz
tar zxf deck.tar.gz deck
sudo mv deck /usr/local/bin
sudo chown root:kong /usr/local/bin/deck
sudo chmod 755 /usr/local/bin/deck
# These certificates are used for
# clustering Kong control plane
# and data plane when used in hybrid
# mode
%{ if lookup(kong_config, "KONG_ROLE", null) != null ~}
mkdir -p /etc/kong_clustering
%{ if kong_hybrid_conf.cluster_cert != "" ~}
cat << EOF >/etc/kong_clustering/cluster.crt
${kong_hybrid_conf.cluster_cert}
EOF
%{ endif ~}
%{ if kong_hybrid_conf.ca_cert != "" ~}
cat << EOF >/etc/kong_clustering/cluster_ca.crt
${kong_hybrid_conf.ca_cert}
EOF
%{ endif ~}
%{ if kong_hybrid_conf.cluster_key != "" ~}
cat << EOF >/etc/kong_clustering/cluster.key
${kong_hybrid_conf.cluster_key}
EOF
%{ endif ~}
%{ endif ~}
# Install Kong
%{ if ee_creds_ssm_param.license != null && ee_creds_ssm_param.bintray_username != null && ee_creds_ssm_param.bintray_password != null && ee_creds_ssm_param.admin_token != null ~}
EE_LICENSE=$(aws_get_parameter ${ee_creds_ssm_param.license})
EE_BINTRAY_USERNAME=$(aws_get_parameter ${ee_creds_ssm_param.bintray_username})
EE_BINTRAY_PASSWORD=$(aws_get_parameter ${ee_creds_ssm_param.bintray_password})
ADMIN_TOKEN=$(aws_get_parameter ${ee_creds_ssm_param.admin_token})
%{ else ~}
EE_LICENSE="placeholder"
%{ endif ~}
if [ "$EE_LICENSE" != "placeholder" ]; then
echo "Installing Kong EE"
curl -sL https://download.konghq.com/gateway-2.x-ubuntu-focal/pool/all/k/kong-enterprise-edition/${ee_pkg} \
-o ${ee_pkg}
if [ ! -f ${ee_pkg} ]; then
echo "Error: Enterprise edition download failed, aborting."
exit 1
fi
dpkg -i ${ee_pkg}
apt-get -f install -y
cat <<EOF > /etc/kong/license.json
$EE_LICENSE
EOF
chown root:kong /etc/kong/license.json
chmod 640 /etc/kong/license.json
else
echo "Installing Kong CE"
curl -sL "https://download.konghq.com/gateway-2.x-ubuntu-focal/pool/all/k/kong/${ce_pkg}" \
-o ${ce_pkg}
dpkg -i ${ce_pkg}
apt-get -f install -y
fi
%{ if lookup(kong_config, "KONG_ROLE", "embedded") != "data_plane" ~}
# Setup database
echo "Setting up Kong database"
PGPASSWORD=$(aws_get_parameter "${parameter_path}/db/password/master")
DB_PASSWORD=$(aws_get_parameter "${parameter_path}/db/password")
DB_HOST=${db_host}
DB_NAME=${db_name}
export PGPASSWORD
RESULT=$(psql --host $DB_HOST --username root \
--tuples-only --no-align postgres \
<<EOF
SELECT 1 FROM pg_roles WHERE rolname='${db_user}'
EOF
)
if [ $? != 0 ]; then
echo "Error: Database connection failed, please configure manually"
exit 1
fi
echo $RESULT | grep -q 1
if [ $? != 0 ]; then
psql --host $DB_HOST --username root postgres <<EOF
CREATE USER ${db_user} WITH PASSWORD '$DB_PASSWORD';
GRANT ${db_user} TO root;
CREATE DATABASE $DB_NAME OWNER = ${db_user};
EOF
fi
unset PGPASSWORD
%{ endif }
# Setup systemd unit file
cat <<EOF > /etc/systemd/system/kong-gw.service
[Unit]
Description=KongGW
Documentation=https://docs.konghq.com/
After=syslog.target network.target remote-fs.target nss-lookup.target
[Service]
ExecStartPre=/usr/local/bin/kong prepare -p /usr/local/kong
ExecStart=/usr/local/openresty/nginx/sbin/nginx -p /usr/local/kong -c nginx.conf
ExecReload=/usr/local/bin/kong prepare -p /usr/local/kong
ExecReload=/usr/local/openresty/nginx/sbin/nginx -p /usr/local/kong -c nginx.conf -s reload
ExecStop=/bin/kill -s QUIT $MAINPID
PrivateTmp=true
Environment=KONG_NGINX_DAEMON=off
Environment=KONG_PROXY_ACCESS_LOG=syslog:server=unix:/dev/log
Environment=KONG_PROXY_ERROR_LOG=syslog:server=unix:/dev/log
Environment=KONG_ADMIN_ACCESS_LOG=syslog:server=unix:/dev/log
Environment=KONG_ADMIN_ERROR_LOG=syslog:server=unix:/dev/log
EnvironmentFile=/etc/kong/kong_env.conf
LimitNOFILE=infinity
[Install]
WantedBy=multi-user.target
EOF
# Setup Configuration file
cat <<EOF > /etc/kong/kong_env.conf
%{if lookup(kong_config, "KONG_ROLE", "embedded") == "embedded" || lookup(kong_config, "KONG_ROLE", "embedded") == "control_plane" ~}
KONG_DATABASE="postgres"
KONG_PG_HOST="$DB_HOST"
KONG_PG_USER="${db_user}"
KONG_PG_PASSWORD="$DB_PASSWORD"
KONG_PG_DATABASE="$DB_NAME"
%{ endif }
# Load balancer headers
KONG_REAL_IP_HEADER="X-Forwarded-For"
KONG_TRUSTED_IPS="0.0.0.0/0"
%{if lookup(kong_config, "KONG_ROLE", null) != null ~}
%{if kong_config["KONG_ROLE"] == "data_plane" ~}
KONG_PROXY_LISTEN="0.0.0.0:${kong_ports.proxy}%{ if kong_ssl_uris.protocol == "https"} ssl%{endif}"
%{ else ~}
KONG_ADMIN_LISTEN="0.0.0.0:${kong_ports.admin_api}%{ if kong_ssl_uris.protocol == "https"} ssl%{endif}"
%{ endif ~}
%{ else ~}
KONG_PROXY_LISTEN="0.0.0.0:${kong_ports.proxy}%{ if kong_ssl_uris.protocol == "https"} ssl%{endif}"
KONG_ADMIN_LISTEN="0.0.0.0:${kong_ports.admin_api}%{ if kong_ssl_uris.protocol == "https"} ssl%{endif}"
%{ endif ~}
EOF
chmod 640 /etc/kong/kong_env.conf
chgrp kong /etc/kong/kong_env.conf
if [ "$EE_LICENSE" != "placeholder" ]; then
cat <<EOF >> /etc/kong/kong_env.conf
KONG_ADMIN_GUI_LISTEN="0.0.0.0:${kong_ports.admin_gui}%{ if kong_ssl_uris.protocol == "https"} ssl%{endif}"
KONG_PORTAL_GUI_LISTEN="0.0.0.0:${kong_ports.portal_gui}%{ if kong_ssl_uris.protocol == "https"} ssl%{endif}"
KONG_PORTAL_API_LISTEN="0.0.0.0:${kong_ports.portal_api}%{ if kong_ssl_uris.protocol == "https"} ssl%{endif}"
${api_uri_env_name}="${replace(kong_ssl_uris.admin_api_uri, "${kong_ssl_uris.protocol}://", "")}"
KONG_ADMIN_GUI_URL="${kong_ssl_uris.admin_gui_url}"
%{ if portal_and_vitals_key_arn != "" }
KONG_PORTAL_AND_VITALS_KEY="${portal_and_vitals_key_arn}"
%{ endif }
KONG_PORTAL_GUI_PROTOCOL="${kong_ssl_uris.protocol}"
KONG_PORTAL_GUI_HOST="${replace(kong_ssl_uris.portal_gui_host, "${kong_ssl_uris.protocol}://", "")}"
KONG_PORTAL_API_URL="${kong_ssl_uris.portal_api_url}"
%{ if kong_ssl_uris.portal_cors_origins != null ~}
KONG_PORTAL_CORS_ORIGINS="${kong_ssl_uris.portal_cors_origins}"
%{ endif ~}
EOF
for DIR in gui lib portal; do
chown -R kong:kong /usr/local/kong/$DIR
done
else
# CE does not create the kong directory
mkdir /usr/local/kong
fi
chown root:kong /usr/local/kong
chmod 2775 /usr/local/kong
%{if lookup(kong_config, "KONG_ROLE", "embedded") == "embedded" || lookup(kong_config, "KONG_ROLE", "embedded") == "control_plane" ~}
# Initialize Kong
echo "Initializing Kong"
export KONG_DATABASE="postgres"
export KONG_PG_HOST="$DB_HOST"
export KONG_PG_DATABASE="$DB_NAME"
export KONG_PG_USER="${db_user}"
export KONG_PG_PASSWORD="$DB_PASSWORD"
export KONG_PG_DATABASE="$DB_NAME"
if [ "$EE_LICENSE" != "placeholder" ]; then
export KONG_PASSWORD=$ADMIN_TOKEN
kong migrations bootstrap %{ if clear_database}-f %{endif}
else
kong migrations bootstrap
fi
unset KONG_DATABASE
unset KONG_PG_HOST
unset KONG_PG_DATABASE
unset KONG_PG_USER
unset KONG_PG_PASSWORD
unset KONG_PG_DATABASE
%{ endif ~}
systemctl enable --now kong-gw
%{if lookup(kong_config, "KONG_ROLE", "embedded") == "embedded" || lookup(kong_config, "KONG_ROLE", "embedded") == "control_plane" ~}
# Verify Admin API is up
RUNNING=0
for I in 1 2 3 4 5 6 7 8 9; do
curl -s -I %{ if kong_ssl_uris.protocol == "https"}-k https%{else}http%{endif}://localhost:${kong_ports.admin_api}/status | grep -q "200 OK"
if [ $? = 0 ]; then
RUNNING=1
break
fi
sleep 1
done
if [ $RUNNING = 0 ]; then
echo "Cannot connect to admin API, avoiding further configuration."
exit 1
fi
# Enable healthchecks using a kong endpoint
curl -s localhost:${kong_ports.admin_api}/services | \
jq -e -r '.data[] | select(.name | contains("status")) | if .id !="" then .name else false end'
if [ $? != 0 ]; then
echo "Configuring healthcheck"
curl -s -X POST http://localhost:${kong_ports.admin_api}/services \
-d name=status \
-d url=http://httpbin.org/get > /dev/null
curl -s -X POST http://localhost:${kong_ports.admin_api}/services/status/routes \
-d name=status \
-d 'methods[]=HEAD' \
-d 'methods[]=GET' \
-d 'paths[]=/status' > /dev/null
curl -s -X POST http://localhost:${kong_ports.admin_api}/services/status/plugins \
-d name=ip-restriction \
-d "config.whitelist=127.0.0.1" \
-d "config.whitelist=${vpc_cidr_block}" > /dev/null
fi
if [ "$EE_LICENSE" != "placeholder" ]; then
echo "Configuring enterprise edition settings"
# Monitor role, endpoints, user, for healthcheck
curl -s -X GET -I http://localhost:${kong_ports.admin_api}/rbac/roles/monitor | grep -q "200 OK"
if [ $? != 0 ]; then
COMMENT="Load balancer access to /status"
curl -s -X POST http://localhost:${kong_ports.admin_api}/rbac/roles \
-d name=monitor \
-d comment="$COMMENT" > /dev/null
curl -s -X POST http://localhost:${kong_ports.admin_api}/rbac/roles/monitor/endpoints \
-d endpoint=/status -d actions=read \
-d comment="$COMMENT" > /dev/null
curl -s -X POST http://localhost:${kong_ports.admin_api}/rbac/users \
-d name=monitor -d user_token=monitor \
-d comment="$COMMENT" > /dev/null
curl -s -X POST http://localhost:${kong_ports.admin_api}/rbac/users/monitor/roles \
-d roles=monitor > /dev/null
# Add authentication token for /status
curl -s -X POST http://localhost:${kong_ports.admin_api}/services/status/plugins \
-d name=request-transformer \
-d 'config.add.headers[]=Kong-Admin-Token:monitor' > /dev/null
fi
cat <<EOF >> /etc/kong/kong_env.conf
%{ if lookup(kong_config, "KONG_ADMIN_GUI_SESSION_CONF", null) == null }
KONG_ADMIN_GUI_SESSION_CONF="{\"secret\":\"${session_secret}\",\"cookie_secure\":false}"
KONG_ADMIN_GUI_AUTH="basic-auth"
KONG_ENFORCE_RBAC="on"
KONG_ADMIN_LISTEN="0.0.0.0:8001, 0.0.0.0:8444 ssl"
%{ endif }
EOF
fi
%{ endif }
cat <<EOF >> /etc/kong/kong_env.conf
%{ if lookup(kong_config, "KONG_ROLE", null) == "control_plane" ~}
KONG_CLUSTER_MTLS="${kong_hybrid_conf.mtls}"
%{ if kong_hybrid_conf.ca_cert != "" ~}
KONG_CLUSTER_CA_CERT="/etc/kong_clustering/cluster_ca.crt"
%{ endif ~}
KONG_CLUSTER_CERT="/etc/kong_clustering/cluster.crt"
KONG_CLUSTER_CERT_KEY="/etc/kong_clustering/cluster.key"
KONG_CLUSTER_SERVER_NAME="${kong_hybrid_conf.server_name}"
# ADMIN API
KONG_ADMIN_SSL_CERT="/etc/kong_clustering/cluster.crt"
KONG_ADMIN_SSL_CERT_KEY="/etc/kong_clustering/cluster.key"
# ADMIN GUI
KONG_ADMIN_GUI_SSL_CERT="/etc/kong_clustering/cluster.crt"
KONG_ADMIN_GUI_SSL_CERT_KEY="/etc/kong_clustering/cluster.key"
# PORTAL API
KONG_PORTAL_API_SSL_CERT="/etc/kong_clustering/cluster.crt"
KONG_PORTAL_API_SSL_CERT_KEY="/etc/kong_clustering/cluster.key"
# PORTAL GUI
KONG_PORTAL_GUI_SSL_CERT="/etc/kong_clustering/cluster.crt"
KONG_PORTAL_GUI_SSL_CERT_KEY="/etc/kong_clustering/cluster.key"
%{ endif ~}
%{ if lookup(kong_config, "KONG_ROLE", null) == "data_plane" ~}
KONG_CLUSTER_MTLS="${kong_hybrid_conf.mtls}"
%{ if kong_hybrid_conf.ca_cert != "" ~}
KONG_CLUSTER_CA_CERT="/etc/kong_clustering/cluster_ca.crt"
%{ endif ~}
KONG_CLUSTER_CERT="/etc/kong_clustering/cluster.crt"
KONG_CLUSTER_CERT_KEY="/etc/kong_clustering/cluster.key"
KONG_CLUSTER_SERVER_NAME="${kong_hybrid_conf.server_name}"
KONG_LUA_SSL_TRUSTED_CERTIFICATE="/etc/kong_clustering/cluster.crt"
KONG_SSL_CERT="/etc/kong_clustering/cluster.crt"
KONG_SSL_CERT_KEY="/etc/kong_clustering/cluster.key"
KONG_CLUSTER_CONTROL_PLANE="${kong_hybrid_conf.endpoint}:${kong_ports.cluster}"
KONG_CLUSTER_TELEMETRY_ENDPOINT="${kong_hybrid_conf.endpoint}:${kong_ports.telemetry}"
%{ endif ~}
KONG_PLUGINS="${kong_plugins}"
KONG_VITALS="${kong_vitals_enabled}"
%{ if kong_vitals_enabled == "on" }
%{ if vitals_endpoint != "" }
KONG_VITALS_STRATEGY="prometheus"
KONG_VITALS_STATSD_ADDRESS="${vitals_endpoint}"
%{ endif }
KONG_VITALS_TSDB_ADDRESS=${vitals_tsdb_address}
%{ endif }
%{ for key, value in kong_config ~}
${key}="${value}"
%{ endfor ~}
EOF
systemctl restart kong-gw