-
Notifications
You must be signed in to change notification settings - Fork 586
/
Copy pathsecret_fetch_script.go
201 lines (176 loc) · 5.08 KB
/
secret_fetch_script.go
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
/*
Copyright 2020 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package ssm
//nolint:gosec
const secretFetchScript = `#cloud-boothook
#!/bin/bash
# Copyright 2020 The Kubernetes Authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
set -o errexit
set -o nounset
set -o pipefail
umask 006
REGION="{{.Region}}"
if [ "{{.Endpoint}}" != "" ]; then
ENDPOINT="--endpoint-url {{.Endpoint}}"
fi
SECRET_PREFIX="{{.SecretPrefix}}"
CHUNKS="{{.Chunks}}"
FILE="/etc/secret-userdata.txt"
FINAL_INDEX=$((CHUNKS - 1))
# Log an error and exit.
# Args:
# $1 Message to log with the error
# $2 The error code to return
log::error_exit() {
local message="${1}"
local code="${2}"
log::error "${message}"
log::error "aws.cluster.x-k8s.io encrypted cloud-init script $0 exiting with status ${code}"
exit "${code}"
}
log::success_exit() {
log::info "aws.cluster.x-k8s.io encrypted cloud-init script $0 finished"
exit 0
}
# Log an error but keep going.
log::error() {
local message="${1}"
timestamp=$(date --iso-8601=seconds)
echo "!!! [${timestamp}] ${1}" >&2
shift
for message; do
echo " ${message}" >&2
done
}
# Print a status line. Formatted to show up in a stream of output.
log::info() {
timestamp=$(date --iso-8601=seconds)
echo "+++ [${timestamp}] ${1}"
shift
for message; do
echo " ${message}"
done
}
check_aws_command() {
local command="${1}"
local code="${2}"
local out="${3}"
local sanitised="${out//[$'\t\r\n']/}"
case ${code} in
"0")
log::info "AWS CLI reported successful execution for ${command}"
;;
"2")
log::error "AWS CLI reported that it could not parse ${command}"
log::error "${sanitised}"
;;
"130")
log::error "AWS CLI reported SIGINT signal during ${command}"
log::error "${sanitised}"
;;
"255")
log::error "AWS CLI reported service error for ${command}"
log::error "${sanitised}"
;;
*)
log::error "AWS CLI reported unknown error ${code} for ${command}"
log::error "${sanitised}"
;;
esac
}
delete_secret_value() {
local id="${SECRET_PREFIX}/${1}"
local out
log::info "deleting secret from AWS SSM Parameter Store"
set +o errexit
set +o nounset
set +o pipefail
out=$(
aws ssm ${ENDPOINT} --region ${REGION} delete-parameter --name "${id}" 2>&1
)
local delete_return=$?
set -o errexit
set -o nounset
set -o pipefail
check_aws_command "SSM::DeleteSecret" "${delete_return}" "${out}"
if [ ${delete_return} -ne 0 ]; then
log::error_exit "Could not delete secret value" 2
fi
}
delete_secrets() {
for i in $(seq 0 ${FINAL_INDEX}); do
delete_secret_value "$i"
done
}
get_secret_value() {
local chunk=$1
local id="${SECRET_PREFIX}/${chunk}"
log::info "getting userdata from AWS SSM Parameter Store"
log::info "getting secret value from AWS SSM Parameter Store"
local data
set +o errexit
set +o nounset
set +o pipefail
data=$(
set +e
set +o pipefail
aws ssm ${ENDPOINT} --region ${REGION} get-parameter --output text --query 'Parameter.Value' --with-decryption --name "${id}" 2>&1
)
local get_return=$?
check_aws_command "SSM::GetSecretValue" "${get_return}" "${data}"
set -o errexit
set -o nounset
set -o pipefail
if [ ${get_return} -ne 0 ]; then
log::error "could not get secret value, deleting secret"
delete_secrets
log::error_exit "could not get secret value, but secret was deleted" 1
fi
log::info "appending data to temporary file ${FILE}.b64.gz"
echo "${data}" >>${FILE}.b64.gz
}
log::info "aws.cluster.x-k8s.io encrypted cloud-init script $0 started"
log::info "secret prefix: ${SECRET_PREFIX}"
log::info "secret count: ${CHUNKS}"
if test -f "${FILE}"; then
log::info "encrypted userdata already written to disk"
log::success_exit
fi
for i in $(seq 0 "${FINAL_INDEX}"); do
get_secret_value "$i"
done
delete_secrets
log::info "decompressing userdata to ${FILE}"
cat "${FILE}.b64.gz" | base64 -d > "${FILE}.gz"
rm -f "${FILE}.b64.gz"
gunzip "${FILE}.gz"
GUNZIP_RETURN=$?
if [ ${GUNZIP_RETURN} -ne 0 ]; then
log::error_exit "could not unzip data" 4
fi
log::info "restarting cloud-init"
systemctl restart cloud-init
log::success_exit
`