#!/usr/bin/env bash # # iam-user-delete.sh — fully delete one or more IAM users (account 328440206208). # # IAM refuses to delete a user that still has attached/inline policies, access # keys, group memberships, MFA devices, a login profile, signing certs, SSH keys, # or service-specific credentials. This tears all of that down in order, then # deletes the user. Built from the Day 4 audit cleanup (frappe/termius/ledgerflow, # then office_mac/home_desktop/Personal-laptop). See reference memory # `reference_identity_center_workmail` for the SSO context. # # Usage: # scripts/iam-user-delete.sh [--profile NAME] [--yes] USER [USER ...] # # --profile NAME AWS CLI profile (default: $AWS_PROFILE or the default chain). # Post-SSO-cutover this is normally `seahaven-mgmt`. # --yes Skip the per-user confirmation prompt. # # Safety: # * Refuses to delete the user the current credentials authenticate as. # * Deactivates access keys before deleting them (a brief, reversible window # if you remove --yes and inspect between users). # * Prints each user's attachments before deleting so there is a record. # set -euo pipefail PROFILE_ARG=() ASSUME_YES=0 USERS=() while [[ $# -gt 0 ]]; do case "$1" in --profile) PROFILE_ARG=(--profile "$2"); shift 2 ;; --yes|-y) ASSUME_YES=1; shift ;; -h|--help) sed -n '2,30p' "$0"; exit 0 ;; -*) echo "unknown flag: $1" >&2; exit 2 ;; *) USERS+=("$1"); shift ;; esac done [[ ${#USERS[@]} -eq 0 ]] && { echo "usage: $0 [--profile NAME] [--yes] USER [USER ...]" >&2; exit 2; } aws_() { aws "${PROFILE_ARG[@]}" "$@"; } # Guard: never delete the identity we're running as. SELF_ARN="$(aws_ sts get-caller-identity --query Arn --output text)" echo "running as: $SELF_ARN" delete_user() { local u="$1" if ! aws_ iam get-user --user-name "$u" >/dev/null 2>&1; then echo " $u: does not exist, skipping"; return 0 fi if [[ "$SELF_ARN" == *":user/$u" ]]; then echo " $u: REFUSING — this is the identity you are authenticated as" >&2; return 1 fi echo "== $u ==" echo " keys: $(aws_ iam list-access-keys --user-name "$u" --query 'AccessKeyMetadata[].AccessKeyId' --output text)" echo " attached: $(aws_ iam list-attached-user-policies --user-name "$u" --query 'AttachedPolicies[].PolicyName' --output text)" echo " inline: $(aws_ iam list-user-policies --user-name "$u" --query 'PolicyNames' --output text)" echo " groups: $(aws_ iam list-groups-for-user --user-name "$u" --query 'Groups[].GroupName' --output text)" if [[ $ASSUME_YES -eq 0 ]]; then read -r -p " delete user '$u'? [y/N] " ans [[ "$ans" =~ ^[Yy]$ ]] || { echo " skipped"; return 0; } fi # access keys: deactivate (reversible) then delete for k in $(aws_ iam list-access-keys --user-name "$u" --query 'AccessKeyMetadata[].AccessKeyId' --output text); do aws_ iam update-access-key --user-name "$u" --access-key-id "$k" --status Inactive aws_ iam delete-access-key --user-name "$u" --access-key-id "$k" done # detach managed policies for p in $(aws_ iam list-attached-user-policies --user-name "$u" --query 'AttachedPolicies[].PolicyArn' --output text); do aws_ iam detach-user-policy --user-name "$u" --policy-arn "$p" done # delete inline policies for ip in $(aws_ iam list-user-policies --user-name "$u" --query 'PolicyNames[]' --output text); do aws_ iam delete-user-policy --user-name "$u" --policy-name "$ip" done # remove from groups for g in $(aws_ iam list-groups-for-user --user-name "$u" --query 'Groups[].GroupName' --output text); do aws_ iam remove-user-from-group --user-name "$u" --group-name "$g" done # MFA devices for m in $(aws_ iam list-mfa-devices --user-name "$u" --query 'MFADevices[].SerialNumber' --output text); do aws_ iam deactivate-mfa-device --user-name "$u" --serial-number "$m" done # login profile (console password) aws_ iam delete-login-profile --user-name "$u" 2>/dev/null || true # signing certs for c in $(aws_ iam list-signing-certificates --user-name "$u" --query 'Certificates[].CertificateId' --output text 2>/dev/null); do aws_ iam delete-signing-certificate --user-name "$u" --certificate-id "$c" done # SSH public keys (CodeCommit) for s in $(aws_ iam list-ssh-public-keys --user-name "$u" --query 'SSHPublicKeys[].SSHPublicKeyId' --output text 2>/dev/null); do aws_ iam delete-ssh-public-key --user-name "$u" --ssh-public-key-id "$s" done # service-specific credentials for sc in $(aws_ iam list-service-specific-credentials --user-name "$u" --query 'ServiceSpecificCredentials[].ServiceSpecificCredentialId' --output text 2>/dev/null); do aws_ iam delete-service-specific-credential --user-name "$u" --service-specific-credential-id "$sc" done aws_ iam delete-user --user-name "$u" echo " $u: deleted" } rc=0 for u in "${USERS[@]}"; do delete_user "$u" || rc=1; done exit $rc