🔒 AWS Secure Configuration Guidance

FedRAMP Rev5 Recommended Secure Configuration (RSC) Requirements

Guidance Home Downloads

FRR-RSC-01: Top-Level Administrative Accounts Guidance

Applies to: Low, Moderate, High
Last Updated: 2025-11-25
Version: 1.0.0

Overview

This guidance explains how to securely access, configure, operate, and decommission 
the AWS root account, which is the top-level administrative account that controls 
enterprise access to your entire AWS cloud service offering.

Secure Access Methods

Enable Multi-Factor Authentication (MFA)

Description:

Root account must have MFA enabled for authentication

How It Works:

MFA adds a second authentication factor beyond password. Hardware MFA devices generate time-based codes. Virtual MFA uses authenticator apps.

Configuration Items:

  • hardware_mfa: ['Gemalto token - FIPS 140-2 Level 2 validated', 'YubiKey - Hardware security key', 'AWS-supported hardware MFA devices']
  • virtual_mfa: ['Google Authenticator - Mobile app', 'Microsoft Authenticator - Mobile app', 'Authy - Multi-device support']

Example Cli:

# Check if root MFA is enabled
aws iam get-account-summary --query 'SummaryMap.AccountMFAEnabled'

# List MFA devices (requires root credentials)
aws iam list-mfa-devices

Example Boto3:

import boto3

iam = boto3.client('iam')

# Check root MFA status
summary = iam.get_account_summary()
mfa_enabled = summary['SummaryMap'].get('AccountMFAEnabled', 0) == 1

if mfa_enabled:
    print("✓ Root account MFA is enabled")
else:
    print("✗ CRITICAL: Root account MFA is NOT enabled")

Delete Root Access Keys

Description:

Root account must not have active access keys

How It Works:

Access keys provide programmatic access. Root access keys are extremely dangerous if compromised. AWS recommends never creating them.

Configuration Items:

  • validation_checks: ['Check credential report for active keys', 'Verify access_key_1_active = false', 'Verify access_key_2_active = false', 'Monitor CloudTrail for key creation events']

Example Cli:

# Generate and check credential report
aws iam generate-credential-report
sleep 5
aws iam get-credential-report --query 'Content' --output text | base64 -d | grep ''

Example Boto3:

import boto3
import csv
import base64
import time

iam = boto3.client('iam')

# Generate credential report
iam.generate_credential_report()
time.sleep(5)

# Get and parse report
response = iam.get_credential_report()
report = base64.b64decode(response['Content']).decode('utf-8')

# Check root account row
reader = csv.DictReader(report.splitlines())
for row in reader:
    if row['user'] == '':
        key1_active = row['access_key_1_active'] == 'true'
        key2_active = row['access_key_2_active'] == 'true'
        
        if key1_active or key2_active:
            print("✗ CRITICAL: Root account has active access keys")
        else:
            print("✓ Root account has no access keys")

Monitor Root Account Usage

Description:

Root account should not be used for day-to-day operations

How It Works:

CloudTrail logs all root account activity. Best practice is zero usage except for specific tasks requiring root.

Configuration Items:

  • monitoring_methods: ['CloudTrail event lookup for root user', 'CloudWatch metric filters and alarms', 'AWS Config rule: root-account-mfa-enabled', 'Security Hub control: IAM.4, IAM.6']
  • acceptable_root_tasks: ['Change account settings', 'Close AWS account', 'Change AWS Support plan', 'Restore IAM user permissions', 'Enable MFA Delete on S3 bucket', 'Sign up for GovCloud']

Example Cli:

# Check for root usage in last 90 days
aws cloudtrail lookup-events \
  --lookup-attributes AttributeKey=Username,AttributeValue=root \
  --start-time $(date -u -d '90 days ago' +%Y-%m-%dT%H:%M:%S) \
  --max-results 10

Example Boto3:

import boto3
from datetime import datetime, timedelta

cloudtrail = boto3.client('cloudtrail')

# Look for root usage in last 90 days
start_time = datetime.now() - timedelta(days=90)

events = cloudtrail.lookup_events(
    LookupAttributes=[
        {'AttributeKey': 'Username', 'AttributeValue': 'root'}
    ],
    StartTime=start_time
)

if events['Events']:
    print(f"âš  Root account used {len(events['Events'])} times in last 90 days")
    for event in events['Events'][:5]:
        print(f"  - {event['EventTime']}: {event['EventName']}")
else:
    print("✓ No root account usage in last 90 days")

Automated Compliance

Automated Root Account Compliance Check

Description:

Complete script to validate all root account security requirements

How It Works:

Checks MFA status, access keys, and recent usage. Returns compliance status with detailed findings.

Example Boto3:

#!/usr/bin/env python3
import boto3
import csv
import base64
import time
from datetime import datetime, timedelta

def check_root_compliance():
    iam = boto3.client('iam')
    cloudtrail = boto3.client('cloudtrail')
    
    results = {
        'mfa_enabled': False,
        'no_access_keys': False,
        'no_recent_usage': False,
        'compliant': False
    }
    
    # Check MFA
    summary = iam.get_account_summary()
    results['mfa_enabled'] = summary['SummaryMap'].get('AccountMFAEnabled', 0) == 1
    
    # Check access keys
    iam.generate_credential_report()
    time.sleep(5)
    response = iam.get_credential_report()
    report = base64.b64decode(response['Content']).decode('utf-8')
    
    reader = csv.DictReader(report.splitlines())
    for row in reader:
        if row['user'] == '':
            key1 = row['access_key_1_active'] == 'true'
            key2 = row['access_key_2_active'] == 'true'
            results['no_access_keys'] = not (key1 or key2)
    
    # Check usage
    start_time = datetime.now() - timedelta(days=90)
    events = cloudtrail.lookup_events(
        LookupAttributes=[
            {'AttributeKey': 'Username', 'AttributeValue': 'root'}
        ],
        StartTime=start_time,
        MaxResults=1
    )
    results['no_recent_usage'] = len(events['Events']) == 0
    
    # Overall compliance
    results['compliant'] = all([
        results['mfa_enabled'],
        results['no_access_keys'],
        results['no_recent_usage']
    ])
    
    return results

if __name__ == '__main__':
    results = check_root_compliance()
    
    print("Root Account Compliance Check")
    print("=" * 40)
    print(f"MFA Enabled: {'✓' if results['mfa_enabled'] else '✗ FAIL'}")
    print(f"No Access Keys: {'✓' if results['no_access_keys'] else '✗ FAIL'}")
    print(f"No Recent Usage: {'✓' if results['no_recent_usage'] else '✗ WARN'}")
    print("=" * 40)
    print(f"Overall: {'✓ COMPLIANT' if results['compliant'] else '✗ NON-COMPLIANT'}")

CloudWatch Alarms for Root Activity

Description:

Set up automated alerts for root account usage

How It Works:

CloudWatch metric filters parse CloudTrail logs. Alarms trigger SNS notifications when root account is used.

Configuration Items:

  • alarm_components: ['CloudTrail log group', 'Metric filter for root user events', 'CloudWatch alarm with SNS topic', 'Email/SMS notifications']

Example Cli:

# Create metric filter for root usage
aws logs put-metric-filter \
  --log-group-name CloudTrail/logs \
  --filter-name RootAccountUsage \
  --filter-pattern '{ $.userIdentity.type = "Root" && $.userIdentity.invokedBy NOT EXISTS && $.eventType != "AwsServiceEvent" }' \
  --metric-transformations \
    metricName=RootAccountUsage,metricNamespace=CloudTrailMetrics,metricValue=1

# Create alarm
aws cloudwatch put-metric-alarm \
  --alarm-name RootAccountUsageAlarm \
  --alarm-description "Alert on root account usage" \
  --metric-name RootAccountUsage \
  --namespace CloudTrailMetrics \
  --statistic Sum \
  --period 300 \
  --evaluation-periods 1 \
  --threshold 1 \
  --comparison-operator GreaterThanOrEqualToThreshold \
  --alarm-actions arn:aws:sns:us-east-1:123456789012:SecurityAlerts

Example Boto3:

import boto3

logs = boto3.client('logs')
cloudwatch = boto3.client('cloudwatch')

# Create metric filter
logs.put_metric_filter(
    logGroupName='CloudTrail/logs',
    filterName='RootAccountUsage',
    filterPattern='{ $.userIdentity.type = "Root" && $.userIdentity.invokedBy NOT EXISTS && $.eventType != "AwsServiceEvent" }',
    metricTransformations=[
        {
            'metricName': 'RootAccountUsage',
            'metricNamespace': 'CloudTrailMetrics',
            'metricValue': '1'
        }
    ]
)

# Create alarm
cloudwatch.put_metric_alarm(
    AlarmName='RootAccountUsageAlarm',
    AlarmDescription='Alert on root account usage',
    MetricName='RootAccountUsage',
    Namespace='CloudTrailMetrics',
    Statistic='Sum',
    Period=300,
    EvaluationPeriods=1,
    Threshold=1.0,
    ComparisonOperator='GreaterThanOrEqualToThreshold',
    AlarmActions=['arn:aws:sns:us-east-1:123456789012:SecurityAlerts']
)

print("✓ Root account monitoring configured")

References