Your AWS root account is the master key to your entire cloud environment. Compromising the root account gives attackers unrestricted access to all resources, billing information, and the ability to delete your entire infrastructure. Properly securing the root account is the most critical security measure you can take in AWS.
This article is part of our comprehensive Cloud Security Tips for 2026 guide covering essential practices for protecting your cloud environment.
Why Root Account Security Matters
The root account has unique properties that make it especially dangerous:
| Root Account Capability | Risk Level |
|---|---|
| Cannot be restricted by IAM policies | Critical |
| Can close the entire AWS account | Critical |
| Can access all billing and payment methods | High |
| Can change account email and contact info | High |
| Can delete any resource without restriction | Critical |
Step 1: Enable MFA on Root Account
Using AWS Console
- Sign in to the AWS Management Console as root user
- Click your account name in the top right, then Security credentials
- In the Multi-factor authentication (MFA) section, click Assign MFA device
- Enter a device name (e.g., "root-yubikey" or "root-authenticator")
- Select your MFA device type:
- Hardware TOTP token - Most secure option
- Authenticator app - Good security, widely available
- Security key - FIDO2 hardware key like YubiKey
- Follow the prompts to register your device
- Enter two consecutive MFA codes to verify setup
Using AWS CLI (For Virtual MFA)
# Create virtual MFA device
aws iam create-virtual-mfa-device \
--virtual-mfa-device-name root-mfa \
--outfile qrcode.png \
--bootstrap-method QRCodePNG
# Display the QR code and scan with your authenticator app
# Then enable MFA with two consecutive codes
aws iam enable-mfa-device \
--user-name root \
--serial-number arn:aws:iam::123456789012:mfa/root-mfa \
--authentication-code1 123456 \
--authentication-code2 789012Step 2: Create Administrative IAM Users
Create IAM users for all administrative tasks instead of using root:
# Create an admin user
aws iam create-user --user-name admin-john
# Attach administrator policy
aws iam attach-user-policy \
--user-name admin-john \
--policy-arn arn:aws:iam::aws:policy/AdministratorAccess
# Create login profile for console access
aws iam create-login-profile \
--user-name admin-john \
--password 'TempPassword123!' \
--password-reset-required
# Enable MFA for the admin user
aws iam create-virtual-mfa-device \
--virtual-mfa-device-name admin-john-mfa \
--outfile admin-john-qr.png \
--bootstrap-method QRCodePNGTerraform Configuration
resource "aws_iam_user" "admin" {
name = "admin-john"
tags = {
Purpose = "Administrative access"
}
}
resource "aws_iam_user_policy_attachment" "admin_attach" {
user = aws_iam_user.admin.name
policy_arn = "arn:aws:iam::aws:policy/AdministratorAccess"
}
resource "aws_iam_user_login_profile" "admin_login" {
user = aws_iam_user.admin.name
password_reset_required = true
}Step 3: Remove Root Access Keys
Root access keys should never exist. If any exist, delete them immediately:
Using AWS Console
- Sign in as root user
- Go to Security credentials
- Under Access keys, delete any existing keys
- Never create new access keys for root
Check for Root Access Keys via CLI
# Generate credential report
aws iam generate-credential-report
# Wait for report generation
sleep 5
# Check root access key status
aws iam get-credential-report \
--query 'Content' \
--output text | base64 -d | head -2
# Output shows if root has access keys:
# user,arn,user_creation_time,access_key_1_active,access_key_2_active
# <root_account>,arn:aws:iam::123456789012:root,2020-01-01,false,falseStep 4: Configure CloudTrail Alerts for Root Usage
Set up immediate alerts when anyone uses the root account:
# Create CloudWatch log group for CloudTrail
aws logs create-log-group --log-group-name /aws/cloudtrail/root-activity
# Create metric filter for root account usage
aws logs put-metric-filter \
--log-group-name /aws/cloudtrail/root-activity \
--filter-name RootAccountUsage \
--filter-pattern '{ $.userIdentity.type = "Root" && $.userIdentity.invokedBy NOT EXISTS && $.eventType != "AwsServiceEvent" }' \
--metric-transformations \
metricName=RootAccountUsageCount,metricNamespace=SecurityMetrics,metricValue=1
# Create alarm
aws cloudwatch put-metric-alarm \
--alarm-name root-account-usage \
--alarm-description "Alert when root account is used" \
--metric-name RootAccountUsageCount \
--namespace SecurityMetrics \
--statistic Sum \
--period 300 \
--threshold 1 \
--comparison-operator GreaterThanOrEqualToThreshold \
--evaluation-periods 1 \
--alarm-actions arn:aws:sns:us-east-1:123456789012:security-alertsTerraform Configuration
resource "aws_cloudwatch_log_metric_filter" "root_usage" {
name = "RootAccountUsage"
pattern = "{ $.userIdentity.type = \"Root\" && $.userIdentity.invokedBy NOT EXISTS && $.eventType != \"AwsServiceEvent\" }"
log_group_name = aws_cloudwatch_log_group.cloudtrail.name
metric_transformation {
name = "RootAccountUsageCount"
namespace = "SecurityMetrics"
value = "1"
}
}
resource "aws_cloudwatch_metric_alarm" "root_usage_alarm" {
alarm_name = "root-account-usage"
comparison_operator = "GreaterThanOrEqualToThreshold"
evaluation_periods = 1
metric_name = "RootAccountUsageCount"
namespace = "SecurityMetrics"
period = 300
statistic = "Sum"
threshold = 1
alarm_description = "Alert when root account is used"
alarm_actions = [aws_sns_topic.security_alerts.arn]
}Step 5: Set Up Break-Glass Procedure
Document a secure process for emergency root access:
Break-Glass Process
- Physical Security: Store root credentials in a physical safe or secure vault
- Dual Control: Require two authorized personnel to access root credentials
- Documentation: Log all root access with ticket number and justification
- Time-Limited: Complete task and sign out immediately
- Post-Access Audit: Review CloudTrail logs after each root session
Secure Storage Options
| Storage Method | Pros | Cons |
|---|---|---|
| Physical Safe | No digital exposure | Physical access required |
| Hardware Security Module | Tamper-resistant, auditable | Expensive |
| Split Knowledge | No single person has full access | Complex recovery |
| Sealed Envelope + Safe | Simple, effective | Manual process |
Step 6: Use AWS Organizations with SCPs
Service Control Policies can restrict root account actions across member accounts:
# Create SCP to deny root actions
aws organizations create-policy \
--name DenyRootActions \
--description "Deny dangerous root account actions" \
--type SERVICE_CONTROL_POLICY \
--content '{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "DenyRootActions",
"Effect": "Deny",
"Action": [
"ec2:*",
"s3:*",
"iam:*"
],
"Resource": "*",
"Condition": {
"StringLike": {
"aws:PrincipalArn": "arn:aws:iam::*:root"
}
}
}
]
}'Step 7: Account Recovery Setup
Configure account recovery options before you need them:
Update Account Contact Information
- Sign in as root to the Account Settings page
- Update Alternate Contacts with security and operations team emails
- Verify the Account email address is monitored
- Add a Phone number for account verification
Store Recovery Information Securely
# Document these items in your break-glass envelope:
# - AWS Account ID: 123456789012
# - Root email address: [email protected]
# - Phone number on file: +1-555-123-4567
# - MFA device serial number: arn:aws:iam::123456789012:mfa/root-yubikey
# - MFA backup codes (if virtual MFA)
# - Answers to security questions (if configured)Audit Your Root Account Security
#!/bin/bash
# Root account security audit script
echo "=== AWS Root Account Security Audit ==="
# Check for root access keys
echo -e "\n1. Checking for root access keys..."
aws iam generate-credential-report > /dev/null 2>&1
sleep 3
ROOT_KEYS=$(aws iam get-credential-report --query 'Content' --output text | base64 -d | grep "^" | cut -d',' -f9,14)
echo "Root access keys status: $ROOT_KEYS"
# Check for root MFA
echo -e "\n2. Checking root MFA status..."
ROOT_MFA=$(aws iam get-credential-report --query 'Content' --output text | base64 -d | grep "^" | cut -d',' -f8)
echo "Root MFA enabled: $ROOT_MFA"
# Check recent root logins
echo -e "\n3. Checking recent root activity..."
aws cloudtrail lookup-events \
--lookup-attributes AttributeKey=Username,AttributeValue=root \
--max-results 5 \
--query 'Events[*].[EventTime,EventName,EventSource]' \
--output table
echo -e "\n=== Audit Complete ===" Best Practices Checklist
| Security Control | Priority | Status |
|---|---|---|
| Enable hardware MFA on root | Critical | [ ] |
| Delete root access keys | Critical | [ ] |
| Create IAM admin users | Critical | [ ] |
| Set up CloudTrail alerts | High | [ ] |
| Document break-glass procedure | High | [ ] |
| Store credentials securely | High | [ ] |
| Update account contacts | Medium | [ ] |
| Apply SCPs (Organizations) | Medium | [ ] |