Skip to content

Automating AWS Security Contact Configuration Across Your Organization

3 minute read
Content level: Foundational
0

A practical guide to implementing security contact automation using CloudFormation StackSets

The Challenge

Organizations with multiple AWS accounts need accurate security contact information to ensure AWS Security can reach appropriate teams during incidents. Manual configuration across hundreds of accounts becomes impractical and error-prone. Organizations need automated deployment that scales with their AWS footprint.

This best practice is supported by CIS AWS Foundations Benchmark v3.0.0 Account.1 control, which requires security contact information for each AWS account.

AWS Organizations Integration

AWS Account Management service integrates with AWS Organizations for centralized alternate contact management. The management account can programmatically set security contact information across all member accounts using APIs for billing, operations, and security contacts.

Implementation Approach

CloudFormation StackSets provide scalable deployment using Lambda-backed custom resources to call the AWS Account Management API. The solution deploys consistently across all accounts and automatically applies to new accounts when configured with automatic deployment.

CloudFormation Template

AWSTemplateFormatVersion: '2010-09-09'
Parameters:
  SecurityContactName:
    Type: String
    Description: Name of the security contact
    Default: "Security Team"
  SecurityContactEmail:
    Type: String
    Description: Email address of the security contact
    AllowedPattern: "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$"
  SecurityContactPhone:
    Type: String
    Description: Phone number of the security contact
    Default: "+1-555-0123"

Resources:
  SecurityContact:
    Type: AWS::CloudFormation::CustomResource
    Properties:
      ServiceToken: !GetAtt SecurityContactFunction.Arn
      ContactName: !Ref SecurityContactName
      ContactEmail: !Ref SecurityContactEmail
      ContactPhone: !Ref SecurityContactPhone
      
  SecurityContactFunction:
    Type: AWS::Lambda::Function
    Properties:
      Runtime: python3.12
      Handler: index.handler
      Role: !GetAtt LambdaExecutionRole.Arn
      Code:
        ZipFile: |
          import boto3
          import cfnresponse
          def handler(event, context):
              try:
                  account_client = boto3.client('account')
                  if event['RequestType'] == 'Create' or event['RequestType'] == 'Update':
                      account_client.put_alternate_contact(
                          AlternateContactType='SECURITY',
                          Name=event['ResourceProperties']['ContactName'],
                          EmailAddress=event['ResourceProperties']['ContactEmail'],
                          PhoneNumber=event['ResourceProperties']['ContactPhone'],
                          Title='Security Operations'
                      )
                  cfnresponse.send(event, context, cfnresponse.SUCCESS, {})
              except Exception as e:
                  print(f"Error: {str(e)}")
                  cfnresponse.send(event, context, cfnresponse.FAILED, {})
                  
  LambdaExecutionRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Effect: Allow
            Principal:
              Service: lambda.amazonaws.com
            Action: sts:AssumeRole
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
      Policies:
        - PolicyName: AccountManagementPolicy
          PolicyDocument:
            Version: '2012-10-17'
            Statement:
              - Effect: Allow
                Action:
                  - account:PutAlternateContact
                  - account:GetAlternateContact
                Resource: '*'

Deployment Strategy

Deploy using CloudFormation StackSets from the management account or delegated administrator. Target organizational units based on governance requirements and enable automatic deployment for new accounts.

# Create StackSet
aws cloudformation create-stack-set \
  --stack-set-name security-contact-stackset \
  --template-body file://security-contact.yaml \
  --capabilities CAPABILITY_IAM \
  --parameters ParameterKey=SecurityContactEmail,ParameterValue=security@company.com

# Deploy to organization
aws cloudformation create-stack-instances \
  --stack-set-name security-contact-stackset \
  --deployment-targets OrganizationalUnitIds=r-[placeholder org id] \
  --regions us-east-1 \
  --operation-preferences MaxConcurrentPercentage=100

Operations and Maintenance

Use centralized security email addresses or distribution lists to ensure notifications reach appropriate teams regardless of personnel changes. Periodically verify contact information using the get-alternate-contact API.

AWS Security Hub provides built-in detective controls to monitor accounts without configured security contacts through CIS compliance checks.

Limitations and Alternatives

This approach creates Lambda functions in each account, which may be unnecessary overhead for one-time configuration.

For one-time setup, AWS CLI provides simpler deployment without per-account resources. See Programmatically managing alternate contacts on member accounts with AWS Organizations for CLI implementation.

CloudFormation StackSets provide ongoing management and automatic application to new accounts, while CLI offers simpler one-time deployment.

AWS
EXPERT
published 2 months ago113 views