Quick Fix: Remove IAM Role
Outcome
The IAM role will be deleted from the AWS account, eliminating a stale or unnecessary principal that could be compromised. Removing unused roles reduces your account's attack surface.
For example, after applying this fix:
- An IAM role
legacy-migration-rolethat hasn't been used in 180 days will no longer exist as an assumable identity - An IAM role
temp-contractor-rolecreated for a completed project will no longer be available for abuse
Fix
Step 1: Set the target role
ROLE_NAME="the-role-to-remove"
ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text)
ROLE_ARN="arn:aws:iam::${ACCOUNT_ID}:role/${ROLE_NAME}"
Step 2: Check for KMS key policy references
Before deleting the role, verify it is not referenced in any customer managed KMS key policies. Deleting a role that is the sole grantee in a KMS key policy can result in losing access to encrypted data.
# List all customer managed KMS keys in the account
KMS_KEY_IDS=$(aws kms list-keys --query 'Keys[*].KeyId' --output text)
# Check each key's policy for references to the role
for KEY_ID in ${KMS_KEY_IDS}; do
KEY_POLICY=$(aws kms get-key-policy --key-id "${KEY_ID}" --policy-name default --output text 2>/dev/null)
if echo "${KEY_POLICY}" | grep -q "${ROLE_NAME}\|${ROLE_ARN}"; then
echo "WARNING: KMS key ${KEY_ID} references ${ROLE_NAME}"
echo "${KEY_POLICY}" | grep -B2 -A2 "${ROLE_NAME}\|${ROLE_ARN}"
echo "---"
fi
done
If any KMS keys reference the role, update those key policies to grant access to an alternative principal before proceeding. Otherwise you risk losing the ability to decrypt data protected by those keys.
Step 3: Remove attached policies and instance profiles
IAM requires that all policies, instance profiles, and inline policies are removed from a role before it can be deleted.
# Detach all managed policies
for POLICY_ARN in $(aws iam list-attached-role-policies \
--role-name "${ROLE_NAME}" \
--query 'AttachedPolicies[*].PolicyArn' --output text); do
echo "Detaching managed policy: ${POLICY_ARN}"
aws iam detach-role-policy \
--role-name "${ROLE_NAME}" \
--policy-arn "${POLICY_ARN}"
done
# Delete all inline policies
for POLICY_NAME in $(aws iam list-role-policies \
--role-name "${ROLE_NAME}" \
--query 'PolicyNames[*]' --output text); do
echo "Deleting inline policy: ${POLICY_NAME}"
aws iam delete-role-policy \
--role-name "${ROLE_NAME}" \
--policy-name "${POLICY_NAME}"
done
# Remove role from all instance profiles
for PROFILE_NAME in $(aws iam list-instance-profiles-for-role \
--role-name "${ROLE_NAME}" \
--query 'InstanceProfiles[*].InstanceProfileName' --output text); do
echo "Removing role from instance profile: ${PROFILE_NAME}"
aws iam remove-role-from-instance-profile \
--role-name "${ROLE_NAME}" \
--instance-profile-name "${PROFILE_NAME}"
done
Step 4: Delete the role
aws iam delete-role --role-name "${ROLE_NAME}"
Verify the fix
Confirm the role no longer exists:
aws iam get-role --role-name "${ROLE_NAME}" 2>&1
This should return a NoSuchEntity error, confirming the role has been deleted.
References
- AWS: Deleting roles or instance profiles
- AWS: Key policies in AWS KMS
- k9 Security Kata 1: Review AWS IAM administrators
Gotcha
Deleting an IAM role that is referenced in a KMS key policy can cause you to lose access to encrypted data. KMS key policies are resource-based policies that grant permissions independently of IAM policies. If the deleted role was the only principal authorized to use a KMS key, no one will be able to decrypt data encrypted with that key (short of contacting AWS Support). Always run the KMS key policy check in Step 2 and update any references before deleting the role.