概要
やりたいこと
マネジメントアカウント(旧組織マスターアカウント)配下の AWS アカウントに対して、 Organizations の CloudFormation StackSets で利用して、 OU (Organizations Unit) 単位で Config を有効化する。
つまり、自分のアカウント以外の AWS アカウントに対して CloudFormation を実行する。
自分のアカウントに対してのみ CloudFormation StackSets を利用する場合(セルフマネージド型)は以下。
AWS Organizations
複数のAWSアカウントを管理できるサービス。多機能。
今回は、OU (Organizational Unit) と呼ばれるアカウントのグルーピング機能が存在し、後述する CloudFormation StackSets が OU ごとに設定適用する。
CloudFormation 以外の AWS サービスにも権限の移譲などを行える。
Organizations の CloudFormation StackSets
CloudFormation StackSets には、自身のアカウントへの適用(セルフマネージド型)と、 Organizations を利用した他アカウントへの適用(サービスマネージド型)の、2種類が存在する。
セルフマネージド型の CloudFormation StackSets は、 IAM Role を実行管理アカウントとターゲットアカウントに作成しておく必要がある。
- 実行管理アカウント : AWSCloudFormationStackSetAdministrationRole
- ターゲットアカウント : AWSCloudFormationStackSetExecutionRole
しかし、サービス型マネージド型 StackSets の場合は、この IAM Role の用意は不要となる。
CloudFormation StackSets
前提:Organizations でアカウント B が所属する OU を作成していること。
- アカウント A : CloudFormation StackSets を実行するマネジメントアカウント
- アカウント B : Config を有効化するメンバーアカウント
アカウント A : Organizations アカウント
信頼されたアクセスを有効にする
Organizations と CloudFormation StackSets の連携を許可する。
Organizations コンソールより「設定」、アクセスの有効化をクリックする。
こうなれば連携完了。
S3 バケット 作成
test-config-organizations3 バケットを作成する。
AWS 公式のサンプルテンプレート を流用する。
AWSTemplateFormatVersion: 2010-09-09
Description: Create S3 bucket for AWS Config
Parameters:
ConfigBucket:
Type: String
OrganizationId:
Type: String
Resources:
Bucket:
DeletionPolicy: Retain
Type: AWS::S3::Bucket
Properties:
BucketName: !Ref ConfigBucket
ConfigBucketPolicy:
Type: AWS::S3::BucketPolicy
Properties:
Bucket: !Ref Bucket
PolicyDocument:
Version: 2012-10-17
Statement:
- Sid: AWSConfigBucketPermissionsCheck
Effect: Allow
Principal:
Service:
- config.amazonaws.com
Action: s3:GetBucketAcl
Resource:
- !Sub "arn:aws:s3:::${ConfigBucket}"
- Sid: AWSConfigBucketDelivery
Effect: Allow
Principal:
Service:
- config.amazonaws.com
Action: s3:PutObject
Resource:
- !Sub "arn:aws:s3:::${ConfigBucket}/${OrganizationId}/AWSLogs/*/Config/*"
Condition:
StringEquals:
"s3:x-amz-acl": "bucket-owner-full-control"
デプロイ。
aws cloudformation deploy \ --profile organizations-test-lac \ --stack-name config-bucket \ --template-file config_s3.yaml \ --parameter-overrides ConfigBucket=test-config-organizations3 OrganizationId=o-xxxxxxxxxxxx
アカウント B : メンバーアカウント
Config 有効化用 CloudFormation テンプレート 解説
クラウドワークスのブログのテンプレートを参考にさせていただきました。
AWSTemplateFormatVersion: 2010-09-09
Description: Enable AWS Config
Parameters:
ConfigBucket:
Type: String
OrganizationId:
Type: String
IncludeGlobalResourceTypeRegion:
Type: String
Default: ap-northeast-1
Conditions:
IsIncludeGlobalResourceTypeRegion: !Equals [ !Ref IncludeGlobalResourceTypeRegion, !Ref "AWS::Region" ]
Resources:
ConfigRecorderRole:
Type: AWS::IAM::Role
Properties:
RoleName: !Sub "config-role-${AWS::Region}"
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
ConfigRecorder:
Type: AWS::Config::ConfigurationRecorder
DependsOn: ConfigRecorderRole
DeletionPolicy: Delete
Properties:
RoleARN: !GetAtt ConfigRecorderRole.Arn
Name: !Sub "configuration-recorder-${AWS::Region}"
RecordingGroup:
AllSupported: true
IncludeGlobalResourceTypes: !If [IsIncludeGlobalResourceTypeRegion, true, false]
ConfigDeliveryChannel:
Type: AWS::Config::DeliveryChannel
DependsOn: ConfigRecorderRole
DeletionPolicy: Delete
Properties:
Name: !Sub "delivery-channel-${AWS::Region}"
ConfigSnapshotDeliveryProperties:
DeliveryFrequency: One_Hour
S3BucketName: !Ref ConfigBucket
S3KeyPrefix: !Ref OrganizationId
このコードのキモは、 IncludeGlobalResourceTypeRegion パラメータで、グローバルリソースの変更履歴を東京リージョンだけで記録するように絞っていること。
全リージョンでグローバルリソースの変更履歴を記録すると、重複したログが発生してしまうため。
Parameters:
IncludeGlobalResourceTypeRegion:
Type: String
Default: ap-northeast-1
〜省略〜
Conditions:
IsIncludeGlobalResourceTypeRegion: !Equals [ !Ref IncludeGlobalResourceTypeRegion, !Ref "AWS::Region" ]
〜省略〜
ConfigRecorder:
Type: AWS::Config::ConfigurationRecorder
DeletionPolicy: Delete
Properties:
Name: !Sub "configuration-recorder-${AWS::Region}"
RoleARN: !GetAtt ConfigRecorderRole.Arn
RecordingGroup:
AllSupported: true
IncludeGlobalResourceTypes: !If [IsIncludeGlobalResourceTypeRegion, true, false]
デフォルトの場合( ap-northeast-1 の時)、 IsIncludeGlobalResourceTypeRegion が true になり、IncludeGlobalResourceTypes も true となり、グローバルリソースの記録は有効となる。
それ以外のときは false となり、グローバルリソースの記録はされなくなる。
CloudFormation StackSets CLI でデプロイ
cloudformation cli から デプロイする。
create-stack-set コマンドでサービスマネージド型のスタックを作成する。
aws cloudformation create-stack-set \ --profile organizations-test-lac \ --stack-set-name config-organizations \ --template-body file://config.yaml \ --parameters ParameterKey=ConfigBucket,ParameterValue=test-config-organizations3 ParameterKey=OrganizationId,ParameterValue=o-xxxxxxxx \ --capabilities CAPABILITY_NAMED_IAM \ --permission-model SERVICE_MANAGED \ --auto-deployment Enabled=true,RetainStacksOnAccountRemoval=true
以下のようにスタックが作成される。
続いて create-stack-instances でデプロイ先の OU と region を指定する。
aws cloudformation create-stack-instances \ --profile organizations-test-lac \ --stack-set-name config-organizations \ --deployment-targets OrganizationalUnitIds="ou-xxxx-xxxxxxxx" \ --regions '["ap-northeast-1","ap-northeast-2", "ap-south-1", "ap-southeast-1", "ap-southeast-2", "ca-central-1", "eu-central-1", "eu-west-1", "eu-west-2", "eu-west-3", "sa-east-1", "us-east-1", "us-east-2", "us-west-1", "us-west-2"]' \ --operation-preferences FailureToleranceCount=0,MaxConcurrentCount=1
OU 配下のアカウント× region 分が登録される。
以下2つが実現できていること。
- 指定した OU 配下のアカウントでのみ Config が有効になっていること
- s3 にログがエクスポートされていること
エラー
ResourceLogicalId:ConfigDeliveryChannel, ResourceType:AWS::Config::DeliveryChannel, ResourceStatusReason:Insufficient delivery policy to s3 bucket: test-config-organizations3, unable to write to bucket, provided s3 key prefix is ‘null’.
s3バケットへの配信ポリシーが不十分です:s3キープレフィックスが「null」の場合、test-config-organizations3バケットに書き込めません。
下記でも同じエラーが報告。
解決方法が示されていた。
- Amazon S3 バケットポリシーを確認し、その後に config.amazonaws.com サービスがターゲットバケットへの書き込みを許可していることを確認してください。
- IAM エンティティのアクセス許可を確認し、AWS Config のフルアクセスポリシーを使用します。
- IAM エンティティに s3:GetBucketAcl バケットと s3:PutObject* バケットへの書き込み許可があることを確認します。
今回は、バケットポリシーではS3 prefix を付けていた(${OrganizationId)が、
ConfigBucketPolicy:
Type: AWS::S3::BucketPolicy
Properties:
Bucket: !Ref Bucket
PolicyDocument:
Version: 2012-10-17
Statement:
- Sid: AWSConfigBucketPermissionsCheck
Effect: Allow
Principal:
Service:
- config.amazonaws.com
Action: s3:GetBucketAcl
Resource:
- !Sub "arn:aws:s3:::${ConfigBucket}"
- Sid: AWSConfigBucketDelivery
Effect: Allow
Principal:
Service:
- config.amazonaws.com
Action: s3:PutObject
Resource:
- !Sub "arn:aws:s3:::${ConfigBucket}/${OrganizationId}/AWSLogs/*/Config/*"
デリバリーチャンネルの方には指定していなかった 。
ConfigDeliveryChannel:
Type: AWS::Config::DeliveryChannel
DependsOn: ConfigRecorderRole
DeletionPolicy: Delete
Properties:
Name: !Sub "delivery-channel-${AWS::Region}"
ConfigSnapshotDeliveryProperties:
DeliveryFrequency: One_Hour
S3BucketName: !Ref ConfigBucket
最後の行に指定したら上手くいった。
ConfigDeliveryChannel:
Type: AWS::Config::DeliveryChannel
DependsOn: ConfigRecorderRole
DeletionPolicy: Delete
Properties:
Name: !Sub "delivery-channel-${AWS::Region}"
ConfigSnapshotDeliveryProperties:
DeliveryFrequency: One_Hour
S3BucketName: !Ref ConfigBucket
S3KeyPrefix: !Ref OrganizationId
参考
Organization内のAWS ConfigをCloudFormation StackSetsで一気に設定する
CloudFormation StackSets でAWS Organization 管理下のアカウントのすべてのリージョンにAWS Config を設定して記録を単一バケットに集約するサンプル
コメント