Skip to content

Commit 6ac9c9e

Browse files
committed
aws/action/openshift-snc/cloud-config: use the snc helper script to fetch the secrets
1 parent 69e950d commit 6ac9c9e

File tree

2 files changed

+279
-11
lines changed

2 files changed

+279
-11
lines changed
Lines changed: 153 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,17 @@
11
#cloud-config
22
bootcmd:
3+
- 'echo "bootcmd executed by service: $(ps -o comm= $PPID)" > /tmp/bootcmd_proof.txt'
34
# Resize the partition (4 = /dev/nvme0n1p4 typically)
45
- growpart /dev/nvme0n1 4
56
runcmd:
7+
- 'echo "runcmd executed by service: $(ps -o comm= $PPID)" > /tmp/runcmd_proof.txt'
68
- systemctl enable --now kubelet
7-
- export PS=$(podman run --rm docker.io/amazon/aws-cli ssm get-parameter --name "{{ .SSMPullSecretName }}" --with-decryption --query "Parameter.Value" --output text)
8-
- echo ${PS} > /opt/crc/pull-secret
9-
- chmod 0644 /opt/crc/pull-secret
10-
- export KP=$(podman run --rm docker.io/amazon/aws-cli ssm get-parameter --name "{{ .SSMKubeAdminPasswordName }}" --with-decryption --query "Parameter.Value" --output text)
11-
- echo ${KP} > /opt/crc/pass_kubeadmin
12-
- chmod 0644 /opt/crc/pass_kubeadmin
13-
- export DV=$(podman run --rm docker.io/amazon/aws-cli ssm get-parameter --name "{{ .SSMDeveloperPasswordName }}" --with-decryption --query "Parameter.Value" --output text)
14-
- echo ${DV} > /opt/crc/pass_developer
15-
- chmod 0644 /opt/crc/pass_developer
16-
- echo "{{ .PublicIP }}" > /opt/crc/eip
17-
- chmod 0644 /opt/crc/eip
9+
- /usr/local/bin/mapt-crc-aws-fetch-secrets-workaround.sh
1810
write_files:
11+
- path: /opt/crc/eip
12+
content: "{{ .PublicIP }}"
13+
owner: root:root
14+
permissions: '0644'
1915
- path: /home/core/.ssh/authorized_keys
2016
content: {{ .PubKey }}
2117
owner: {{ .Username }}
@@ -27,6 +23,152 @@ write_files:
2723
- content: |
2824
CRC_SELF_SUFFICIENT=1
2925
CRC_NETWORK_MODE_USER=0
26+
CRC_SOURCE=mapt/snc
3027
owner: root:root
3128
path: /etc/sysconfig/crc-env
3229
permissions: '0644'
30+
- owner: root:root
31+
path: /usr/local/bin/mapt-crc-aws-fetch-secrets-workaround.sh
32+
permissions: '0755'
33+
content: |
34+
#!/bin/bash
35+
if [[ -f /usr/local/bin/crc-aws-fetch-secrets.sh ]]; then
36+
script=/usr/local/bin/crc-aws-fetch-secrets.sh
37+
else
38+
echo "crc-aws-fetch-secrets.sh not found, falling back to MAPT's copy"
39+
script=/usr/local/bin/mapt-crc-aws-fetch-secrets.sh
40+
fi
41+
42+
exec "$script" "{{ .SSMPullSecretName }}" "{{ .SSMKubeAdminPasswordName }}" "{{ .SSMDeveloperPasswordName }}"
43+
- owner: root:root
44+
path: /usr/local/bin/mapt-crc-aws-fetch-secrets.sh
45+
permissions: '0755'
46+
content: |
47+
#!/bin/bash
48+
49+
set -o pipefail
50+
set -o errexit
51+
set -o nounset
52+
set -o errtrace
53+
set -x
54+
55+
# set -x is safe, the secrets are passed via stdin
56+
57+
AWS_CLI_IMG=docker.io/amazon/aws-cli
58+
MIN_CHAR_COUNT=8 # minimum number of chars for the secret to be
59+
# assumed valid
60+
61+
umask 0077 # 0600 file permission for secrets
62+
install -d -m 0700 /opt/crc # ensure that the target directory exists
63+
64+
PULL_SECRETS_KEY=${1:-}
65+
KUBEADM_PASS_KEY=${2:-}
66+
DEVELOPER_PASS_KEY=${3:-}
67+
68+
if [[ -z "$PULL_SECRETS_KEY" || -z "$KUBEADM_PASS_KEY" || -z "$DEVELOPER_PASS_KEY" ]]; then
69+
echo "ERROR: expected to receive 3 parameters: PULL_SECRETS_KEY KUBEADM_PASS_KEY DEVELOPER_PASS_KEY"
70+
exit 1
71+
fi
72+
73+
DELAY=5
74+
TOTAL_PERIOD=$(( 3*60 ))
75+
ATTEMPTS=$(( TOTAL_PERIOD / DELAY))
76+
function retry_compact() {
77+
for i in $(seq 1 $ATTEMPTS); do
78+
# If the command succeeds (returns 0), exit the function with success.
79+
if "$@"; then
80+
echo "'$*' succeeded after $i attempts "
81+
return 0
82+
fi
83+
echo "'$*' still failing after $i/$ATTEMPTS attempts ..."
84+
sleep "$DELAY"
85+
done
86+
echo "'$*' didn't succeed after $i attempt ..."
87+
# If the loop finishes, the command never succeeded.
88+
return 1
89+
}
90+
91+
cleanup() {
92+
rm -f /tmp/aws-region /opt/crc/pull-secret.tmp /opt/crc/pass_kubeadmin.tmp /opt/crc/pass_developer.tmp
93+
echo "Temp files cleanup complete."
94+
}
95+
96+
# Cleanup happens automatically via trap on error or at script end
97+
trap cleanup ERR EXIT
98+
99+
SECONDS=0
100+
podman pull --quiet "$AWS_CLI_IMG"
101+
echo "Took $SECONDS seconds to pull the $AWS_CLI_IMG"
102+
103+
check_imds_available_and_get_region() {
104+
IMDS_TOKEN_COMMAND=(
105+
curl
106+
--connect-timeout 1
107+
-X PUT
108+
"http://169.254.169.254/latest/api/token"
109+
-H "X-aws-ec2-metadata-token-ttl-seconds: 21600"
110+
-Ssf
111+
)
112+
113+
if ! TOKEN=$("${IMDS_TOKEN_COMMAND[@]}"); then
114+
echo "Couldn't fetch the token..." >&2
115+
return 1
116+
fi
117+
118+
# Then, use the token to get the region
119+
echo "Fetching the AWS region ..."
120+
curl -Ssf -H "X-aws-ec2-metadata-token: $TOKEN" http://169.254.169.254/latest/meta-data/placement/region > /tmp/aws-region
121+
echo >> /tmp/aws-region # add EOL at EOF, for consistency
122+
echo "AWS region: $(< /tmp/aws-region)"
123+
}
124+
125+
(
126+
set +x # disable the xtrace as the token would be leaked
127+
echo "Waiting for the AWS IMDS service to be available ..."
128+
SECONDS=0
129+
retry_compact check_imds_available_and_get_region
130+
echo "Took $SECONDS for the IMDS service to become available."
131+
)
132+
133+
save_secret() {
134+
name=$1
135+
key=$2
136+
dest=$3
137+
138+
# --log-driver=none avoids that the journal captures the stdout
139+
# logs of podman and leaks the passwords in the journal ...
140+
if ! podman run \
141+
--name "cloud-init-fetch-$name" \
142+
--env AWS_REGION="$(< /tmp/aws-region)" \
143+
--log-driver=none \
144+
--rm \
145+
"$AWS_CLI_IMG" \
146+
ssm get-parameter \
147+
--name "$key" \
148+
--with-decryption \
149+
--query "Parameter.Value" \
150+
--output text \
151+
> "${dest}.tmp"
152+
then
153+
rm -f "${dest}.tmp"
154+
echo "ERROR: failed to get the '$name' secret ... (fetched from $key)"
155+
return 1
156+
fi
157+
char_count=$(wc -c < "${dest}.tmp")
158+
if (( char_count < MIN_CHAR_COUNT )); then
159+
echo "ERROR: the content of the '$name' secret is too short ... (fetched from $key)"
160+
rm -f "${dest}.tmp"
161+
return 1
162+
fi
163+
164+
mv "${dest}.tmp" "${dest}" # atomic creation of the file
165+
166+
return 0
167+
}
168+
169+
# execution will abort if 'retry_compact' fails.
170+
retry_compact save_secret "pull-secrets" "$PULL_SECRETS_KEY" /opt/crc/pull-secret
171+
retry_compact save_secret "kubeadmin-pass" "$KUBEADM_PASS_KEY" /opt/crc/pass_kubeadmin
172+
retry_compact save_secret "developer-pass" "$DEVELOPER_PASS_KEY" /opt/crc/pass_developer
173+
174+
exit 0
Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
#!/bin/bash
2+
3+
set -o pipefail
4+
set -o errexit
5+
set -o nounset
6+
set -o errtrace
7+
set -x
8+
9+
# set -x is safe, the secrets are passed via stdin
10+
11+
AWS_CLI_IMG=docker.io/amazon/aws-cli
12+
MIN_CHAR_COUNT=8 # minimum number of chars for the secret to be
13+
# assumed valid
14+
15+
umask 0077 # 0600 file permission for secrets
16+
17+
PULL_SECRETS_KEY=${1:-}
18+
KUBEADM_PASS_KEY=${2:-}
19+
DEVELOPER_PASS_KEY=${3:-}
20+
21+
if [[ -z "$PULL_SECRETS_KEY" || -z "$KUBEADM_PASS_KEY" || -z "$DEVELOPER_PASS_KEY" ]]; then
22+
echo "ERROR: expected to receive 3 parameters: PULL_SECRETS_KEY KUBEADM_PASS_KEY DEVELOPER_PASS_KEY"
23+
exit 1
24+
fi
25+
26+
SECONDS=0
27+
podman pull --quiet "$AWS_CLI_IMG"
28+
echo "Took $SECONDS seconds to pull the $AWS_CLI_IMG"
29+
30+
wait_imds_available_and_get_region() {
31+
total_timeout_minutes=5
32+
retry_interval_seconds=5
33+
34+
IMDS_TOKEN_COMMAND=(
35+
curl
36+
--connect-timeout 1
37+
-X PUT
38+
"http://169.254.169.254/latest/api/token"
39+
-H "X-aws-ec2-metadata-token-ttl-seconds: 21600"
40+
-Ssf
41+
)
42+
success=false
43+
deadline=$(( $(date +%s) + (total_timeout_minutes * 60) ))
44+
while [[ $(date +%s) -lt $deadline ]]; do
45+
# By placing the command in an 'if' condition, we can test its exit code
46+
# without triggering 'set -e'. The output is still captured.
47+
if TOKEN=$("${IMDS_TOKEN_COMMAND[@]}"); then
48+
# This block only runs if the curl command succeeds (exit code 0)
49+
success=true
50+
echo "Successfully fetched token." >&2
51+
break # Exit the loop on success
52+
fi
53+
54+
# This block runs if the curl command fails
55+
echo "Failed to connect. Retrying in $retry_interval_seconds seconds..." >&2
56+
sleep "$retry_interval_seconds"
57+
done
58+
59+
if [[ "$success" != "true" ]]; then
60+
echo "ERROR: Could not fetch token after $total_timeout_minutes minutes." >&2
61+
return 1
62+
fi
63+
64+
# Then, use the token to get the region
65+
echo "Fetching the AWS region ..."
66+
curl -Ssf -H "X-aws-ec2-metadata-token: $TOKEN" http://169.254.169.254/latest/meta-data/placement/region > /tmp/aws-region
67+
echo >> /tmp/aws-region # add EOL at EOF, for consistency
68+
echo "AWS region: $(< /tmp/aws-region)"
69+
}
70+
71+
(
72+
set +x # disable the xtrace as the token would be leaked
73+
echo "Waiting for the AWS IMDS service to be available ..."
74+
SECONDS=0
75+
wait_imds_available_and_get_region
76+
echo "Took $SECONDS for the IMDS service to become available."
77+
)
78+
79+
missing_secrets=0
80+
81+
save_secret() {
82+
name=$1
83+
key=$2
84+
dest=$3
85+
86+
# --log-driver=none avoids that the journal captures the stdout
87+
# logs of podman and leaks the passwords in the journal ...
88+
if ! podman run \
89+
--name "cloud-init-fetch-$name" \
90+
--env AWS_REGION="$(< /tmp/aws-region)" \
91+
--log-driver=none \
92+
--rm \
93+
"$AWS_CLI_IMG" \
94+
ssm get-parameter \
95+
--name "$key" \
96+
--with-decryption \
97+
--query "Parameter.Value" \
98+
--output text \
99+
> "${dest}.tmp"
100+
then
101+
rm -f "${dest}.tmp"
102+
echo "ERROR: failed to get the '$name' secret ... (fetched from $key)"
103+
((missing_secrets += 1))
104+
return
105+
fi
106+
char_count=$(wc -c < "${dest}.tmp")
107+
if (( char_count < MIN_CHAR_COUNT )); then
108+
echo "ERROR: the content of the '$name' secret is too short ... (fetched from $key)"
109+
rm -f "${dest}.tmp"
110+
((missing_secrets += 1))
111+
return
112+
fi
113+
114+
mv "${dest}.tmp" "${dest}" # atomic creation of the file
115+
}
116+
117+
save_secret "pull-secrets" "$PULL_SECRETS_KEY" /opt/crc/pull-secret
118+
save_secret "kubeadmin-pass" "$KUBEADM_PASS_KEY" /opt/crc/pass_kubeadmin
119+
save_secret "developer-pass" "$DEVELOPER_PASS_KEY" /opt/crc/pass_developer
120+
121+
if (( missing_secrets != 0 )); then
122+
echo "ERROR: failed to fetch $missing_secrets secrets ..."
123+
exit 1
124+
fi
125+
126+
exit 0

0 commit comments

Comments
 (0)