Skip to content

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-role that hasn't been used in 180 days will no longer exist as an assumable identity
  • An IAM role temp-contractor-role created 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

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.


Last update: February 5, 2026