fix(scp): deny platform-path changes in bootstrap simulate (PLAT-233)

Add a simulate case for role/platform/hcptf-example and fail when CreateRole,
PutRolePolicy, or DeleteRole is allowed. The unpathed hcptf-* import check stays.

Co-authored-by: Adam Moussa <amoussa1229@users.noreply.github.com>
This commit is contained in:
Cursor Agent 2026-09-28 15:29:05 +00:00
parent f35512edaa
commit 3478c9d539
No known key found for this signature in database

View file

@ -18,6 +18,9 @@
# --simulate runs iam:SimulatePrincipalPolicy against the apply role. Requires
# the role to already exist. The policy source is the live Role.Arn from
# iam:GetRole, so an existing unpathed role and a /platform/ create both match.
# The platform-path case must come back denied. role/hcptf-* does not cover
# role/platform/*, and ProtectPlatformPath denies that resource for every
# principal except OrganizationAccountAccessRole and the Platform SSO role.
#
# Default trust is exact StringEquals for workspace iam-bootstrap-<env> only.
# HCP workspace names are org-unique, so prod and dev cannot both be
@ -45,7 +48,7 @@ while [[ $# -gt 0 ]]; do
--dry-run) DRY_RUN=1; shift ;;
--simulate) SIMULATE=1; shift ;;
--allow-workspace) ALLOW_WORKSPACE="$2"; shift 2 ;;
-h|--help) sed -n '2,36p' "$0"; exit 0 ;;
-h|--help) sed -n '2,35p' "$0"; exit 0 ;;
-*) echo "unknown flag: $1" >&2; exit 2 ;;
*) echo "unexpected argument: $1" >&2; exit 2 ;;
esac
@ -205,7 +208,7 @@ if [[ "$SIMULATE" -eq 1 ]]; then
--resource-arns "arn:aws:iam::${ACCOUNT_ID}:policy/tf-managed/example" \
--query 'EvaluationResults[].{Action:EvalActionName,Decision:EvalDecision}' \
--output table
echo "-- PutRolePolicy on hcptf-* (expect allowed; import/first-apply path) --"
echo "-- PutRolePolicy on unpathed role/hcptf-example (expect allowed; import/first-apply path) --"
aws iam simulate-principal-policy \
--policy-source-arn "$APPLY_ARN" \
--action-names iam:PutRolePolicy iam:DetachRolePolicy \
@ -221,6 +224,24 @@ if [[ "$SIMULATE" -eq 1 ]]; then
"arn:aws:iam::${ACCOUNT_ID}:role/OrganizationAccountAccessRole" \
--query 'EvaluationResults[].{Action:EvalActionName,Resource:EvalResourceName,Decision:EvalDecision}' \
--output table
echo "-- IAM changes on role/platform/hcptf-example (expect denied) --"
platform_sim="$(aws iam simulate-principal-policy \
--policy-source-arn "$APPLY_ARN" \
--action-names iam:CreateRole iam:PutRolePolicy iam:DeleteRole \
--resource-arns "arn:aws:iam::${ACCOUNT_ID}:role/platform/hcptf-example" \
--query 'EvaluationResults[].{Action:EvalActionName,Decision:EvalDecision}' \
--output table)"
printf '%s\n' "$platform_sim"
if grep -q 'allowed' <<<"$platform_sim"; then
echo "role/platform/* simulation allowed an IAM change" >&2
exit 1
fi
for action in iam:CreateRole iam:PutRolePolicy iam:DeleteRole; do
grep -q "$action" <<<"$platform_sim" || {
echo "role/platform/* simulation missing ${action}" >&2
exit 1
}
done
exit 0
fi