
AWS Control Towerを触ってみた
Contorl Towerの東京リージョンがサポートされたので触ってみました。
色々と調査する過程で、Control Towerを有効化した時に
裏側で流れるcloudformationを読み解いて図示したので
きっと誰かの役に立つと思いブログ化してみました。
Control Towerを有効化する前
簡単に、有効化前はorganizationsの配下にたくさんアカウントがいると仮定します。
Control Towerを有効化した後
control towerを有効化しても、既存アカウントに即座には影響はありません。
control towerが有効化されているOUの配下にアカウントを持ってくると
各種設定(cloudformationやらSCPやら)が有効化されます。
ここで、SCPは分かりやすくドキュメントに整理されていました。 docs.aws.amazon.com
ただ、cloudformationの方は、分かりやすく記載されたものが
見つけられませんでした。
ドキュメントをみてみると、cloudformaitonを確認するのが良いと書いてあったので、
大変でしたが自分で読み解いてみました。
読み解くと結構時間かかったので、
今後、同じ想いで苦労する人を救いたい一心で結果を図示してみました。
裏側のcloudformationを図示
全部読み解くと、下記のようになっていました。
control towerの全体図です。
裏側のcloudformation詳細
ここからは各stackの中身を記載していきます。
読み解く時にはメモが参考になると思います。
もし間違いを見つけた場合は、ご連絡いただけますと嬉しいです。
AWSControlTowerBP-BASELINE-CLOUDTRAIL
概要
trailを有効化し結果をS3とlogsに出力する
S3はアーカイブアカウント宛で、マルチリージョンを記録します
logs連携は有効化され、retentionは14日
configはsnsを設定、セキュリティアカウントの「aws-controltower-AllConfigNotification」に通知 します
デプロイ対象
下記のcontroltowerを有効化した1つのリージョン
core ou
custome ou
cloudformation template
AWSTemplateFormatVersion: 2010-09-09
Description: Configure AWS CloudTrail
Parameters:
ManagedResourcePrefix:
Type: 'String'
Description: 'Prefix for the managed resources'
EnableLogFileValidation:
Type: String
Default: 'true'
Description: Indicates whether CloudTrail validates the integrity of log files.
AllowedValues:
- 'true'
- 'false'
IncludeGlobalEvents:
Type: String
Default: 'true'
Description: Indicates whether the trail is publishing events from global services, such as IAM, to the log files.
AllowedValues:
- 'true'
- 'false'
MultiRegion:
Type: String
Default: 'true'
Description: Indicates whether the CloudTrail trail is created in the region in which you create the stack (false) or in all regions (true).
AllowedValues:
- 'true'
- 'false'
AllConfigTopicName:
Type: String
Default: ''
Description: All Configuration Notification SNS Topic in Security Account that AWS Config delivers notifications to.
SecurityAccountId:
Type: 'String'
Description: AWS Account Id of the Security account.
AuditBucketName:
Type: String
Default: ''
Description: Audit Bucket name from the Log Archive Account
PublishToCloudWatchLogs:
Type: String
Default: 'true'
Description: Indicates whether notifications are published to CloudWatch Logs.
AllowedValues:
- 'true'
- 'false'
LogsRetentionInDays:
Description: 'Specifies the number of days you want to retain CloudTrail log events in the CloudWatch Logs.'
Type: Number
Default: 14
AllowedValues: [1, 3, 5, 7, 14, 30, 60, 90, 120, 150, 180, 365, 400, 545, 731, 1827, 3653]
AWSLogsS3KeyPrefix:
Type: 'String'
Description: 'Organization ID to use as the S3 Key prefix for storing the audit logs'
Conditions:
IsMultiRegion: !Equals
- !Ref MultiRegion
- 'true'
IsPublishToCloudWatchLogs: !Equals
- !Ref PublishToCloudWatchLogs
- 'true'
Resources:
Trail:
Type: AWS::CloudTrail::Trail
Properties:
TrailName: !Sub ${ManagedResourcePrefix}-BaselineCloudTrail
S3BucketName: !Ref AuditBucketName
S3KeyPrefix: !Ref AWSLogsS3KeyPrefix
SnsTopicName: !Sub arn:aws:sns:${AWS::Region}:${SecurityAccountId}:${AllConfigTopicName}
IsLogging: True
EnableLogFileValidation: !Ref EnableLogFileValidation
IncludeGlobalServiceEvents: !If
- IsMultiRegion
- True
- !Ref IncludeGlobalEvents
IsMultiRegionTrail: !Ref MultiRegion
CloudWatchLogsLogGroupArn: !If
- IsPublishToCloudWatchLogs
- !GetAtt TrailLogGroup.Arn
- !Ref AWS::NoValue
CloudWatchLogsRoleArn: !If
- IsPublishToCloudWatchLogs
- !GetAtt TrailLogGroupRole.Arn
- !Ref AWS::NoValue
TrailLogGroup:
Type: 'AWS::Logs::LogGroup'
Condition: IsPublishToCloudWatchLogs
Properties:
LogGroupName: !Sub ${ManagedResourcePrefix}/CloudTrailLogs
RetentionInDays: !Ref LogsRetentionInDays
TrailLogGroupRole:
Type: 'AWS::IAM::Role'
Condition: IsPublishToCloudWatchLogs
Properties:
RoleName: !Sub ${ManagedResourcePrefix}-CloudWatchLogsRole
AssumeRolePolicyDocument:
Version: '2012-10-17'
Statement:
- Sid: CloudTrailAssumeRole
Effect: Allow
Principal:
Service: 'cloudtrail.amazonaws.com'
Action: 'sts:AssumeRole'
Policies:
- PolicyName: 'cloudtrail-policy'
PolicyDocument:
Version: '2012-10-17'
Statement:
- Sid: AWSCloudTrailCreateLogStream
Effect: Allow
Action: 'logs:CreateLogStream'
Resource: !GetAtt 'TrailLogGroup.Arn'
- Sid: AWSCloudTrailPutLogEvents
Effect: Allow
Action: 'logs:PutLogEvents'
Resource: !GetAtt 'TrailLogGroup.Arn'
Outputs:
BaselineCloudTrail:
Description: Baseline CloudTrail
Value: !GetAtt 'Trail.Arn'
CloudWatchLogsGroupArn:
Description: CloudWatch Log Group ARN for Baseline CloudTrail
Value: !GetAtt 'TrailLogGroup.Arn'
CloudWatchLogsGroupName:
Description: CloudWatch Log Group Name for Baseline CloudTrail
Value: !Ref TrailLogGroup
AWSControlTowerBP-BASELINE-CLOUDWATCH
概要
LambdaとSNS。
configのルールに準拠していない場合は、子アカウントのLambdaを経由して
AuditアカウントのSNSに通知する
デフォルトではSNSの名前は下記になっている
aws-controltower-AggregateSecurityNotifications
デプロイ対象
下記のcontroltowerがサポートされている全リージョン
core ou
custome ou
cloudformation template
---
AWSTemplateFormatVersion: '2010-09-09'
Description: Configure Cloudwatch Rule, local SNS Topic, forwarding notifications from local SNS Topic to Security Topic
Parameters:
ManagedResourcePrefix:
Type: 'String'
Description: 'Prefix for the managed resources'
SecurityTopicName:
Type: String
Description: Security Notification SNS Topic Name.
SecurityAccountId:
Type: 'String'
Description: AWS Account Id of the Security account.
LogsRetentionInDays:
Description: 'Specifies the number of days you want to retain notification forwarding log events in the Lambda log group.'
Type: Number
Default: 14
AllowedValues: [1, 3, 5, 7, 14, 30, 60, 90, 120, 150, 180, 365, 400, 545, 731, 1827, 3653]
EnableConfigRuleComplianceChangeAlarm:
Type: String
Description: "Enable notifications for AWS Config rule compliance status changes?"
Default: true
AllowedValues:
- true
- false
Mappings:
TopicNameSuffix:
LocalTopicName:
Suffix: 'SecurityNotifications'
Conditions:
EnableConfigRuleChangeNotification: !Equals
- !Ref EnableConfigRuleComplianceChangeAlarm
- 'true'
Resources:
ForwardSnsNotification:
Type: 'AWS::Lambda::Function'
Properties:
FunctionName: !Sub ${ManagedResourcePrefix}-NotificationForwarder
Description: SNS message forwarding function for aggregating account notifications.
Code:
ZipFile:
!Sub |
from __future__ import print_function
import boto3
import json
import os
def lambda_handler(event, context):
#print("Received event: " + json.dumps(event, indent=2))
sns = boto3.client('sns')
subject=event['Records'][0]['Sns']['Subject']
if subject is None:
subject = 'None'
message = event['Records'][0]['Sns']['Message']
try:
msg = json.loads(message)
message = json.dumps(msg, indent=4)
if 'detail-type' in msg:
subject = msg['detail-type']
except:
print('Not json')
response = sns.publish(
TopicArn=os.environ.get('sns_arn'),
Subject=subject,
Message=message
)
print(response)
return response
Handler: 'index.lambda_handler'
MemorySize: 128
Role: !Sub arn:aws:iam::${AWS::AccountId}:role/${ManagedResourcePrefix}-ForwardSnsNotificationRole
Runtime: 'python3.6'
Timeout: 60
Environment:
Variables:
sns_arn: !Sub arn:aws:sns:${AWS::Region}:${SecurityAccountId}:${SecurityTopicName}
ForwardSnsNotificationGroup:
Type: 'AWS::Logs::LogGroup'
Properties:
LogGroupName: !Sub '/aws/lambda/${ForwardSnsNotification}'
RetentionInDays: !Ref LogsRetentionInDays
LocalSecurityTopic:
Type: AWS::SNS::Topic
Properties:
DisplayName: !Join [ "-", [ !Ref ManagedResourcePrefix, !FindInMap [TopicNameSuffix, LocalTopicName, Suffix] ]]
TopicName: !Join [ "-", [ !Ref ManagedResourcePrefix, !FindInMap [TopicNameSuffix, LocalTopicName, Suffix] ]]
SNSNotificationPolicy:
Type: AWS::SNS::TopicPolicy
Metadata:
cfn_nag:
rules_to_suppress:
- id: F18
reason: "Condition restricts permissions to current account."
Properties:
Topics:
- !Ref LocalSecurityTopic
PolicyDocument:
Statement:
- Sid: __default_statement_ID
Effect: Allow
Principal:
AWS: "*"
Action:
- SNS:GetTopicAttributes
- SNS:SetTopicAttributes
- SNS:AddPermission
- SNS:RemovePermission
- SNS:DeleteTopic
- SNS:Subscribe
- SNS:ListSubscriptionsByTopic
- SNS:Publish
- SNS:Receive
Resource: !Ref LocalSecurityTopic
Condition:
StringEquals:
AWS:SourceOwner: !Sub ${AWS::AccountId}
- Sid: TrustCWEToPublishEventsToMyTopic
Effect: Allow
Principal:
Service: events.amazonaws.com
Action: sns:Publish
Resource: !Ref LocalSecurityTopic
SNSNotificationSubscription:
Type: "AWS::SNS::Subscription"
Properties:
Endpoint: !GetAtt ForwardSnsNotification.Arn
Protocol: lambda
TopicArn: !Ref LocalSecurityTopic
SNSInvokeLambdaPermission:
Type: AWS::Lambda::Permission
Properties:
Action: lambda:InvokeFunction
Principal: sns.amazonaws.com
SourceArn: !Ref LocalSecurityTopic
FunctionName: !GetAtt ForwardSnsNotification.Arn
# Enable notifications for AWS Config Rule compliance changes
CWEventRuleComplianceChangeEvent:
Type: AWS::Events::Rule
Condition: EnableConfigRuleChangeNotification
Properties:
Name: !Sub ${ManagedResourcePrefix}-ConfigComplianceChangeEventRule
Description: 'CloudWatch Event Rule to send notification on Config Rule compliance changes.'
EventPattern:
{
"source": [
"aws.config"
],
"detail-type": [
"Config Rules Compliance Change"
]
}
State: ENABLED
Targets:
- Id: !Sub 'Compliance-Change-Topic'
Arn: !Ref LocalSecurityTopic
Outputs:
LocalSecurityTopic:
Description: Local Security Notification SNS Topic ARN
Value: !Ref LocalSecurityTopic
LocalSecurityTopicName:
Description: Local Security Notification SNS Topic Name
Value: !GetAtt LocalSecurityTopic.TopicName
AWSControlTowerBP-BASELINE-CONFIG
概要
configを有効化し、security(Audit)のアカウントにアグリゲーションする configの通知はsecurity(Audit)のアカウントの下記に通知する aws-controltower-AllConfigNotifications
デプロイ対象
下記のcontroltowerがサポートされている全リージョン
core ou
custome ou
cloudformation template
AWSTemplateFormatVersion: 2010-09-09
Description: Configure AWS Config
Parameters:
ManagedResourcePrefix:
Type: 'String'
Description: 'Prefix for the managed resources'
AllSupported:
Type: String
Default: 'true'
Description: Indicates whether to record all supported resource types.
AllowedValues:
- 'true'
- 'false'
IncludeGlobalResourceTypes:
Type: String
Default: 'true'
Description: Indicates whether AWS Config records all supported global resource types.
AllowedValues:
- 'true'
- 'false'
ResourceTypes:
Type: CommaDelimitedList
Description: A list of valid AWS resource types to include in this recording group. Eg. AWS::CloudTrail::Trail
Frequency:
Type: String
Default: 1hour
Description: The frequency with which AWS Config delivers configuration snapshots.
AllowedValues:
- 1hour
- 3hours
- 6hours
- 12hours
- 24hours
AllConfigTopicName:
Type: String
Default: ''
Description: All Configuration Notification SNS Topic in Security Account that AWS Config delivers notifications to.
SecurityAccountId:
Type: 'String'
Description: AWS Account Id of the Security account.
AuditBucketName:
Type: String
Default: ''
Description: Audit Bucket name from the Log Archive Account
AWSLogsS3KeyPrefix:
Type: 'String'
Description: Organization ID to use as the S3 Key prefix for storing the audit logs
HomeRegionName:
Type: 'String'
Description: The name of the home region for the customer
IsHomeRegionInitialControlTowerRegion:
Type: 'String'
AllowedValues:
- 'true'
- 'false'
Description: Indicates whether the Home Region of the customer is one of the initial regions in which AWS Control Tower launched.
Conditions:
IsAllSupported: !Equals
- !Ref AllSupported
- 'true'
CreateHomeRegionConfigAggregatorAuthorization: !Equals
- !Ref IsHomeRegionInitialControlTowerRegion
- 'false'
CreateRegionalConfigAggregatorAuthorization: !Equals
- !Ref IsHomeRegionInitialControlTowerRegion
- 'true'
Mappings:
Settings:
FrequencyMap:
1hour : One_Hour
3hours : Three_Hours
6hours : Six_Hours
12hours : Twelve_Hours
24hours : TwentyFour_Hours
Resources:
ConfigRecorder:
Type: AWS::Config::ConfigurationRecorder
Properties:
Name: !Sub ${ManagedResourcePrefix}-BaselineConfigRecorder
RoleARN: !Sub arn:aws:iam::${AWS::AccountId}:role/${ManagedResourcePrefix}-ConfigRecorderRole
RecordingGroup:
AllSupported: !Ref AllSupported
IncludeGlobalResourceTypes: !Ref IncludeGlobalResourceTypes
ResourceTypes: !If
- IsAllSupported
- !Ref AWS::NoValue
- !Ref ResourceTypes
ConfigDeliveryChannel:
Type: AWS::Config::DeliveryChannel
Properties:
Name: !Sub ${ManagedResourcePrefix}-BaselineConfigDeliveryChannel
ConfigSnapshotDeliveryProperties:
DeliveryFrequency: !FindInMap
- Settings
- FrequencyMap
- !Ref Frequency
S3BucketName: !Ref AuditBucketName
S3KeyPrefix: !Ref AWSLogsS3KeyPrefix
SnsTopicARN: !Sub arn:aws:sns:${AWS::Region}:${SecurityAccountId}:${AllConfigTopicName}
AuthorizerPdx:
Condition: CreateRegionalConfigAggregatorAuthorization
Type: "AWS::Config::AggregationAuthorization"
Properties:
AuthorizedAccountId: !Ref SecurityAccountId
AuthorizedAwsRegion: us-west-2
AuthorizerIad:
Condition: CreateRegionalConfigAggregatorAuthorization
Type: "AWS::Config::AggregationAuthorization"
Properties:
AuthorizedAccountId: !Ref SecurityAccountId
AuthorizedAwsRegion: us-east-1
AuthorizerCmh:
Condition: CreateRegionalConfigAggregatorAuthorization
Type: "AWS::Config::AggregationAuthorization"
Properties:
AuthorizedAccountId: !Ref SecurityAccountId
AuthorizedAwsRegion: us-east-2
AuthorizerDub:
Condition: CreateRegionalConfigAggregatorAuthorization
Type: "AWS::Config::AggregationAuthorization"
Properties:
AuthorizedAccountId: !Ref SecurityAccountId
AuthorizedAwsRegion: eu-west-1
AuthorizerSyd:
Condition: CreateRegionalConfigAggregatorAuthorization
Type: "AWS::Config::AggregationAuthorization"
Properties:
AuthorizedAccountId: !Ref SecurityAccountId
AuthorizedAwsRegion: ap-southeast-2
HomeRegionAuthorizer:
Condition: CreateHomeRegionConfigAggregatorAuthorization
Type: "AWS::Config::AggregationAuthorization"
Properties:
AuthorizedAccountId: !Ref SecurityAccountId
AuthorizedAwsRegion: !Ref HomeRegionName
Outputs:
BaselineConfigRecorder:
Description: Baseline Config Recorder
Value: !Ref ConfigRecorder
BaselineConfigDeliveryChannel:
Description: Baseline Config Delivery Channel
Value: !Ref ConfigDeliveryChannel
AWSControlTowerBP-BASELINE-ROLES
概要
Auditのアカウントからスイッチロールが可能なよう
readonlyとadminの2種類のroleを作成する
デプロイ対象
下記のcontroltowerが有効化された単一リージョン
core ou
custome ou
cloudformation template
AWSTemplateFormatVersion: 2010-09-09
Description: Configure the Cross-Account IAM Security Roles for the member accounts.
Parameters:
ManagedResourcePrefix:
Type: 'String'
Description: 'Prefix for the managed resources'
SecurityAccountAdminRoleArn:
Type: String
Description: Admin role ARN from the security account.
SecurityAccountReadOnlyRoleArn:
Type: String
Description: Admin role ARN from the security account.
EnableAdminRole:
Type: String
Default: 'true'
Description: Create an administrative cross-account role from Security Account to this account.
AllowedValues:
- 'true'
- 'false'
EnableReadOnlyRole:
Type: String
Default: 'true'
Description: Create a read-only cross-account role from Security Account to this account.
AllowedValues:
- 'true'
- 'false'
Conditions:
CreateAdminRole: !Equals
- !Ref EnableAdminRole
- 'true'
CreateReadOnlyRole: !Equals
- !Ref EnableReadOnlyRole
- 'true'
Resources:
AdminExecutionRole:
Type: AWS::IAM::Role
Condition: CreateAdminRole
Properties:
RoleName: !Sub ${ManagedResourcePrefix}-AdministratorExecutionRole
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Principal:
AWS:
- !Ref SecurityAccountAdminRoleArn
Action:
- sts:AssumeRole
Path: /
ManagedPolicyArns:
- arn:aws:iam::aws:policy/AdministratorAccess
ReadOnlyExecutionRole:
Type: AWS::IAM::Role
Condition: CreateReadOnlyRole
Properties:
RoleName: !Sub ${ManagedResourcePrefix}-ReadOnlyExecutionRole
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Principal:
AWS:
- !Ref SecurityAccountReadOnlyRoleArn
Action:
- sts:AssumeRole
Path: /
ManagedPolicyArns:
- arn:aws:iam::aws:policy/ReadOnlyAccess
AWSControlTowerBP-BASELINE-SERVICE-ROLES
概要
AWSControlTowerBP-BASELINE-CLOUDWATCH
の実行に必要なlambdaとconfig用のロールを作成する
デプロイ対象
下記のcontroltowerが有効化された単一リージョン core ou custome ou
cloudformation template
AWSTemplateFormatVersion: 2010-09-09
Description: Configure AWS Config and SNS Notification Forward IAM Roles
Parameters:
ManagedResourcePrefix:
Type: 'String'
Description: 'Prefix for the managed resources'
SecurityTopicName:
Type: String
Description: Security Notification SNS Topic Name.
SecurityAccountId:
Type: 'String'
Description: AWS Account Id of the Security account.
Resources:
ConfigRecorderRole:
Type: AWS::IAM::Role
Properties:
RoleName: !Sub ${ManagedResourcePrefix}-ConfigRecorderRole
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Principal:
Service:
- config.amazonaws.com
Action:
- sts:AssumeRole
Path: /
ManagedPolicyArns:
- arn:aws:iam::aws:policy/service-role/AWSConfigRole
- arn:aws:iam::aws:policy/ReadOnlyAccess
ForwardSnsNotificationLambdaRole:
Type: 'AWS::IAM::Role'
Properties:
RoleName: !Sub ${ManagedResourcePrefix}-ForwardSnsNotificationRole
AssumeRolePolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Principal:
Service: 'lambda.amazonaws.com'
Action:
- 'sts:AssumeRole'
Path: '/'
ManagedPolicyArns:
- 'arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole'
Policies:
- PolicyName: sns
PolicyDocument:
Statement:
- Effect: Allow
Action:
- 'sns:publish'
Resource: !Sub arn:aws:sns:*:${SecurityAccountId}:${SecurityTopicName}
Outputs:
BaselineConfigRole:
Description: Baseline Config Role
Value: !GetAtt 'ConfigRecorderRole.Arn'
AWSControlTowerBP-SECURITY-TOPICS
概要
SNSのtopicを2つ作成する
AggregateSecurityNotifications
AllConfigNotifications
各アカウントで何かあったときの受け口となるSNS Topic
対象
下記のcontroltowerがサポートされている全リージョン audit
cloudformation template
AWSTemplateFormatVersion: 2010-09-09
Description: Configure the SNS Topics for Security Account
Parameters:
ManagedResourcePrefix:
Type: 'String'
Description: 'Prefix for the managed resources'
AllConfigurationEmail:
Type: 'String'
Description: Email for receiving all AWS configuration events
SecurityNotificationEmail:
Type: 'String'
Description: Email for the security administrator(s)
OrgID:
Type: 'String'
Description: AWS Organizations ID to allow notifications from member accounts
SubscribeToAllConfigurationTopic:
Type: String
Default: false
Description: Indicates whether AllConfigurationEmail will be subscribed to the AllConfigurationTopicName topic.
AllowedValues:
- true
- false
Conditions:
Subscribe: !Equals
- !Ref SubscribeToAllConfigurationTopic
- 'true'
Mappings:
TopicNameSuffix:
AllConfigurationTopicName:
Suffix: 'AllConfigNotifications'
NotifyTopicName:
Suffix: 'AggregateSecurityNotifications'
Resources:
SNSAllConfigurationTopic:
Type: AWS::SNS::Topic
Properties:
DisplayName: !Join [ "-", [ !Ref ManagedResourcePrefix, !FindInMap [TopicNameSuffix, AllConfigurationTopicName, Suffix] ]]
TopicName: !Join [ "-", [ !Ref ManagedResourcePrefix, !FindInMap [TopicNameSuffix, AllConfigurationTopicName, Suffix] ]]
SNSAllConfigurationTopicPolicy:
Type: AWS::SNS::TopicPolicy
Properties:
Topics:
- !Ref SNSAllConfigurationTopic
PolicyDocument:
Statement:
- Sid: AWSSNSPolicy
Action:
- sns:Publish
Effect: Allow
Resource: !Ref SNSAllConfigurationTopic
Principal:
Service:
- cloudtrail.amazonaws.com
- config.amazonaws.com
SNSAllConfigurationEmailNotification:
Condition: Subscribe
Type: AWS::SNS::Subscription
Properties:
Endpoint: !Ref AllConfigurationEmail
Protocol: email
TopicArn: !Ref SNSAllConfigurationTopic
SNSNotification:
Type: AWS::SNS::Topic
Properties:
DisplayName: !Join [ "-", [ !Ref ManagedResourcePrefix, !FindInMap [TopicNameSuffix, NotifyTopicName, Suffix] ]]
TopicName: !Join [ "-", [ !Ref ManagedResourcePrefix, !FindInMap [TopicNameSuffix, NotifyTopicName, Suffix] ]]
Subscription:
- Protocol: email
Endpoint: !Ref SecurityNotificationEmail
SNSNotificationPolicy:
Type: AWS::SNS::TopicPolicy
Metadata:
cfn_nag:
rules_to_suppress:
- id: F18
reason: "Conditions restrict permissions to Organization account and publishing only to member accounts."
Properties:
Topics:
- !Ref SNSNotification
PolicyDocument:
Statement:
- Sid: __default_statement_ID
Effect: Allow
Principal:
AWS: "*"
Action:
- SNS:GetTopicAttributes
- SNS:SetTopicAttributes
- SNS:AddPermission
- SNS:RemovePermission
- SNS:DeleteTopic
- SNS:Subscribe
- SNS:ListSubscriptionsByTopic
- SNS:Publish
- SNS:Receive
Resource: !Ref SNSNotification
Condition:
StringEquals:
AWS:SourceOwner: !Sub ${AWS::AccountId}
- Sid: AWSSNSPolicy
Effect: Allow
Principal:
AWS: "*"
Action: sns:Publish
Resource: !Ref SNSNotification
Condition:
StringEquals:
aws:PrincipalOrgID: !Ref OrgID
Outputs:
SecurityTopicARN:
Description: Security Notification SNS Topic ARN
Value: !Ref SNSNotification
SecurityTopicName:
Description: Security Notification SNS Topic Name
Value: !GetAtt SNSNotification.TopicName
AllConfigTopicARN:
Description: All Configuration Notification SNS Topic ARN
Value: !Ref SNSAllConfigurationTopic
AllConfigTopicName:
Description: All Configuration Notification SNS Topic Name
Value: !GetAtt SNSAllConfigurationTopic.TopicName
AWSControlTowerGuardrailAWS-GR-AUDIT-BUCKET-PUBLIC-READ-PROHIBITED
概要
config ruleを作成する
ルール:S3_BUCKET_PUBLIC_READ_PROHIBITED
デプロイ対象
下記のcontroltowerがサポートされている全リージョン
Log archive
audit
cloudformation template
AWSTemplateFormatVersion: 2010-09-09
Description: Configure AWS Config rules to check that your S3 buckets do not allow public access
Parameters:
ConfigRuleName:
Type: 'String'
Description: 'Name for the Config rule'
Resources:
CheckForS3PublicRead:
Type: AWS::Config::ConfigRule
Properties:
ConfigRuleName: !Sub ${ConfigRuleName}
Description: Checks that your S3 buckets do not allow public read access. If an S3 bucket policy or bucket ACL allows public read access, the bucket is noncompliant.
Source:
Owner: AWS
SourceIdentifier: S3_BUCKET_PUBLIC_READ_PROHIBITED
Scope:
ComplianceResourceTypes:
- AWS::S3::Bucket
AWSControlTowerGuardrailAWS-GR-AUDIT-BUCKET-PUBLIC-WRITE-PROHIBITED
概要
config ruleを作成する
ルール:S3_BUCKET_PUBLIC_WRITE_PROHIBITED
デプロイ対象
下記のcontroltowerがサポートされている全リージョン
Log archive
audit
AWSTemplateFormatVersion: 2010-09-09
Description: Configure AWS Config rules to check that your S3 buckets do not allow public access
Parameters:
ConfigRuleName:
Type: 'String'
Description: 'Name for the Config rule'
Resources:
CheckForS3PublicWrite:
Type: AWS::Config::ConfigRule
Properties:
ConfigRuleName: !Sub ${ConfigRuleName}
Description: Checks that your S3 buckets do not allow public write access. If an S3 bucket policy or bucket ACL allows public write access, the bucket is noncompliant.
Source:
Owner: AWS
SourceIdentifier: S3_BUCKET_PUBLIC_WRITE_PROHIBITED
Scope:
ComplianceResourceTypes:
- AWS::S3::Bucket
AWSControlTowerLoggingResources
概要
バケットを2つ作成する
1つはaudit。ここに他アカウントからのconfigやtrail結果が書き込まれる
2つ目は上記のs3へのアクセスログを記録するためのバケット
デプロイ対象
下記のcontroltowerが有効化された単一リージョン
Log archive
cloudformation template
AWSTemplateFormatVersion: 2010-09-09
Description: Configure an Audit S3 bucket for the Log Archive account.
Parameters:
SSEAlgorithm:
Type: 'String'
Default: 'AES256'
Description: S3 bucket SSE Algorithm.
AllowedValues:
- 'AES256'
- 'aws:kms'
KMSMasterKeyID:
Type: 'String'
Description: 'KMS key ID required if SSE algorithm is aws:kms.'
ManagedResourcePrefix:
Type: 'String'
Description: 'Prefix for the managed resources'
RetentionDays:
Type: String
Description: 'No of Days to retain the logs, after which it will be permanently deleted'
TransitionToGlacier:
Type: String
Description: 'Do you wish to transition the logs to Glacier before permanently deleting?'
Default: 'No'
AllowedValues:
- 'Yes'
- 'No'
TransitionDays:
Type: String
Description: 'No of Days to transition the data from S3 to Glacier'
AWSLogsS3KeyPrefix:
Type: 'String'
Description: 'Organization ID to use as the S3 Key prefix for storing the audit logs'
Conditions:
UseKMS: !Equals
- !Ref SSEAlgorithm
- 'aws:kms'
MoveToGlacier: !Equals
- !Ref TransitionToGlacier
- 'Yes'
Resources:
# Create S3 Server Access Logging bucket
S3LoggingBucket:
DeletionPolicy: Retain
Type: AWS::S3::Bucket
Properties:
BucketName: !Sub ${ManagedResourcePrefix}-s3-access-logs-${AWS::AccountId}-${AWS::Region}
AccessControl: LogDeliveryWrite
VersioningConfiguration:
Status: Enabled
BucketEncryption:
ServerSideEncryptionConfiguration:
- !If
- UseKMS
- ServerSideEncryptionByDefault:
SSEAlgorithm: !Ref SSEAlgorithm
KMSMasterKeyID: !Ref KMSMasterKeyID
- ServerSideEncryptionByDefault:
SSEAlgorithm: !Ref SSEAlgorithm
# Create S3 Audit bucket
S3AuditBucket:
DeletionPolicy: Retain
Type: AWS::S3::Bucket
Properties:
BucketName: !Sub ${ManagedResourcePrefix}-logs-${AWS::AccountId}-${AWS::Region}
VersioningConfiguration:
Status: Enabled
LoggingConfiguration:
DestinationBucketName: !Ref S3LoggingBucket
BucketEncryption:
ServerSideEncryptionConfiguration:
- !If
- UseKMS
- ServerSideEncryptionByDefault:
SSEAlgorithm: !Ref SSEAlgorithm
KMSMasterKeyID: !Ref KMSMasterKeyID
- ServerSideEncryptionByDefault:
SSEAlgorithm: !Ref SSEAlgorithm
LifecycleConfiguration:
Rules:
- !If
- MoveToGlacier
- Id: RetentionRule
Status: Enabled
ExpirationInDays: !Ref RetentionDays
NoncurrentVersionExpirationInDays: !Ref RetentionDays
Transitions:
- TransitionInDays: !Ref TransitionDays
StorageClass: Glacier
NoncurrentVersionTransitions:
- TransitionInDays: !Ref TransitionDays
StorageClass: Glacier
- Id: RetentionRule
Status: Enabled
ExpirationInDays: !Ref RetentionDays
NoncurrentVersionExpirationInDays: !Ref RetentionDays
# Create Bucket Policy for S3 Audit bucket
S3AuditBucketPolicy:
Type: AWS::S3::BucketPolicy
Properties:
Bucket: !Ref S3AuditBucket
PolicyDocument:
Version: 2012-10-17
Statement:
- Sid: AWSBucketPermissionsCheck
Effect: Allow
Principal:
Service:
- cloudtrail.amazonaws.com
- config.amazonaws.com
Action: s3:GetBucketAcl
Resource:
- !Sub "arn:aws:s3:::${S3AuditBucket}"
- Sid: AWSBucketDelivery
Effect: Allow
Principal:
Service:
- cloudtrail.amazonaws.com
- config.amazonaws.com
Action: s3:PutObject
Resource:
- Fn::Join:
- ""
-
- "arn:aws:s3:::"
- !Ref "S3AuditBucket"
- !Sub "/${AWSLogsS3KeyPrefix}/AWSLogs/*/*"
Outputs:
BucketName:
Description: Audit S3 bucket name
Value: !Ref S3AuditBucket
LoggingBucketName:
Description: S3 Access Logging Bucket name
Value: !Ref S3LoggingBucket
AuditLogsS3KeyPrefix:
Description: S3 Key prefix for storing the audit logs
Value: !Ref AWSLogsS3KeyPrefix
AWSControlTowerSecurityResources
概要
Lambda実行用のロール(adminとreadonlyの2つ)
対象
下記のcontroltowerが有効化された単一リージョン
audit
cloudformation template
AWSTemplateFormatVersion: 2010-09-09
Description: Configure the Cross-Account IAM Audit Roles for Audit Account
Parameters:
ManagedResourcePrefix:
Type: 'String'
Description: 'Prefix for the managed resources'
AuditAccountId:
Type: 'String'
Description: 'Audit account Id'
LoggingAccountId:
Type: 'String'
Description: 'Logging account Id'
Resources:
AdministrationRole:
Type: AWS::IAM::Role
Properties:
RoleName: !Sub ${ManagedResourcePrefix}-AuditAdministratorRole
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Principal:
Service: lambda.amazonaws.com
Action:
- sts:AssumeRole
Path: /
ManagedPolicyArns:
- arn:aws:iam::aws:policy/AWSLambdaExecute
Policies:
- PolicyName: !Sub AssumeRole-${ManagedResourcePrefix}-AuditAdministratorRole
PolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Action:
- sts:AssumeRole
Resource:
- !Sub "arn:aws:iam::*:role/${ManagedResourcePrefix}-AdministratorExecutionRole"
ReadOnlyRole:
Type: AWS::IAM::Role
Properties:
RoleName: !Sub ${ManagedResourcePrefix}-AuditReadOnlyRole
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Principal:
Service: lambda.amazonaws.com
Action:
- sts:AssumeRole
Path: /
ManagedPolicyArns:
- arn:aws:iam::aws:policy/AWSLambdaExecute
Policies:
- PolicyName: !Sub AssumeRole-${ManagedResourcePrefix}-AuditReadOnlyRole
PolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Action:
- sts:AssumeRole
Resource:
- !Sub "arn:aws:iam::*:role/${ManagedResourcePrefix}-ReadOnlyExecutionRole"
# AWSConfig Aggregator for Guardrail compliance
GuardrailsComplianceAggregator:
Type: AWS::Config::ConfigurationAggregator
Properties:
AccountAggregationSources:
- AccountIds:
- !Ref AuditAccountId
- !Ref LoggingAccountId
AllAwsRegions: true
ConfigurationAggregatorName: !Sub ${ManagedResourcePrefix}-GuardrailsComplianceAggregator
Outputs:
CrossAccountAdminRole:
Description: Audit Administrator Role
Value: !GetAtt 'AdministrationRole.Arn'
CrossAccountReadOnlyRole:
Description: Audit ReadOnly Role
Value: !GetAtt 'ReadOnlyRole.Arn'
最後に
役に立った人がいれば褒めて欲しい。。。。
Organization管理は、自社の管理しか深く関わらず、
サンプル数が少ないので
他の詳しい人の考え方も聞きたいと思う事がよくあります。
何かあればコメント頂けると嬉しいです。