Hidden Danger of AWS Managed IAM Policies: PowerUserAccess and Identity Center

StackAdvisor.AI / AI Tool

Using AWS-managed IAM policies are convenient — they're maintained by AWS, follow best practices, and save time. But convenience can breed complacency. If you look closely you can uncovered a critical security flaw: the widely-used PowerUserAccess policy grants full access to IAM Identity Center, including the ability to delete users and permission sets.

Even more concerning: users can delete themselves from Identity Center and remain logged in, masking the security breach. This post explores the issue, its implications, and how to properly secure your AWS environment.

What Happened:

  1. Created a "Power User" with AWS-managed PowerUserAccess policy
  2. Expected behavior: Full access except IAM (as documented)
  3. Tested access to IAM Identity Center console and full access granted ⚠️
  4. Deleted own user account from Identity Center
  5. Remained logged in with active session (temporary credentials)
  6. Could still delete other users and permission sets

Security Implications:

  • Privilege Escalation: "Power Users" can grant themselves admin access
  • Account Takeover Risk: Delete legitimate users, create malicious ones
  • Audit Trail Corruption: Deleted users obscure CloudTrail evidence
  • Session Persistence: Temporary credentials remain valid after user deletion
  • Hidden Attack Surface: Most teams assume PowerUserAccess is safe

Understanding PowerUserAccess

As per, AWS Documentation: Provides full access to AWS services and resources, but does not allow management of Users and groups.

What PowerUserAccess Actually Grants:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "NotAction": [
        "iam:*",
        "organizations:*",
        "account:*"
      ],
      "Resource": "*"
    },
    {
      "Effect": "Allow",
      "Action": [
        "iam:CreateServiceLinkedRole",
        "iam:DeleteServiceLinkedRole",
        "iam:ListRoles",
        "organizations:DescribeOrganization",
        "account:ListRegions"
      ],
      "Resource": "*"
    }
  ]
}

# The problem: NotAction excludes "iam:*" but NOT:
# - sso:*              (IAM Identity Center management)
# - sso-directory:*    (Identity Center directory)
# - identitystore:*    (User/group management)

# These are separate service namespaces, so they slip through!

The IAM Identity Center Loophole

PDF File converted to Plain Text

Actions PowerUserAccess Can Perform:

ActionImpactSeverity
identitystore:DeleteUserRemove users from organizationCRITICAL
sso:CreatePermissionSetCreate custom admin permission setsCRITICAL
sso:AttachManagedPolicyToPermissionSetAssign AdministratorAccess to own accountCRITICAL
identitystore:CreateUserCreate backdoor accountsHIGH
sso-directory:DisableUserLock out legitimate administratorsHIGH

Reproducing the Issue (Safely)

Warning: Only test this in a non-production environment. Never test on production accounts or with real user data.

# Step 1: Create test user with PowerUserAccess
aws iam create-user --user-name test-power-user

aws iam attach-user-policy \
  --user-name test-power-user \
  --policy-arn arn:aws:iam::aws:policy/PowerUserAccess

# Step 2: Create access keys
aws iam create-access-key --user-name test-power-user

# Step 3: Configure AWS CLI with test user credentials
export AWS_ACCESS_KEY_ID=AKIA...
export AWS_SECRET_ACCESS_KEY=...

# Step 4: List Identity Center users (should work)
aws identitystore list-users \
  --identity-store-id d-1234567890

# Output: Returns list of all users ⚠️

# Step 5: Attempt to delete a user (DO NOT RUN ON PRODUCTION)
aws identitystore delete-user \
  --identity-store-id d-1234567890 \
  --user-id 12345678-1234-1234-1234-123456789012

# Result: User deleted successfully ⚠️

# Step 6: Check CloudTrail
aws cloudtrail lookup-events \
  --lookup-attributes AttributeKey=EventName,AttributeValue=DeleteUser

# Shows the deletion event with test-power-user as the actor

The Fix: Custom Power User Policy

Option 1: Explicit Deny for Identity Center

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "PowerUserBaseAccess",
      "Effect": "Allow",
      "NotAction": [
        "iam:*",
        "organizations:*",
        "account:*"
      ],
      "Resource": "*"
    },
    {
      "Sid": "AllowLimitedIAMActions",
      "Effect": "Allow",
      "Action": [
        "iam:CreateServiceLinkedRole",
        "iam:DeleteServiceLinkedRole",
        "iam:ListRoles",
        "organizations:DescribeOrganization",
        "account:ListRegions"
      ],
      "Resource": "*"
    },
    {
      "Sid": "DenySSOAndIdentityAdminAPIs",
      "Effect": "Deny",
      "Action": [
        "sso:*",
        "sso-admin:*",
        "sso-directory:*",
        "identitystore:*"
      ],
      "Resource": "*"
    },
    {
      "Sid": "DenyIamPassRoleAndRiskyIam",
      "Effect": "Deny",
      "Action": [
        "iam:PassRole",
        "iam:PutRolePolicy",
        "iam:AttachRolePolicy",
        "iam:CreatePolicy",
        "iam:CreatePolicyVersion"
      ],
      "Resource": "*"
    }
  ]
}

# Save as custom policy: "SecurePowerUserAccess"

Option 2: Permission Boundaries

# Create permission boundary policy
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "AllowMostServices",
      "Effect": "Allow",
      "NotAction": [
        "iam:*",
        "organizations:*",
        "account:*",
        "sso:*",
        "sso-directory:*",
        "identitystore:*"
      ],
      "Resource": "*"
    }
  ]
}

# Apply to user
aws iam put-user-permissions-boundary \
  --user-name power-user \
  --permissions-boundary arn:aws:iam::123456789012:policy/PowerUserBoundary

# Permission boundary acts as maximum permission ceiling
# Even if user has PowerUserAccess, boundary restricts SSO actions

Detecting Misuse with CloudTrail

# Query 1: Find all Identity Center modifications
aws cloudtrail lookup-events \
  --lookup-attributes \
    AttributeKey=ResourceType,AttributeValue=AWS::SSO::User \
  --max-results 100

# Query 2: Find user deletions
aws cloudtrail lookup-events \
  --lookup-attributes \
    AttributeKey=EventName,AttributeValue=DeleteUser \
  --start-time 2024-01-01T00:00:00Z

# Query 3: Find permission set changes
aws cloudtrail lookup-events \
  --lookup-attributes \
    AttributeKey=EventName,AttributeValue=CreatePermissionSet

# Set up CloudWatch Alarm for suspicious events
aws cloudwatch put-metric-alarm \
  --alarm-name identity-center-user-deletion \
  --alarm-description "Alert on Identity Center user deletions" \
  --metric-name IdentityCenterUserDeletion \
  --namespace AWS/IAM \
  --statistic Sum \
  --period 300 \
  --threshold 1 \
  --comparison-operator GreaterThanThreshold

Audit Your Environment

#!/bin/bash
# Script to audit PowerUserAccess usage

echo "Scanning for users with PowerUserAccess..."

# Find all users with PowerUserAccess
aws iam list-users --output json | jq -r '.Users[].UserName' | while read user; do
  policies=$(aws iam list-attached-user-policies --user-name "$user" --output json)
  
  if echo "$policies" | jq -e '.AttachedPolicies[] | select(.PolicyArn == "arn:aws:iam::aws:policy/PowerUserAccess")' > /dev/null; then
    echo "⚠️  User: $user has PowerUserAccess"
    
    # Check if permission boundary is set
    boundary=$(aws iam get-user --user-name "$user" --query 'User.PermissionsBoundary' --output text)
    
    if [ "$boundary" == "None" ]; then
      echo "   🚨 CRITICAL: No permission boundary set!"
    else
      echo "   ✓ Permission boundary: $boundary"
    fi
  fi
done

echo ""
echo "Scanning for roles with PowerUserAccess..."

aws iam list-roles --output json | jq -r '.Roles[].RoleName' | while read role; do
  policies=$(aws iam list-attached-role-policies --role-name "$role" --output json)
  
  if echo "$policies" | jq -e '.AttachedPolicies[] | select(.PolicyArn == "arn:aws:iam::aws:policy/PowerUserAccess")' > /dev/null; then
    echo "⚠️  Role: $role has PowerUserAccess"
  fi
done

# Run: bash audit-poweruser.sh

Security Best Practices

Do's

  • Audit all managed policies—don't blindly trust AWS
  • Use IAM Access Analyzer—detect overly permissive policies
  • Implement permission boundaries—defense in depth
  • Enable CloudTrail logging—all regions, all accounts
  • Set up CloudWatch alarms—detect suspicious API calls
  • Review policies quarterly—AWS updates managed policies
  • Apply least privilege—grant only necessary permissions

Dont's

  • Don't trust managed policies blindly—always review
  • Don't skip permission boundaries—they're your safety net
  • Don't ignore CloudTrail alerts—investigate immediately
  • Don't use PowerUserAccess for production—create custom policies
  • Don't grant broad access to contractors—time-bound, scoped permissions
  • Don't assume AWS policies are secure—they prioritize functionality

Immediate Remediation Checklist

Audit Current State:

  • Run audit script to find PowerUserAccess usage
  • Review CloudTrail for recent Identity Center API calls
  • Identify users with PowerUserAccess + no permission boundary

Immediate Mitigation:

  • Apply permission boundaries to all PowerUserAccess users
  • Create custom "SecurePowerUserAccess" policy
  • Migrate users to custom policy

Set Up Monitoring:

  • CloudWatch alarm for identitystore:DeleteUser
  • CloudWatch alarm for sso:CreatePermissionSet
  • Weekly IAM Access Analyzer scans

Documentation and Internal practices:

  • Document custom policy rationale
  • Update security runbooks
  • Train team on least privilege principles

Conclusion

This process serves as a critical reminder: never blindly trust managed policies, even from AWS. The PowerUserAccess policy is designed for convenience, prioritizing functionality over strict security boundaries. While AWS's intention is to provide broad access for development teams, the unintended consequence is a significant privilege escalation risk through Identity Center.

The principle of least privilege isn't just a guideline—it's a security requirement. Every permission should be explicitly granted, reviewed regularly, and constrained by permission boundaries. AWS-managed policies are a starting point, not a security guarantee.

Security is a journey, not a destination. This discovery highlights why continuous monitoring, regular audits, and healthy skepticism are essential—even when dealing with AWS's own managed policies.

More articles

The Arrows, Not the Boxes: Systems Thinking for AWS Architects

You can configure an ALB flawlessly and explain IAM policies from memory. But can you articulate why an ALB is better than an NLB for your specific constraints? The different between "knowing AWS services" and "thinking in systems" is what separates engineers who implement from architects who design.

Read more

AWS CodeCommit Returns: What the Reversal Means for You

In an unprecedented reversal, AWS has restored CodeCommit to general availability after deprecating it in July 2024. This decision validates teams that remained committed to AWS-native git repositories while leaving migrated teams questioning their investment.

Read more

Tell us about your project

Our office

  • 425, Avadh Kontina
    Vip Road, Canal Road Corner, near CB patel club
    Surat, Gujarat 395007
    Google Map