こんにちは。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の有効化の他にも、様々なことに活用できそうだと感じました。