FRR-RSC-03: Privileged Accounts
Applies to: Low, Moderate, High
Last Updated: 2025-11-25
Version: 1.0.0
Last Updated: 2025-11-25
Version: 1.0.0
Overview
Guidance for securing IAM users and roles with administrative or privileged access.
Privileged Account Management
Identify Privileged Users
Description:
Find IAM users with administrative access
How It Works:
Query IAM for users with AdministratorAccess or other privileged policies attached.
Configuration Items:
- admin_policies: ['AdministratorAccess - Full AWS access', 'PowerUserAccess - All except IAM/Organizations', 'SecurityAudit - Read-only security access', 'Custom admin policies']
- validation_checks: ['List users with admin policies attached', 'Check MFA status for each privileged user', 'Verify access key age < 90 days', 'Review last activity date']
Example Cli:
# List users with AdministratorAccess policy aws iam list-entities-for-policy --policy-arn arn:aws:iam::aws:policy/AdministratorAccess # Check user MFA status aws iam get-credential-report --query 'Content' --output text | base64 -d
Example Boto3:
import boto3
import csv, base64, time
iam = boto3.client('iam')
# Get users with admin policy
admin_policy = 'arn:aws:iam::aws:policy/AdministratorAccess'
entities = iam.list_entities_for_policy(PolicyArn=admin_policy)
print("Users with AdministratorAccess:")
for user in entities['PolicyUsers']:
print(f" - {user['UserName']}")
# Check MFA status
iam.generate_credential_report()
time.sleep(5)
report = base64.b64decode(iam.get_credential_report()['Content']).decode()
print("\nPrivileged Users MFA Status:")
for row in csv.DictReader(report.splitlines()):
if row['user'] in [u['UserName'] for u in entities['PolicyUsers']]:
mfa = 'true' in row['mfa_active']
print(f" {row['user']}: {'✓ MFA' if mfa else '✗ NO MFA'}")
Access Key Rotation
Description:
Ensure access keys are rotated every 90 days
How It Works:
Check creation date of all access keys. Keys older than 90 days should be rotated.
Configuration Items:
- rotation_process: ['Create new access key', 'Update applications with new key', 'Test new key functionality', 'Deactivate old key', 'Monitor for errors', 'Delete old key after validation']
Example Cli:
# List all access keys with age aws iam list-users --query 'Users[].UserName' --output text | \ while read user; do aws iam list-access-keys --user-name $user done
Example Boto3:
import boto3
from datetime import datetime, timedelta
iam = boto3.client('iam')
threshold = datetime.now() - timedelta(days=90)
users = iam.list_users()
print("Access Keys Older Than 90 Days:")
for user in users['Users']:
keys = iam.list_access_keys(UserName=user['UserName'])
for key in keys['AccessKeyMetadata']:
if key['CreateDate'].replace(tzinfo=None) < threshold:
age = (datetime.now() - key['CreateDate'].replace(tzinfo=None)).days
print(f" {user['UserName']}: {key['AccessKeyId']} ({age} days old)")
Audit Privileged Roles
Description:
Review IAM roles with administrative permissions
How It Works:
Check roles for admin policies and review trust relationships to ensure only authorized principals can assume them.
Configuration Items:
- role_checks: ['List roles with admin policies', 'Review trust policy (who can assume)', 'Check for cross-account access', 'Verify session duration limits', 'Review role tags for ownership']
Example Cli:
# List all roles aws iam list-roles # Get role details aws iam get-role --role-name MyAdminRole # List attached policies aws iam list-attached-role-policies --role-name MyAdminRole
Example Boto3:
import boto3
import json
iam = boto3.client('iam')
roles = iam.list_roles()
print("Roles with Administrative Permissions:")
for role in roles['Roles']:
# Check attached policies
attached = iam.list_attached_role_policies(RoleName=role['RoleName'])
for policy in attached['AttachedPolicies']:
if 'Admin' in policy['PolicyName']:
print(f"\n{role['RoleName']}:")
print(f" Policy: {policy['PolicyName']}")
# Get trust policy
trust = role['AssumeRolePolicyDocument']
principals = []
for statement in trust['Statement']:
if 'Principal' in statement:
principals.append(statement['Principal'])
print(f" Can be assumed by: {principals}")
Automated Compliance
Automated Privileged Account Compliance Scan
Description:
Complete scan of all privileged accounts
How It Works:
Checks all privileged users and roles for MFA, key age, and policy compliance.
Example Boto3:
#!/usr/bin/env python3
import boto3, csv, base64, time
from datetime import datetime, timedelta
def scan_privileged_accounts():
iam = boto3.client('iam')
findings = []
# Generate credential report
iam.generate_credential_report()
time.sleep(5)
report = base64.b64decode(iam.get_credential_report()['Content']).decode()
# Check each user
for row in csv.DictReader(report.splitlines()):
user = row['user']
if user == '':
continue
# Check for admin access
try:
policies = iam.list_attached_user_policies(UserName=user)
is_admin = any('Admin' in p['PolicyName'] for p in policies['AttachedPolicies'])
if is_admin:
# Check MFA
if row['mfa_active'] != 'true':
findings.append(f"CRITICAL: {user} has admin access without MFA")
# Check key age
keys = iam.list_access_keys(UserName=user)
for key in keys['AccessKeyMetadata']:
age = (datetime.now() - key['CreateDate'].replace(tzinfo=None)).days
if age > 90:
findings.append(f"WARNING: {user} has access key {age} days old")
except:
pass
return findings
if __name__ == '__main__':
findings = scan_privileged_accounts()
print(f"Found {len(findings)} issues:")
for f in findings:
print(f" - {f}")
References
- AWS IAM Best Practices: https://docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html
- AWS Organizations SCPs: https://docs.aws.amazon.com/organizations/latest/userguide/orgs_manage_policies_scps.html