こんにちは。SCSK渡辺(大)です。
今回は、
AWS Organizationsを使用できない場合にAWS Configを全リージョンで有効化する方法
を考えてみました。
背景
AWSアカウントのセキュリティ監視をしたい
AWSアカウントのセキュリティ監視をしたいとなった場合、AWS Security Hubを利用することが候補に挙がるかと思います。
AWS Security Hubを利用するための前提として、AWS Configを有効化している必要があります。
AWS Configのベストプラクティスには以下のように書かれています。
AWS Config ベストプラクティス | Amazon Web Services ブログ
—抜粋—————————————————————
1.すべてのアカウントとリージョンで AWS Config を有効にします。
これは、 Center for Internet Security (CIS) が推奨する業界のベストプラクティスです。AWS Config を使用すると、AWS リソースの設定を監査し、設定のベストプラクティスに確実に準拠することができます。 AWS CloudFormation StackSets を使用すると、共通の CloudFormation テンプレートを使用して、複数のアカウントとリージョンで AWS Config を有効にできます。
———————————————————————-
上記の通り、AWS CloudFormation StackSetsを使用することで複数アカウントとリージョンでAWS Configを有効にできます。
AWS CloudFormation StackSetsには2種類あります。
- セルフマネージド型 : AWS Organizationsを使えなくても問題ありません
- サービスマネージド型: AWS Organizationsを使えることが前提です
今回はAWS Organizationsを使用できない場合を想定しているため、セルフマネージド型を利用します。
セルフマネージド許可を持つ CloudFormation StackSets を作成する – AWS CloudFormation
上記リンク先にAWS Configを有効化するためのAWS CloudFormationテンプレートが用意されていますが、自分が作りたい構成には過剰だったため、オリジナルのAWS CloudFormationテンプレート(以降、Cfnテンプレート)を作ることにしました。
余談
ちなみに、「利用しないリージョンは無効化にしておけばセキュリティ監視が不要になるから、使用するリージョンだけ有効化して、AWS Management ConsoleからAWS Configを有効化するならそこまで手間ではないのでは?」と一度は考えましたが、悲しいことに、デフォルトで有効になっているリージョンは無効にすることはできません。
デフォルトで有効になっているリージョンは記事執筆時点で17個ありますので、仮に監視対象のAWSアカウントが10個あったとしたら、AWS Management Consoleでリージョン切替とAWS Config有効化を170回繰り返す必要があります…。
アーキテクチャ
AWSアカウント
今回は2つのアカウントを用意しました。
- AWS Configアグリゲータアカウント(以降、アグリゲータアカウント)
- AWS Configソースアカウント(以降、ソースアカウント)
使用するサービス
以下のサービスを使用します。
- Amazon S3
- AWS CloudFormation
作業内容
以下の作業を実施します。
- From:アグリゲータアカウント、To:アグリゲータアカウント
- AWSマネジメントコンソールからAmazon S3バケットを作成し、AWS CloudFormationテンプレート(以降、Cfnテンプレート)をアップロードする
- AWS CloudFormationでAWS CloudFormation StackSets セルフマネージド型用のIAMロールを作成する
- AWS CloudFormationでAWS Configの配信先(Amazon S3バケット)を作成する
- AWS CloudFormationでAWS Config用のIAMロールを作成する
- From:ソースアカウント、To:ソースアカウント
- AWS CloudFormationでAWS CloudFormation StackSets セルフマネージド型用のIAMロールを作成する
- AWS CloudFormationでAWS Config用のIAMロール、を作成する
- From:アグリゲータアカウント、To:ソースアカウント
- AWS CloudFormation StackSets セルフマネージド型でAWS Configを有効化にする
- From:ソースアカウント、To:アグリゲータアカウント
- AWS CloudFormation StackSets セルフマネージド型でAWS Configを有効化にする
構成図
上記の設計を図にすると以下になります。
事前作業
Amazon S3バケットにCfnテンプレートをアップロードします。
ゴールは下図のようにアップロードされていることです。

Amazon S3バケット作成
作業実施アカウント
- アグリゲータアカウント
推奨設定
- ブロックパブリックアクセスを有効化
- ソースアカウントからもGetObjectできるようにバケットポリシーを設定する
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::${ソースアカウントのAWSID}:root"
},
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::${S3バケット名}/*"
}
]
}
配置するCfnテンプレートは次の通りです。
Cfnテンプレート: AWSCloudFormationStackSetAdministrationRole
AWS CloudFormation StackSets セルフマネージド型で別アカウントにリソースを作成することが出来るようにするためのAWS IAMローカルを作成します。(AWSユーザーガイドからダウンロードできます)
AWSTemplateFormatVersion: 2010-09-09
Description: Configure the AWSCloudFormationStackSetAdministrationRole to enable use of AWS CloudFormation StackSets.
Parameters:
AdministrationRoleName:
Type: String
Default: AWSCloudFormationStackSetAdministrationRole
Description: "The name of the administration role. Defaults to 'AWSCloudFormationStackSetAdministrationRole'."
ExecutionRoleName:
Type: String
Default: AWSCloudFormationStackSetExecutionRole
Description: "The name of the execution role that can assume this role. Defaults to 'AWSCloudFormationStackSetExecutionRole'."
Resources:
AdministrationRole:
Type: AWS::IAM::Role
Properties:
RoleName: !Ref AdministrationRoleName
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Principal:
Service: cloudformation.amazonaws.com
Action:
- sts:AssumeRole
Path: /
Policies:
- PolicyName: AssumeRole-AWSCloudFormationStackSetExecutionRole
PolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Action:
- sts:AssumeRole
Resource:
- !Sub 'arn:*:iam::*:role/${ExecutionRoleName}'
Cfnテンプレート: AWSCloudFormationStackSetExecutionRole
AWS CloudFormation StackSets セルフマネージド型で別アカウントからリソースを作成することが出来るようにするためのAWS IAMロールを作成します。(AWSユーザーガイドからダウンロードできます)
AWSTemplateFormatVersion: 2010-09-09
Description: Configure the AWSCloudFormationStackSetExecutionRole to enable use of your account as a target account in AWS CloudFormation StackSets.
Parameters:
AdministratorAccountId:
Type: String
Description: AWS Account Id of the administrator account (the account in which StackSets will be created).
MaxLength: 12
MinLength: 12
ExecutionRoleName:
Type: String
Default: AWSCloudFormationStackSetExecutionRole
Description: "The name of the execution role. Defaults to 'AWSCloudFormationStackSetExecutionRole'."
Resources:
ExecutionRole:
Type: AWS::IAM::Role
Properties:
RoleName: !Ref ExecutionRoleName
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Principal:
AWS:
- !Ref AdministratorAccountId
Action:
- sts:AssumeRole
Path: /
ManagedPolicyArns:
- !Sub arn:${AWS::Partition}:iam::aws:policy/AdministratorAccess
Cfnテンプレート: PreAWSConfigAggregator
アグリゲータアカウントで集約するアグリゲータアカウント自身およびソースアカウントのAWS Configデータを集約するためのAmazon S3バケットを作成します。また、アグリゲータアカウント自身のAWS Config用のAWS IAMロールを作成します。
AWSTemplateFormatVersion: "2010-09-09"
Parameters:
AdministratorAccountS3Bucket:
Description: AWS account S3Bucket of the administrator account (security monitoring administrator account)
Type: String
OrganizationID:
Description: Organization ID
Type: String
Resources:
ConfigBucket:
DeletionPolicy: Retain
Type: AWS::S3::Bucket
Properties:
BucketName: !Ref AdministratorAccountS3Bucket
BucketEncryption:
ServerSideEncryptionConfiguration:
- ServerSideEncryptionByDefault:
SSEAlgorithm: AES256
ConfigBucketPolicy:
Type: AWS::S3::BucketPolicy
Properties:
Bucket: !Ref ConfigBucket
PolicyDocument:
Version: 2012-10-17
Statement:
- Sid: AWSConfigBucketPermissionsCheck
Effect: Allow
Principal: "*"
Action: s3:GetBucketAcl
Resource: !Sub "arn:${AWS::Partition}:s3:::${ConfigBucket}"
Condition:
StringEquals:
"aws:PrincipalOrgID": !Ref OrganizationID
- Sid: AWSConfigBucketExistenceCheck
Effect: Allow
Principal: "*"
Action: s3:ListBucket
Resource: !Sub "arn:${AWS::Partition}:s3:::${ConfigBucket}"
Condition:
StringEquals:
"aws:PrincipalOrgID": !Ref OrganizationID
- Sid: AWSConfigBucketDelivery
Effect: Allow
Principal: "*"
Action: s3:PutObject
Resource: !Sub "arn:${AWS::Partition}:s3:::${ConfigBucket}/AWSLogs/*/Config/*"
Condition:
StringEquals:
"s3:x-amz-acl": "bucket-owner-full-control"
"aws:PrincipalOrgID": !Ref OrganizationID
- Sid: AWSConfigBucketSecureTransport
Effect: Deny
Principal: "*"
Action:
- s3:*
Resource:
- !Sub "arn:${AWS::Partition}:s3:::${ConfigBucket}"
- !Sub "arn:${AWS::Partition}:s3:::${ConfigBucket}/*"
Condition:
Bool:
aws:SecureTransport: false
ConfigRole:
Type: AWS::IAM::Role
Properties:
RoleName: AWSConfigCustomRole
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Principal:
Service: config.amazonaws.com
Action: "sts:AssumeRole"
ManagedPolicyArns:
- arn:aws:iam::aws:policy/service-role/AWS_ConfigRole
Outputs:
ConfigBucketName:
Description: Name of the S3 bucket for AWS Config data
Value: !Ref ConfigBucket
ConfigRoleArn:
Description: ARN of the IAM role for AWS Config
Value: !GetAtt ConfigRole.Arn
Cfnテンプレート: PreAWSConfigSource
ソースアカウント自身のAWS Config用のAWS IAMロールを作成します。
AWSTemplateFormatVersion: "2010-09-09"
Parameters:
AdministratorAccountS3Bucket:
Description: AWS account S3Bucket of the administrator account (security monitoring administrator account)
Type: String
Resources:
ConfigRole:
Type: AWS::IAM::Role
Properties:
RoleName: AWSConfigCustomRole
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Principal:
Service: config.amazonaws.com
Action: "sts:AssumeRole"
ManagedPolicyArns:
- arn:aws:iam::aws:policy/service-role/AWS_ConfigRole
Policies:
- PolicyName: ConfigS3BucketAccess
PolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Action:
- "s3:PutObject"
- "s3:PutObjectAcl"
Resource:
- !Sub "arn:aws:s3:::${AdministratorAccountS3Bucket}/AWSLogs/*"
Condition:
StringLike:
"s3:x-amz-acl": "bucket-owner-full-control"
- Effect: Allow
Action:
- "s3:GetBucketAcl"
Resource: "arn:aws:s3:::${AdministratorAccountS3Bucket}"
Outputs:
ConfigRoleArn:
Description: ARN of the IAM role for AWS Config
Value: !GetAtt ConfigRole.Arn
Cfnテンプレート: EnableAWSConfig
アグリゲータアカウントまたはソースアカウントでAWS Configを有効化にします。
AWSTemplateFormatVersion: "2010-09-09"
Conditions:
IncludeGlobalResourceRegion: !Equals [!Ref AWS::Region, us-east-1]
Parameters:
AdministratorAccountS3Bucket:
Description: AWS account S3Bucket of the administrator account (security monitoring administrator account)
Type: String
Resources:
ConfigRecorder:
Type: AWS::Config::ConfigurationRecorder
Properties:
Name: !Sub "config-${AWS::AccountId}"
RecordingGroup:
AllSupported: true
IncludeGlobalResourceTypes:
!If [IncludeGlobalResourceRegion, true, false]
RoleARN: !Sub arn:aws:iam::${AWS::AccountId}:role/AWSConfigCustomRole
ConfigDeliveryChannel:
Type: AWS::Config::DeliveryChannel
Properties:
Name: !Sub "config-${AWS::AccountId}"
S3BucketName: !Ref AdministratorAccountS3Bucket
ConfigSnapshotDeliveryProperties:
DeliveryFrequency: TwentyFour_Hours
Outputs:
ConfigRecorderName:
Description: Name of the AWS Config Recorder
Value: !Ref ConfigRecorder
DeliveryChannelName:
Description: Name of the AWS Config Delivery Channel
Value: !Ref ConfigDeliveryChannel
余談
本記事では説明のためにCfnテンプレートを分けていますが、AWSCloudFormationStackSetAdministrationRoleとAWSCloudFormationStackSetExecutionRoleはPreAWSConfigAggregatorやPreAWSConfigSourceにまとめることが出来ると思います。
設定作業
AWS CloudFormationで設定していきます。
Cfnテンプレート: AWSCloudFormationStackSetAdministrationRole
作業実施アカウント
- アグリゲータアカウント
- ソースアカウント
パラメーター
- 何も変更しません
確認画面
- 下図のようになっていればOKです
Cfnテンプレート: AWSCloudFormationStackSetExecutionRole
作業実施アカウント
- アグリゲータアカウント
- ソースアカウント
パラメーター
- AdministratorAccountIdを設定します
- アグリゲータアカウント側ではソースアカウントAWSIDを設定します
- ソースアカウント側ではアグリゲータアカウントAWSIDを設定します
確認画面
Cfnテンプレート: PreAWSConfigAggregator
作業実施アカウント
- アグリゲータアカウント
パラメーター
- AdministratorAccountS3Bucketを設定します
- 任意の名前で設定します(AWSの全てのリージョンにわたって一意である必要があります)
- OrganizationID(組織ID)を設定します
確認画面
Cfnテンプレート: PreAWSConfigSource
作業実施アカウント
- ソースアカウント
パラメーター
- AdministratorAccountS3Bucketを設定します
- PreAWSConfigAggregatorで設定した名前を指定します
確認画面
Cfnテンプレート: EnableAWSConfig
これまでのCfnテンプレートとは異なり、AWS CloudFormation StackSets セルフマネージド型で実行します。
作業実施アカウント
- アグリゲータアカウント
- ソースアカウント
パラメーター
- アグリゲータアカウントとソースアカウントとも共通で、AdministratorAccountS3Bucketを設定します
- PreAWSConfigAggregatorで設定した名前を指定します
作業画面
- 基本的にはアグリゲータアカウントとソースアカウントとも共通です。
- リージョンを指定します。
以下は有効化になっている全てのリージョンに対してAWS Configを有効化する場合の設定方法です。
まず、有効化になっているリージョンを確認します。
画面右上のログインユーザーをクリックした後に「アカウント」をクリックすると見れます。
確認画面
以上です。
ソースアカウントを追加したい時はどうしたら良いの?
追加したいソースアカウントでPreAWSConfigAggregatorを実行した後、アグリゲータアカウントのAWS CloudFormation StackSetsからEnableAWSConfigを選択した後、アクションから「StackSetにスタックを追加」をクリックすることで、追加したいソースアカウントに対してスタックを作成することができます。
なお、aws:PrincipalOrgIDを使わずにaws:PrincipalAccountを使う場合には、配信先のAmazon S3バケットにおいて、バケットポリシーの変更が必要になります。
まとめ
AWS CloudFormation StackSetセルフマネージド型はAWS Configの有効化の他にも、様々なことに活用できそうだと感じました。























