マルチアカウント環境でAWS Configのルール非準拠判定の通知を一元化させてみた

#はじめに
AWSのマルチアカウントでのシステム構成も増えてきて、サービスの役割ごとにアカウントを使い分けるケースもあるかと思います。
構成例として、Configルールは各アカウントで設定するが、メール通知やログ管理は一つのアカウントに集約させるといったような構成があげられます。

本記事では、アカウントA（送信側アカウント）で非準拠判定されたConfigルールを、アカウントB（受信側アカウント）のSNSトピックを利用してEメール通知させる設定方法について書いていきたいと思います。

#構成図
![構成図.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/629857/f95c2c3e-9d8c-93f2-5f7a-d88c064044ba.jpeg)
アカウントAでAWS Configルールを「required-tags」で新規作成し、EC2インスタンスのタグに「Name」「Application」の2つが含まれているかを判定します。
判定結果が非準拠となると、アカウントAのEventBridgeで検知しアカウントBのEventBridgeへ連携され、紐づけられたSNSを使って対象者にメール通知されます。
（参考：[AWS Configのルールで非準拠判定されたらメール通知したい](https://blog.serverworks.co.jp/notice-config-noncompliant)）

アカウントBをバージニアリージョンにしていますが、受信側のイベントバスがバージニア、オレゴン、アイルランドリージョンに限定されてしまっているためです。
（参考：[AmazonEventBridgeを使用したクロスリージョンイベントルーティングの紹介](https://aws.amazon.com/jp/blogs/compute/introducing-cross-region-event-routing-with-amazon-eventbridge/)）

今回は送信側のアカウントAを東京リージョン、受信側のアカウントBをバージニアリージョンで構築していきます。


#構築順
本記事では以下の流れで環境構築を進めていきます。

**アカウントA（送信側アカウント）**
1. Configルール作成

**アカウントB（受信側アカウント）**
2. KMSキー（カスタマー管理型 以降CMK）作成
3. SNSトピック作成
4. EventBridge作成

**アカウントA（送信側アカウント）**
5. EventBridge作成

以下に詳細な構築手順を記載していくので、実際に構築していってみましょう。

#環境構築手順
##1. Configルール作成
アカウントAにログインし、東京リージョンを選択した状態でAWS Configに移動し、「ルールの追加」をクリックします。
![Config001_01.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/629857/a05f1277-25db-0624-4bf0-5f8201314693.jpeg)

ルールタイプ「AWSによって管理されるルールの追加」を選択します。
「required-tags」を検索し、チェックを入れて「次へ」をクリックします。
![Config002_01.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/629857/bcb007c5-23fd-21ff-c493-f63cb885fbfd.jpeg)

以下でルールの設定を行い、「次へ」をクリックします。

* 名前：任意の名前（ここでは「required-tags」）
* 説明：任意の説明（ここではデフォルトのまま）
![Config003_01.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/629857/38906313-710d-8188-4c57-257cd5275af3.jpeg)

* 変更範囲：リソース
* リソース：任意のリソース（ここでは「AWS EC2 Instance」）
![Config004_01.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/629857/f6b9c438-cd0f-eff3-0459-40567afa24d6.jpeg)

* tag1Key：Name
* tag2Key：Application
* 上記以外は記載せず
![Config005_01.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/629857/236be3fd-ad07-8c62-6b47-b0b6325869b5.jpeg)

「確認と作成」で設定内容を確認し、「ルールを追加」をクリックします。
![Config006_01.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/629857/8c91a9ba-ce50-4738-c397-0a5fbb3ff450.jpeg)
![Config007_01.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/629857/31520060-a93c-0012-de7a-40d4621d55e7.jpeg)

無事ルールが作成されたことを確認します。
![Config009_01.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/629857/18be73bb-0304-c957-f80d-4e18a4ea6116.jpeg)

##2. CMK作成
アカウントBにログインし、バージニアリージョンを選択した状態でKMSに移動します。カスタマー管理型のキーを選択し、「キーの作成」をクリックします。
![バージニア001_01.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/629857/9ebe0fa8-96fb-bd00-6d40-9febe8a79592.jpeg)

以下でキーを設定し、「次へ」をクリックします。

* キーのタイプ：対象
* キーマテリアルオリジン：KMS
![バージニア002_01.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/629857/f081e093-c13a-633f-76a5-f193b230dccb.jpeg)

以下でラベルの追加をし、「次へ」をクリックします。

* エイリアス：任意のエイリアス名（ここでは「test-sns」）
![バージニア003_01.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/629857/829af07e-572a-23c7-3bb7-7254e453b637.jpeg)

ステップ3とステップ4はデフォルト設定のまま「次へ」をクリックします。

ステップ5のキーポリシーに以下の内容を記載し「完了」をクリックします。

```
{
    "Id": "key-consolepolicy-3",
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "Enable IAM User Permissions",
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::<Account B>:root"
            },
            "Action": "kms:*",
            "Resource": "*"
        },
        {
            "Sid": "Allow_EventBridge_for_CMK",
            "Effect": "Allow",
            "Principal": {
                "Service": "events.amazonaws.com"
            },
            "Action": [
                "kms:Decrypt",
                "kms:GenerateDataKey"
            ],
            "Resource": "*"
        }
    ]
}
```

※「"Sid": "Allow_EventBridge_for_CMK"」以降の設定を記載することで、EventBridgeからKMSへのアクセスを許可します。見落としがちですが、SNSの暗号化をCMKで行う場合は、KMSのキーポリシーが原因で想定通りに動作できないといったことも起こり得るので設定内容には注意しましょう。

無事CMKが作成されたことを確認します。
![Config010_01.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/629857/ea361527-caf9-9573-6065-398a4598a318.jpeg)

##3. SNSトピック作成
###3-1.トピック作成
アカウントBにログインし、バージニアリージョンを選択した状態でAmazon SNSに移動し、トピックを選択し「トピックの作成」をクリックします。
![バージニア007_01.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/629857/cb4e3fae-e106-f217-9feb-f5eee7c552c9.jpeg)

詳細は以下の設定を行います。

* タイプ：スタンダード
* 名前：任意の名前（ここでは「test-sns」）
* 表示名：任意の表示名（ここでは「AWSConfig-NON_COMPLIANT」）
![バージニア008_01.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/629857/0f02423a-5b3a-617d-311b-c50fc4d0c738.jpeg)

暗号化は以下の設定を行います。

* 暗号化：暗号化の有効化
* カスタマーマスターキー（CMK）：「2. CMK作成」で作成したKMSキー（ここでは「alias/test-sns」）
![バージニア009_01.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/629857/18d79c1a-8a15-d6da-739b-2f6310071b9e.jpeg)

アクセスポリシーは以下の設定を行います。

* メソッドの選択：高度な
* JSONエディタ：以下テキスト
![Config011_01.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/629857/00ae2cd1-15e1-b0d3-2ffb-5812e549bc29.jpeg)


```
{
  "Version": "2008-10-17",
  "Id": "__default_policy_ID",
  "Statement": [
    {
      "Sid": "__default_statement_ID",
      "Effect": "Allow",
      "Principal": {
        "AWS": "*"
      },
      "Action": [
        "SNS:Publish",
        "SNS:RemovePermission",
        "SNS:SetTopicAttributes",
        "SNS:DeleteTopic",
        "SNS:ListSubscriptionsByTopic",
        "SNS:GetTopicAttributes",
        "SNS:Receive",
        "SNS:AddPermission",
        "SNS:Subscribe"
      ],
      "Resource": "arn:aws:sns:us-east-1:<Account B>:test-sns",
      "Condition": {
        "StringEquals": {
          "AWS:SourceOwner": "<Account B>"
        }
      }
    },
    {
      "Sid": "AWSEvents_Allow",
      "Effect": "Allow",
      "Principal": {
        "Service": "events.amazonaws.com"
      },
      "Action": "sns:Publish",
      "Resource": "arn:aws:sns:us-east-1:<Account B>:test-sns"
    }
  ]
}
```
※「"Sid": "AWSEvents_Allow"」以降の設定を記載することで、EventBridgeからSNSへのアクセスを許可します。こちらもKMSのキーポリシー同様、アクセスポリシーが原因で想定通りに動作できないといったことも起こり得るので設定内容には注意しましょう。


無事トピックが作成されていることを確認します。
![Config013_01.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/629857/8f7d6082-7d14-5b50-c131-dbdbc15c3e09.jpeg)

###3-2.サブスクリプションの作成
3-1で作成したSNSトピックに移動し、サブスクリプションタブを開いた状態で「サブスクリプションの作成」をクリックします。
![バージニア013_01.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/629857/88111aaf-4269-bb6c-1881-0bbd18938933.jpeg)

詳細は以下の設定を行い、「サブスクリプションの作成」をクリックします。

* トピックARN：3-1で作成したSNSトピック（ここでは「test-sns」）
* プロトコル：Eメール
* エンドポイント：通知させるメールアドレス

![バージニア014_01.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/629857/a1f89539-9de2-4e24-d625-3ac0d5174716.jpeg)

以下のようなメールが届くので、メール本文中の「Confirm subscription」をクリックします。
![Config014_01.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/629857/9f875779-57d0-46d5-7fd9-54c906fdedee.jpeg)

ブラウザに遷移し、以下の画面が表示されることを確認します。
![Config015_01.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/629857/fe2e446b-127b-d277-0a9f-3fd47629eaac.jpeg)

マネジメントコンソール上でも、ステータスが「確認済み」になったことを確認します。
![バージニア016_01.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/629857/4875efd6-808f-4e48-2629-e1979662d7fb.jpeg)

##4. EventBridge作成（受信側アカウントB）
###4-1.イベントバスのアクセス設定
アカウントBにログインし、バージニアリージョンを選択した状態でEventBridgeに移動し、イベントバスのdefaultを開きます。
「アクセス許可を管理」をクリックします。
![Config016_01.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/629857/289f9de4-aa25-8e72-cb74-5d5cd91d71b9.jpeg)

リソースベースのポリシーに以下テキストを記載し、「作成」をクリックします。

```
{
  "Version": "2012-10-17",
  "Statement": [{
    "Sid": "allow_account_to_put_events",
    "Effect": "Allow",
    "Principal": {
      "AWS": "<Account A>"
    },
    "Action": "events:PutEvents",
    "Resource": "arn:aws:events:us-east-1:<Account B>:event-bus/default"
  }]
}
```
※このアクセス許可でアカウントAからのEventBridgeのアクセスを許可します。受信側のアカウントでは必要な設定となるので気を付けましょう。

イベントバスのARNは後述の5. EventBridge作成時に必要になるので、メモを取っておきましょう。


###4-2.ルールの作成
ルールを開き、イベントバスに「default」が選択されている状態で「ルールを作成」をクリックします。
![Config017_01.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/629857/e52fbdea-c843-b352-cb22-f69e5faa8ef0.jpeg)

名前と説明は以下を設定します。

* 名前：任意の名前（ここでは「test-config」）
* 説明：任意の説明（ここではデフォルトのまま）

![バージニア020_01.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/629857/bf804199-58fa-5de6-25de-fdd733f1ebf1.jpeg)

パターンを定義は以下を設定します。

* イベントパターンorスケジュール：イベントパターン
* イベント一致パターン：カスタムパターン
* イベントパターン：以下テキスト

![バージニア021_01.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/629857/4f8680d0-1865-f400-1090-58c5f92c1050.jpeg)

```
{
  "source": ["aws.config"],
  "detail-type": ["Config Rules Compliance Change"],
  "detail": {
    "messageType": ["ComplianceChangeNotification"],
    "configRuleName": [
      "required-tags"
    ],
    "newEvaluationResult": {
      "complianceType": ["NON_COMPLIANT"]
    }
  }
}
```

※「"configRuleName"」の箇所は、作成したConfigルール名によって適宜書き換えてください。

イベントバスがデフォルトのものが選択されていることを確認します。
![Config018_01.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/629857/5f80fbb1-4517-7208-c54a-0cb2534f0c22.jpeg)

ターゲットを選択は以下の設定を行います。

* ターゲット：SNSトピック
* トピック：3-1で作成したSNSトピック（ここでは「test-sns」）
* 入力の設定：入力トランスフォーマー

![バージニア023_01.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/629857/b986cadf-ff84-8ed2-7cf7-f9672de40894.jpeg)

* 入力トランスフォーマー
    * 入力パス：以下①テキスト
    * 入力テンプレート：以下②テキスト

```①.txt
{
        "awsRegion": "$.detail.awsRegion",
        "resourceId": "$.detail.resourceId",
        "awsAccountId": "$.detail.awsAccountId",
        "compliance": "$.detail.newEvaluationResult.complianceType",
        "rule": "$.detail.configRuleName",
        "time": "$.detail.newEvaluationResult.resultRecordedTime",
        "resourceType": "$.detail.resourceType"
}
```

```②.txt
"発生時刻 : <time>"
"ルール名 : <rule> "
"リソースタイプ : <resourceType>"
"リソースID : <resourceId>"
"AWSアカウント : <awsAccountId>"


"上記リソースが <compliance> 判定となりました。"
"詳細は以下URLよりご確認ください。"
"https://console.aws.amazon.com/config/home?region=<awsRegion>#/timeline/<resourceType>/<resourceId>/configuration"
```

上記入力が完了したら、「作成」をクリックします。

無事ルールが作成されていることを確認します。
![EventBridge013_01.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/629857/34afd048-78ce-4181-9fd4-e5816a1c1164.jpeg)

##5. EventBridge作成（送信側アカウントA）
アカウントAにログインし、東京リージョンを選択した状態でEventBridgeに移動します。
ルールを開き、イベントバスでdefaultが選択されている状態で「ルールを作成」をクリックします。
![EventBridge001_01.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/629857/38e1d853-0d87-6ae8-39cc-a05bea93a305.jpeg)

「イベントバスを選択」までは4-2.ルールの作成と同様のものを設定します。（ここではルール名を「test-notice-config」とし、それ以外は4-2と同様の設定を行います。）

ターゲットを選択は以下の設定を行います。

* ターゲット：別のアカウントまたはリージョンのイベントバス
* イベントバス：「4-1.イベントバスのアクセス設定」で設定したイベントバスARN
* IAMロール：この特定のリソースに対して新しいロールを作成する。
![EventBridge004_01.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/629857/7a23818b-74e8-e07b-52aa-dba5e570ed2e.jpeg)


※IAMロールを別途手動で作成する場合は、アカウントBのイベントバスへのアクセスを許可する内容で作成された、以下IAMポリシーを含んだIAMロールを作成する必要があります。

```
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "events:PutEvents"
            ],
            "Resource": [
                "arn:aws:events:us-east-1:<Account B>:event-bus/default"
            ]
        }
    ]
}
```

ターゲットを選択まで設定が完了したら「作成」をクリックし、ルールの作成を行います。

無事ルールが作成されていることを確認します。
![EventBridge005_01.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/629857/83a11add-7115-c731-f58f-1cd393872853.jpeg)

以上で環境構築は完了です。このあと動作確認をしていきます。

#動作確認
今回はEC2インスタンスのタグに「Name」「Application」が含まれているか判定するConfigルールを作成しているので、
アカウントA側の任意のEC2インスタンスから、タグ「Application」を削除してみます。

EC2の画面を表示し、任意のEC2インスタンスを選択したら、「タグを管理」をクリックします。
![EventBridge006_01.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/629857/b6b9aa1c-3153-3bad-84c1-c5b05118866f.jpeg)


キーがApplicationのタグを削除し、「保存」をクリックします。
![EventBridge007_01.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/629857/191cea0c-0366-cd02-200b-faefe4b46b61.jpeg)

Configの画面を表示し、1. Configルール作成で作成した「required-tags」を表示します。
アクションから再評価をクリックします。
![EventBridge014_01.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/629857/e3454dca-5620-547f-b218-a1dc8942f022.jpeg)


数分後、非準拠のルールとしてApplicationタグを削除したEC2インスタンスが検知され、3-2.サブスクリプションの作成で設定したメールアドレスあてにメールが届くことを確認します。
![EventBridge009_01.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/629857/7f25aac6-e974-fe36-e687-a6e3494f700c.jpeg)
![EventBridge011_01.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/629857/a2134a33-928f-5544-8152-aed8602f728d.jpeg)

以上で実装は完了です。

#おわりに
今回はマルチアカウントのシステムで活用できる、Configで非準拠ルールが検知された際に他アカウントのSNSトピックでメール通知させる構成を作成してみました。
複数アカウントのマルチアカウントシステムとなる場合、各アカウントでSNSトピックを管理するよりも圧倒的に管理工数が削減できるかと思います。
また、メール通知させるメール本文をEventBridgeで設定できるのがよいですね。
通知に必要な情報をピックアップして本文をカスタマイズするのもよいと思います。

以下に本構成を検討する際に参考にしたURLを貼っておきますので、こちらもあわせてご参照ください。

#参考記事
[AWS リソースが準拠していない場合に AWS Config を使用して通知を受けるにはどうすればよいですか?](https://aws.amazon.com/jp/premiumsupport/knowledge-center/config-resource-non-compliant/)

[AWS Configのルールで非準拠判定されたらメール通知したい](https://blog.serverworks.co.jp/notice-config-noncompliant)

[AmazonEventBridgeを使用したクロスリージョンイベントルーティングの紹介](https://aws.amazon.com/jp/blogs/compute/introducing-cross-region-event-routing-with-amazon-eventbridge/)

[AWSアカウント間でAmazon EventBridgeイベントを送受信してみた](https://dev.classmethod.jp/articles/cross-account-delivery-of-eventbridge-event-buts/)