Skip to content

Commit 42e2ebe

Browse files
committed
update deploy cfn action
1 parent 228f2f3 commit 42e2ebe

1 file changed

Lines changed: 29 additions & 11 deletions

File tree

.github/actions/deploy-cfn/action.yml

Lines changed: 29 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -66,12 +66,20 @@ runs:
6666
run: |
6767
# Build a 20-char password that satisfies all known MATLAB / NLM regexes:
6868
# >=14 chars, includes upper, lower, digit, and special character.
69-
UPPER=$(LC_ALL=C tr -dc 'A-Z' < /dev/urandom | head -c1)
70-
LOWER=$(LC_ALL=C tr -dc 'a-z' < /dev/urandom | head -c1)
71-
DIGIT=$(LC_ALL=C tr -dc '0-9' < /dev/urandom | head -c1)
72-
SPECIAL=$(LC_ALL=C tr -dc '!@#%^_+=-' < /dev/urandom | head -c1)
73-
REST=$(LC_ALL=C tr -dc 'A-Za-z0-9' < /dev/urandom | head -c16)
69+
# Read a bounded block from /dev/urandom before filtering: piping an
70+
# unbounded stream straight into `head -c` makes `tr` die on SIGPIPE
71+
# when head closes the pipe, which aborts the step under pipefail.
72+
gen() { LC_ALL=C head -c 8192 /dev/urandom | LC_ALL=C tr -dc "$1" | head -c "$2"; }
73+
UPPER=$(gen 'A-Z' 1)
74+
LOWER=$(gen 'a-z' 1)
75+
DIGIT=$(gen '0-9' 1)
76+
SPECIAL=$(gen '!@#%^_+=-' 1)
77+
REST=$(gen 'A-Za-z0-9' 16)
7478
PASSWORD="${UPPER}${LOWER}${DIGIT}${SPECIAL}${REST}"
79+
if [ "${#PASSWORD}" -lt 14 ]; then
80+
echo "::error::Generated password too short (${#PASSWORD} chars); entropy source may be unavailable"
81+
exit 1
82+
fi
7583
echo "::add-mask::$PASSWORD"
7684
echo "password=$PASSWORD" >> "$GITHUB_OUTPUT"
7785
@@ -86,6 +94,7 @@ runs:
8694
CLIENT_IP: "${{ steps.get-ip.outputs.ipv4 }}/32"
8795
STACK_PASSWORD: ${{ steps.gen-password.outputs.password }}
8896
CONFIG_FILE: "${{ github.action_path }}/refarch-type-mappings.json"
97+
TEMPLATE_FILE: ${{ inputs.compiled_template_file_path }}
8998
run: |
9099
KEY_PARAM=$(jq -r ".\"$REFARCH_TYPE\".key_param" $CONFIG_FILE)
91100
VPC_PARAM=$(jq -r ".\"$REFARCH_TYPE\".vpc_param" $CONFIG_FILE)
@@ -99,12 +108,21 @@ runs:
99108
jq --arg k "$KEY_PARAM" --arg v "$KEY" '. += [{"ParameterKey": $k, "ParameterValue": $v}]' params.json > tmp.json && mv tmp.json params.json
100109
jq --arg k "$CLIENT_IP_PARAM" --arg v "$CLIENT_IP" '. += [{"ParameterKey": $k, "ParameterValue": $v}]' params.json > tmp.json && mv tmp.json params.json
101110
102-
# Inject a random password for any template that asks for one. We
103-
# set Password / ConfirmPassword (and never log them) so deployments
104-
# do not rely on a hardcoded credential.
105-
jq --arg pw "$STACK_PASSWORD" '
106-
(.[] | select(.ParameterKey == "Password") | .ParameterValue) |= $pw
107-
| (.[] | select(.ParameterKey == "ConfirmPassword") | .ParameterValue) |= $pw
111+
# Inject a random password for any template that asks for one. Only
112+
# Password / ConfirmPassword parameters that the compiled template
113+
# actually declares are set (added if absent, updated if present), so
114+
# we never pass an unknown parameter to CloudFormation. The values are
115+
# masked and never logged, so deployments do not rely on a hardcoded
116+
# credential.
117+
jq --arg pw "$STACK_PASSWORD" --slurpfile tmpl "$TEMPLATE_FILE" '
118+
($tmpl[0].Parameters // {}) as $tp
119+
| reduce ["Password", "ConfirmPassword"][] as $name (.;
120+
if ($tp | has($name)) then
121+
if any(.[]; .ParameterKey == $name)
122+
then map(if .ParameterKey == $name then .ParameterValue = $pw else . end)
123+
else . + [{"ParameterKey": $name, "ParameterValue": $pw}]
124+
end
125+
else . end)
108126
' params.json > tmp.json && mv tmp.json params.json
109127
110128
echo "Generated Parameters (passwords redacted by runner masking):"

0 commit comments

Comments
 (0)