FRR-RSC-04: Secure Defaults on Provisioning
Applies to: Low, Moderate, High
Last Updated: 2025-11-25
Version: 1.0.0
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
- name: AWS Control Tower
url: https://aws.amazon.com/controltower/ - name: CloudFormation
url: https://docs.aws.amazon.com/cloudformation/ - name: AWS Organizations SCPs
url: https://docs.aws.amazon.com/organizations/latest/userguide/orgs_manage_policies_scps.html