šŸ”’ AWS Secure Configuration Guidance

FedRAMP Rev5 Recommended Secure Configuration (RSC) Requirements

Guidance Home Downloads

FRR-RSC-04: Secure Defaults on Provisioning

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

Overview

AWS provides secure defaults for new accounts and can be configured to enforce
secure settings automatically using CloudFormation, AWS Control Tower, or Organizations.

Automation Methods

AWS CloudFormation

Description:

Infrastructure as Code for deploying secure defaults

How It Works:

Define resources and configurations in YAML/JSON templates. CloudFormation creates resources with specified settings automatically.

Configuration Items:

  • deployable_resources: ['IAM password policy via custom resource', 'CloudTrail with encryption and validation', 'S3 buckets with encryption and versioning', 'VPC with security groups', 'Config rules and conformance packs', 'CloudWatch alarms and dashboards']
  • template_features: ['Parameters for customization', 'Conditions for environment-specific logic', 'Outputs for cross-stack references', 'Change sets for preview before deployment']

Example Cli:

# Deploy CloudFormation stack
aws cloudformation create-stack \
  --stack-name fedramp-baseline \
  --template-body file://fedramp-rsc-complete.yaml \
  --capabilities CAPABILITY_IAM \
  --parameters ParameterKey=Environment,ParameterValue=Production

# Check stack status
aws cloudformation describe-stacks --stack-name fedramp-baseline

# Update stack
aws cloudformation update-stack \
  --stack-name fedramp-baseline \
  --template-body file://fedramp-rsc-complete.yaml \
  --capabilities CAPABILITY_IAM

Example Boto3:

import boto3

cfn = boto3.client('cloudformation')

# Read template
with open('fedramp-rsc-complete.yaml', 'r') as f:
    template = f.read()

# Create stack
response = cfn.create_stack(
    StackName='fedramp-baseline',
    TemplateBody=template,
    Capabilities=['CAPABILITY_IAM'],
    Parameters=[
        {'ParameterKey': 'Environment', 'ParameterValue': 'Production'}
    ]
)

print(f"Stack ID: {response['StackId']}")

# Wait for completion
waiter = cfn.get_waiter('stack_create_complete')
waiter.wait(StackName='fedramp-baseline')
print("āœ“ Stack created successfully")

AWS Control Tower

Description:

Automated multi-account AWS environment setup with guardrails

How It Works:

Orchestrates AWS Organizations, SSO, CloudFormation, and Config to enforce governance across all accounts.

Configuration Items:

  • guardrails: ['Disallow changes to CloudTrail (preventive)', 'Enable CloudTrail in all regions (detective)', 'Disallow public S3 buckets (preventive)', 'Enable MFA for root user (detective)', 'Disallow internet connection through RDP (preventive)']
  • account_factory: ['Automated account provisioning', 'Baseline security controls applied', 'SSO integration', 'Centralized logging']

Example Cli:

# List Control Tower guardrails (via Service Catalog)
aws servicecatalog search-products --filters FullTextSearch=guardrail

# Check Control Tower landing zone status
aws controltower list-landing-zones

Example Boto3:

import boto3

# Control Tower uses Service Catalog for account factory
sc = boto3.client('servicecatalog')

# List available account factory products
products = sc.search_products(
    Filters={'FullTextSearch': ['AWS Control Tower Account Factory']}
)

print("Control Tower Products:")
for product in products['ProductViewSummaries']:
    print(f"  - {product['Name']}")

AWS Organizations Service Control Policies

Description:

Permission boundaries that apply to all accounts in an organization

How It Works:

SCPs are JSON policies that set maximum permissions. Even if IAM allows an action, SCP can deny it.

Configuration Items:

  • preventive_controls: ['Prevent disabling CloudTrail', 'Prevent disabling Config', 'Enforce encryption requirements', 'Restrict regions', 'Prevent root access key creation']
  • policy_targets: ['Root of organization (all accounts)', 'Organizational units (subset of accounts)', 'Individual accounts']

Example Cli:

# List all SCPs
aws organizations list-policies --filter SERVICE_CONTROL_POLICY

# Create SCP
aws organizations create-policy \
  --name PreventSecurityDisablement \
  --type SERVICE_CONTROL_POLICY \
  --content file://scp.json

# Attach SCP to OU
aws organizations attach-policy \
  --policy-id p-xxxxx \
  --target-id ou-xxxxx

Example Boto3:

import boto3
import json

orgs = boto3.client('organizations')

# Create SCP to prevent CloudTrail disablement
scp_policy = {
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Deny",
            "Action": [
                "cloudtrail:StopLogging",
                "cloudtrail:DeleteTrail"
            ],
            "Resource": "*"
        }
    ]
}

# Create policy
response = orgs.create_policy(
    Content=json.dumps(scp_policy),
    Description='Prevent CloudTrail disablement',
    Name='ProtectCloudTrail',
    Type='SERVICE_CONTROL_POLICY'
)

print(f"Created SCP: {response['Policy']['PolicySummary']['Id']}")

# Attach to organization root
orgs.attach_policy(
    PolicyId=response['Policy']['PolicySummary']['Id'],
    TargetId='r-xxxx'  # Organization root ID
)
print("āœ“ SCP attached to organization")

Validation Checks

Validate IAM Password Policy

Description:

Check password policy meets FedRAMP requirements

How It Works:

Query IAM for current password policy and compare against FedRAMP baseline.

Configuration Items:

  • fedramp_requirements: ['MinimumPasswordLength >= 14', 'RequireSymbols = true', 'RequireNumbers = true', 'RequireUppercaseCharacters = true', 'RequireLowercaseCharacters = true', 'MaxPasswordAge <= 90', 'PasswordReusePrevention >= 24']

Example Cli:

aws iam get-account-password-policy

Example Boto3:

import boto3

iam = boto3.client('iam')

try:
    policy = iam.get_account_password_policy()['PasswordPolicy']
    
    checks = {
        'MinimumPasswordLength >= 14': policy.get('MinimumPasswordLength', 0) >= 14,
        'RequireSymbols': policy.get('RequireSymbols', False),
        'RequireNumbers': policy.get('RequireNumbers', False),
        'RequireUppercaseCharacters': policy.get('RequireUppercaseCharacters', False),
        'RequireLowercaseCharacters': policy.get('RequireLowercaseCharacters', False),
        'MaxPasswordAge <= 90': policy.get('MaxPasswordAge', 999) <= 90,
        'PasswordReusePrevention >= 24': policy.get('PasswordReusePrevention', 0) >= 24
    }
    
    print("Password Policy Compliance:")
    for check, passed in checks.items():
        print(f"  {'āœ“' if passed else 'āœ—'} {check}")
    
    if all(checks.values()):
        print("\nāœ“ Password policy is FedRAMP compliant")
    else:
        print("\nāœ— Password policy needs updates")
except:
    print("āœ— No password policy configured")

Verify CloudTrail Configuration

Description:

Ensure CloudTrail is enabled with proper settings

How It Works:

Check all trails for multi-region logging, log validation, and encryption.

Configuration Items:

  • required_settings: ['IsLogging = true', 'IsMultiRegionTrail = true', 'LogFileValidationEnabled = true', 'S3 bucket encryption enabled', 'CloudWatch Logs integration']

Example Cli:

# List all trails
aws cloudtrail describe-trails

# Check trail status
aws cloudtrail get-trail-status --name my-trail

# Get event selectors
aws cloudtrail get-event-selectors --trail-name my-trail

Example Boto3:

import boto3

cloudtrail = boto3.client('cloudtrail')

trails = cloudtrail.describe_trails()['trailList']

if not trails:
    print("āœ— CRITICAL: No CloudTrail trails configured")
else:
    for trail in trails:
        name = trail['Name']
        status = cloudtrail.get_trail_status(Name=name)
        
        checks = {
            'Logging': status['IsLogging'],
            'Multi-Region': trail.get('IsMultiRegionTrail', False),
            'Log Validation': trail.get('LogFileValidationEnabled', False)
        }
        
        print(f"\nTrail: {name}")
        for check, value in checks.items():
            print(f"  {'āœ“' if value else 'āœ—'} {check}")

Complete Account Baseline Validation

Description:

Validate all secure defaults are configured

How It Works:

Comprehensive script that checks password policy, CloudTrail, Config, and other baseline requirements.

Example Boto3:

#!/usr/bin/env python3
import boto3
from datetime import datetime

def validate_account_baseline():
    iam = boto3.client('iam')
    cloudtrail = boto3.client('cloudtrail')
    config = boto3.client('config')
    
    results = {
        'timestamp': datetime.now().isoformat(),
        'checks': {},
        'compliant': False
    }
    
    # Check password policy
    try:
        policy = iam.get_account_password_policy()['PasswordPolicy']
        results['checks']['password_policy'] = {
            'status': 'PASS' if policy.get('MinimumPasswordLength', 0) >= 14 else 'FAIL',
            'details': f"Min length: {policy.get('MinimumPasswordLength', 0)}"
        }
    except:
        results['checks']['password_policy'] = {'status': 'FAIL', 'details': 'Not configured'}
    
    # Check CloudTrail
    trails = cloudtrail.describe_trails()['trailList']
    multi_region = any(t.get('IsMultiRegionTrail') for t in trails)
    results['checks']['cloudtrail'] = {
        'status': 'PASS' if multi_region else 'FAIL',
        'details': f"{len(trails)} trails, multi-region: {multi_region}"
    }
    
    # Check Config
    try:
        recorders = config.describe_configuration_recorders()
        recorder_status = config.describe_configuration_recorder_status()
        recording = any(r['recording'] for r in recorder_status['ConfigurationRecordersStatus'])
        results['checks']['config'] = {
            'status': 'PASS' if recording else 'FAIL',
            'details': f"Recording: {recording}"
        }
    except:
        results['checks']['config'] = {'status': 'FAIL', 'details': 'Not configured'}
    
    # Overall compliance
    results['compliant'] = all(
        c['status'] == 'PASS' for c in results['checks'].values()
    )
    
    return results

if __name__ == '__main__':
    import json
    results = validate_account_baseline()
    print(json.dumps(results, indent=2))
    
    if results['compliant']:
        print("\nāœ“ Account baseline is compliant")
    else:
        print("\nāœ— Account baseline has issues")

References