📝

CloudFormation を使用した AWS アカウントのセキュリティ対策を 2 つ紹介

2022/06/10に公開

AWS の Well-Architected フレームワークにはセキュリティの柱があり、設計原則などが記載されています。

https://wa.aws.amazon.com/wellarchitected/2020-07-02T19-33-23/wat.pillar.security.ja.html

今回は、設計原則の 1 つである「セキュリティイベントに備える」に関連して、AWS 公式から公開されている、 CloudFormation を使用した、AWS アカウントのセキュリティ対策を 2 つ紹介します。

概要

  1. AWS ルートユーザーアカウントが使用されたことを通知する EventBridge イベントルールを作成するにはどうすればよいですか?
  2. AWS Health AWS_RISK_CREDENTIALS_EXPOSED

1. AWS ルートユーザーアカウントが使用されたことを通知する EventBridge イベントルールを作成するにはどうすればよいですか?

まずは、ルートユーザーが使用されたときに通知する内容について紹介します。

https://aws.amazon.com/jp/premiumsupport/knowledge-center/root-user-account-eventbridge-rule/

実装手順は上記の AWS 公式資料通りに進めるだけです。

1-1. YAML テンプレートをコピー

公式の YAML テンプレートをコピーし、任意の名前の YAML ファイルを作成して貼り付けます。

# Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
# Permission is hereby granted, free of charge, to any person obtaining a copy of this
# software and associated documentation files (the "Software"), to deal in the Software
# without restriction, including without limitation the rights to use, copy, modify,
# merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
# permit persons to whom the Software is furnished to do so.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
# INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
# PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

AWSTemplateFormatVersion: '2010-09-09'
Description: ROOT-AWS-Console-Sign-In-via-CloudTrail
Metadata:
  AWS::CloudFormation::Interface:
    ParameterGroups:
    - Label:
        default: Amazon SNS parameters
      Parameters:
      - Email Address
Parameters:
  EmailAddress:
    Type: String
    AllowedPattern: "^[\\x20-\\x45]?[\\w-\\+]+(\\.[\\w]+)*@[\\w-]+(\\.[\\w]+)*(\\.[a-z]{2,})$"
    ConstraintDescription: Email address required.
    Description: Enter an email address you want to subscribe to the Amazon SNS topic
      that will send notifications if your account's AWS root user logs in.
Resources:
  RootActivitySNSTopic:
    Type: AWS::SNS::Topic
    Properties:
      DisplayName: ROOT-AWS-Console-Sign-In-via-CloudTrail
      Subscription:
      - Endpoint:
          Ref: EmailAddress
        Protocol: email
      TopicName: ROOT-AWS-Console-Sign-In-via-CloudTrail
  EventsRule:
    Type: AWS::Events::Rule
    Properties:
      Description: Events rule for monitoring root AWS Console Sign In activity
      EventPattern:
        detail-type:
        - AWS Console Sign In via CloudTrail
        detail:
          userIdentity:
            type:
            - Root
      Name:
        Fn::Sub: "${AWS::StackName}-RootActivityRule"
      State: ENABLED
      Targets:
      - Arn:
          Ref: RootActivitySNSTopic
        Id: RootActivitySNSTopic
    DependsOn:
    - RootActivitySNSTopic
  RootPolicyDocument:
    Type: AWS::SNS::TopicPolicy
    Properties:
      PolicyDocument:
        Id: RootPolicyDocument
        Version: '2012-10-17'
        Statement:
        - Sid: RootPolicyDocument
          Effect: Allow
          Principal:
            Service: events.amazonaws.com
          Action: sns:Publish
          Resource:
          - Ref: RootActivitySNSTopic
      Topics:
      - Ref: RootActivitySNSTopic
Outputs:
  EventsRule:
    Value:
      Ref: EventsRule
    Export:
      Name:
        Fn::Sub: "${AWS::StackName}-RootAPIMonitorEventsRule"
    Description: Event Rule ID.

1-2. バージニア北部リージョンで CloudFormation スタックを作成

ルートユーザーのコンソールへのサインインイベントは、バージニア北部リージョンで発生するため、バージニア北部リージョンで CloudFormation スタックを作成します。

スタック名は任意なので、今回はテンプレートファイルの Description に記載されている内容をスタック名にしました。

パラメータでは通知先の EmailAddress を入力する必要があるので、通知を受け取りたいメールアドレスを入力します。

その他の設定はデフォルトのまま、スタックを作成します。

1-3. 確認メールで承認

スタック作成後、パラメータに入力したメールアドレス宛に、以下の確認メールが届きます。

本文にある Confirm subscription のリンクをクリックし、確認メールで承認します。

ここまでで設定は完了なので、通知をテストしたい場合には、ルートユーザーでログインしてみてください。

1-4. Slack に通知する方法

ログインイベントにすぐに気づけるよう、メールだけではなく、Slack に通知したい場合もあると思うので、Slack への通知方法も紹介します。

今回は AWS Chatbot を使用するので、Chatbot のコンソールにアクセスします。
初めて使用する場合は、チャットクライアントの設定が必要なので、Slack を選択します。

ワークスペースの URL を入力します。
URL 入力後にログインを求められる場合には、ワークスペースに所属するユーザー情報でログインしてください。

「許可する」をクリックします。

設定後に自動的に Chatbot のコンソールに戻ってくるので、「新しいチャネルを設定」をクリックします。

設定名、ログ記録、チャネルは任意の内容で設定してください。

アクセス許可のロール設定では、ロール名を入力し、チャネルガードレールポリシーは AdministratorAccess にしておきます。

通知の設定で、バージニア北部リージョンから、サインインイベントのトピックを選択します。

設定後、テストメッセージを送信することもできます。

もしプライベートチャネルを選択し、テストメッセージが届かない場合には、以下のブログを参考に設定してみてください。
https://dev.classmethod.jp/articles/aws-chatbot-slack-private-channel/

これで Slack への通知設定も完了です。

AWS Health AWS_RISK_CREDENTIALS_EXPOSED

2 つ目に紹介するのは、IAM アクセスキーが漏洩した際に、アクセスキーを自動的に削除し、通知を行うという内容です。

https://github.com/aws/aws-health-tools/tree/master/automated-actions/AWS_RISK_CREDENTIALS_EXPOSED

こちらも設定は簡単で、上記 GitHub 内の「Launch stack」をクリックし、デフォルト設定で CloudFormtion スタックを作成するだけです。
GitHub からクローンする方法も紹介されていますが、今回は簡単にできる方を紹介します。

2-1. CloudFormation スタック作成

GitHun 内の「Launch stack」をクリックし、デフォルト設定で CloudFormtion スタックを作成します。
スタック作成時にチェックをつける箇所がありますが、すべてチェックを入れて作成します。

2-2. SNS トピックにサブスクリプションを登録

Ensure you have at least one E-mail address subscribed to the SecurityNotificationTopic created by the template to receive the notification.

通知を受信するには、作成された SNS トピックにサブスクライブされているメールアドレスが必要とのことなので、メールアドレスを登録します。

SecurityNotificationTopic という SNS トピックが自動的に作成されているので、トピックにメールアドレスを関連付けます。

2-3. Slack に通知する方法

1 で紹介したサインインイベントについては、Chatbot で Slack に通知できましたが、今回のイベントは Chatbot が対応していませんでした。

そこで、Lambda 関数を使用して、Slack に通知する方法を実装したので紹介します。

Slack の設定

まずは Slack の設定が必要なのですが、設定方法については以下の記事を参考にしてください。
https://zenn.dev/mn87/articles/f102140a0540bf#3.-slack-の設定-(★)

実施するのは「3. Slack の設定」のみで OK です。

Lambda の設定

Slack の設定後、以下の設定で Lambda 関数を作成します。

・関数名: 任意
・ランタイム: Python 3.9
・アクセス権限: 基本的な Lambda アクセス権限で新しいロールを作成

コードには以下の内容を貼り付けます。

import urllib3
import json
http = urllib3.PoolManager()


def lambda_handler(event, context):
    print(json.dumps(event))
    
    url = "Slack Incoming Webhooks URL"
    msg = {
        "channel": "slack-channel-name",
        "username": "",
        "text": json.dumps(event),
        "icon_emoji": ""
    }

    encoded_msg = json.dumps(msg).encode('utf-8')
    resp = http.request('POST', url, body=encoded_msg)
    print({
        "message": "ok", 
        "status_code": resp.status, 
        "response": resp.data
    })

以下の部分を書き換えます。

Slack Incoming Webhooks URL: Slack の設定で払い出された URL を設定
slack-channel-name: 通知を送信したい Slack のチャンネル名

ここまでできたら、「Deploy」をクリックしてください。
デプロイ後、関数の ARN をコピーしておきます。

SNS トピックと Lambda を連携させる

SNS の SecurityNotificationTopic と、先ほど作成した Lambda を連携させます。

SecurityNotificationTopic のサブスクリプションに Lambda を追加します。
エンドポイントには先ほどコピーした Lambda の ARN を入力します。

これで SNS トピックと Lambda の連携は完了です。

2-4. テスト

テスト方法は、GitHub 内の Testing the Example の項目通りに実施して下さい。

  1. test-user という IAM ユーザーを作成し、アクセスキーをコピーする
  2. Step Functions で ExposedKeyStepFunction という名前で始まるステートマシンで、「実行の開始」をクリックする
  3. ステートマシンの入力に以下の JSON を貼り付け、ACCESS_KEY_ID_HERE の部分を、test-user のアクセスキーに書き換える
{
    "version": "0",
    "id": "121345678-1234-1234-1234-123456789012",
    "detail-type": "AWS Health Event",
    "source": "aws.health",
    "account": "123456789012",
    "time": "2016-06-05T06:27:57Z",
    "region": "us-east-1",
    "resources": [],
    "detail": {
        "eventArn": "arn:aws:health:us-east-1::event/AWS_RISK_CREDENTIALS_EXPOSED_XXXXXXXXXXXXXXXXX",
        "service": "RISK",
        "eventTypeCode": "AWS_RISK_CREDENTIALS_EXPOSED",
        "eventTypeCategory": "issue",
        "startTime": "Sat, 05 Jun 2016 15:10:09 GMT",
        "eventDescription": [
            {
                "language": "en_US",
                "latestDescription": "A description of the event will be provided here"
            }
        ],
        "affectedEntities": [
            {
                "entityValue": "ACCESS_KEY_ID_HERE"
            }
        ]
    }
}
  1. ステートマシンを実行する
  2. test-user のアクセスキーが削除されていることを確認する
  3. 指定のメールに通知が来ていることを確認する

Slack への通知設定を行った場合は、 Slack に通知が来ることも確認してください。

これで IAM アクセスキーが漏洩した時の、アクセスキー自動削除と通知の設定は完了です。

まとめ

今回は、設計原則の 1 つである「セキュリティイベントに備える」に関連して、AWS 公式から公開されている、 CloudFormation を使用した、AWS アカウントのセキュリティ対策を 2 つ紹介しました。

いずれも用意されたテンプレートを使用するだけですぐに設定できますし、Slack への通知も簡単なので、セキュリティイベントへの備えとしていかがでしょうか。

参考になれば幸いです。

Discussion