-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathinit-aws-auth-vpn
executable file
·308 lines (249 loc) · 9.24 KB
/
init-aws-auth-vpn
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
#!/bin/bash
set -e
readonly DEFAULT_POLL_DURATION=5
readonly DEFAULT_SERVICE_INTERVAL=60
EXECDIR="$(pwd)"
SCRIPTDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" # The directory of this script
function print_usage {
echo
echo "Usage: init-aws-auth-vpn [OPTIONS]"
echo
echo "Retrieves a specific payload provided by firehawk to an SQS queue. The payload allows temporary use of a vault token to aquire a VPN cert"
echo "You must already have AWS credentials configured for this function to work in."
echo
echo "Options:"
echo
echo -e " --resourcetier\tThe environment to use (dev/blue/green/main)"
echo -e " --install-service\tInstall a service to regularly check for VPN credentials if there is no VPN tun interface established."
echo
echo "Example: Wait for VPN payload in message queue."
echo
echo " init-aws-auth-vpn --resourcetier dev"
echo
echo "Example: Install as a service to poll for VPN auth payload. Service will poll 3 times every $DEFAULT_SERVICE_INTERVAL seconds. "
echo
echo " init-aws-auth-vpn --resourcetier dev --install-service"
}
function log {
local -r level="$1"
local -r message="$2"
local -r timestamp=$(date +"%Y-%m-%d %H:%M:%S")
>&2 echo -e "${timestamp} [${level}] [$SCRIPT_NAME] ${message}"
}
function log_info {
local -r message="$1"
log "INFO" "$message"
}
function log_warn {
local -r message="$1"
log "WARN" "$message"
}
function log_error {
local -r message="$1"
log "ERROR" "$message"
}
function error_if_empty {
if [[ -z "$2" ]]; then
log_error "$1"
exit 1
fi
return
}
function assert_not_empty {
local -r arg_name="$1"
local -r arg_value="$2"
if [[ -z "$arg_value" ]]; then
log_error "The value for '$arg_name' cannot be empty"
print_usage
exit 1
fi
}
# function cron { # See https://stackoverflow.com/questions/878600/how-to-create-a-cron-job-using-bash-automatically-without-the-interactive-editor
# local -r resourcetier="$1"
# log "...Configuring cron.d to ensure VPN is up once per minute."
# sudo cat > /etc/cron.d/aws-auth-vpn << EOF
# SHELL=/bin/bash
# PATH=/sbin:/bin:/usr/sbin:/usr/bin
# HOME=/home/deployuser
# * * * * * deployuser /deployuser/scripts/firehawk-auth-scripts/init-aws-auth-vpn --resourcetier $resourcetier
# EOF
# }
function install_service { # see https://opensource.com/article/20/7/systemd-timers for further examples
local -r resourcetier="$1"
local -r target_script_dir="/opt/firehawk-auth-scripts"
# set -x
sudo mkdir -p $target_script_dir
# sudo chmod -R u=rwX,g=rwX,o=rwX $target_script_dir
sudo cp -fr $SCRIPTDIR/* $target_script_dir
sudo chown -R deployuser:deployuser $target_script_dir
sudo chmod -R u=rwX,g=rwX,o=rX $target_script_dir
sudo chmod u+x,g+x $target_script_dir/init-aws-auth-vpn
if [[ -z "$target_script_dir" ]]; then
echo "ERROR no defined target_script_dir: $target_script_dir "
exit 1
fi
var=$1
sudo tee "/etc/systemd/system/awsauthvpn.service" > /dev/null <<EOF
[Unit]
Description=Service: Ensure VPN credentials are current (Firehawk: Utilises AWS CLI user credentials)
Wants=awsauthvpn.timer
[Service]
Type=oneshot
User=deployuser
Group=deployuser
ExecStart=$target_script_dir/init-aws-auth-vpn --resourcetier $resourcetier
[Install]
WantedBy=multi-user.target
EOF
sudo tee "/etc/systemd/system/awsauthvpn.timer" > /dev/null <<EOF
[Unit]
Description=Regular timer to handle VPN auth changes - Automates a VPN with dynamic credentials.
Requires=awsauthvpn.service
[Timer]
Unit=awsauthvpn.service
OnUnitActiveSec=$DEFAULT_SERVICE_INTERVAL
[Install]
WantedBy=timers.target
EOF
echo
echo "...Starting and enabling service on boot"
echo
sudo systemctl start awsauthvpn
sudo systemctl daemon-reload
sudo systemctl enable awsauthvpn
completion_message=$(cat << EOF
### Firehawk VPN Service Message:
Provided you have run init-aws-auth-ssh and have SSH certificates configured, if the service isn't running, start the service with:
sudo systemctl start awsauthvpn
You can enable on boot with:
sudo systemctl enable awsauthvpn
You can view the service logs with:
sudo journalctl -S today -u awsauthvpn
Or follow live output with:
sudo journalctl -f -u awsauthvpn
###
EOF
)
# echo "$completion_message"
if sudo test -f "/etc/motd"; then
grep -q "^Firehawk VPN Service Message:" /etc/motd || echo "$completion_message" | sudo tee --append /etc/motd
else
sudo touch /etc/motd
echo "$completion_message" | sudo tee --append /etc/motd
fi
}
function ssm_get_parm {
local -r parm_name="$1"
output=$(aws ssm get-parameters --with-decryption --names ${parm_name}) && exit_status=0 || exit_status=$?
invalid=$(echo ${output} | jq -r .'InvalidParameters | length')
if [[ $exit_status -eq 0 && $invalid -eq 0 ]]; then
log "Result: ${output}"
value=$(echo ${output} | jq -r '.Parameters[0].Value')
echo "$value"
return
fi
log "...Failed retrieving: ${parm_name}"
log "Result: ${output}"
}
function get_vpn_cert {
local -r resourcetier="$1"
local -r host1="$2"
local -r host2="$3"
local -r vault_token="$4"
echo "Request the VPN config / certs"
source_file_path="/usr/local/openvpn_as/scripts/seperate/client.ovpn" # the original file path that was stored in vault
source_vault_path="$resourcetier/data/vpn/client_cert_files$source_file_path" # the full namespace / path to the file in vault.
target_path="$SCRIPTDIR/../openvpn_config/$(basename $source_file_path)"
rm -f $SCRIPTDIR/../openvpn_config/client.ovpn
rm -f $SCRIPTDIR/../openvpn_config/openvpn.conf
$SCRIPTDIR/get-vault-file --host1 $host1 --host2 $host2 --source-vault-path $source_vault_path --target-path $target_path --vault-token $vault_token
# Replicate file for vpn. This might be able to be deprecated, or replaced with a move
cp -f $SCRIPTDIR/../openvpn_config/client.ovpn $SCRIPTDIR/../openvpn_config/openvpn.conf
# echo "Request the deadline client certifcate."
# source_file_path="/opt/Thinkbox/certs/Deadline10RemoteClient.pfx" # the original file path that was stored in vault
# source_vault_path="$resourcetier/data/deadline/client_cert_files$source_file_path" # the full namespace / path to the file in vault.
# target_path="$HOME/.ssh/$(basename $source_file_path)"
# $SCRIPTDIR/get-vault-file --host1 $host1 --host2 $host2 --source-vault-path $source_vault_path --target-path $target_path --vault-token $VAULT_TOKEN
# openvpn_user=$openvpn_user openvpn_user_pw=$openvpn_user_pw
# vagrant up
}
function poll_sqs_remote_in_vpn {
local -r resourcetier="$1"
local -r parm_name="/firehawk/resourcetier/$resourcetier/sqs_remote_in_vpn_url"
local -r sqs_queue_url="$(ssm_get_parm "$parm_name")"
log "...Polling SQS queue for vault and vpn pass"
local -r max_count=3 # set to 1 or larger to limit the number of retries
local count=0
local poll="true"
while [[ "$poll" == "true" ]]; do # the funciton will poll the message queue until a message is received, or count is reached.
((count+=1))
local msg="$(aws sqs receive-message --queue-url $sqs_queue_url)"
if [[ ! -z "$msg" ]]; then
poll="false"
local reciept_handle="$(echo "$msg" | jq -r '.Messages[] | .ReceiptHandle')"
aws sqs delete-message --queue-url $sqs_queue_url --receipt-handle $reciept_handle && echo "$msg" | jq -r '.Messages[] | .Body'
fi
if [[ "$poll" == "true" ]]; then
if [[ $max_count -gt 0 ]] && [[ $count -ge $max_count ]]; then
poll="false"
log "Max count reached."
else
log "...Waiting $DEFAULT_POLL_DURATION seconds before retry."
sleep $DEFAULT_POLL_DURATION
fi
fi
done
}
function install {
local resourcetier=""
local run_vpn="true"
local install_service="false"
while [[ $# > 0 ]]; do
local key="$1"
case "$key" in
--resourcetier)
resourcetier="$2"
shift
;;
--install-service)
run_vpn="false"
install_service="true"
;;
--help)
print_usage
exit
;;
*)
log_error "Unrecognized argument: $key"
print_usage
exit 1
;;
esac
shift
done
error_if_empty "Argument resourcetier or env var TF_VAR_resourcetier not provided" "$resourcetier"
if [[ "$install_service" == "true" ]]; then
install_service "$resourcetier"
fi
if [[ "$run_vpn" == "true" ]]; then
if ! /sbin/ifconfig tun0 | grep -q "00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00"; then
log "tun0 down"
log "...Getting SQS endpoint from SSM Parameter and await SQS message for VPN credentials."
local -r result="$(poll_sqs_remote_in_vpn $resourcetier)"
if [[ ! -z "$result" ]]; then
local -r openvpn_user="openvpnas"
local -r openvpn_user_pw=$(echo "$result" | jq -r '.openvpn_admin_pw')
local -r host1=$(echo "$result" | jq -r '.host1')
local -r host2=$(echo "$result" | jq -r '.host2')
local -r vault_token=$(echo "$result" | jq -r '.token')
get_vpn_cert "$resourcetier" "$host1" "$host2" "$vault_token"
cd /opt/firehawk-auth-scripts; ansible-playbook ansible/openvpn.yaml -v --extra-vars "variable_host=localhost openvpn_user=$openvpn_user openvpn_user_pw=$openvpn_user_pw"
else
log "No payload aquired."
fi
else
log "VPN is up"
fi
fi
}
install "$@"