CloudFormation を使用した AWS アカウントのセキュリティ対策を 2 つ紹介
AWS の Well-Architected フレームワークにはセキュリティの柱があり、設計原則などが記載されています。
今回は、設計原則の 1 つである「セキュリティイベントに備える」に関連して、AWS 公式から公開されている、 CloudFormation を使用した、AWS アカウントのセキュリティ対策を 2 つ紹介します。
概要
- AWS ルートユーザーアカウントが使用されたことを通知する EventBridge イベントルールを作成するにはどうすればよいですか?
- AWS Health AWS_RISK_CREDENTIALS_EXPOSED
1. AWS ルートユーザーアカウントが使用されたことを通知する EventBridge イベントルールを作成するにはどうすればよいですか?
まずは、ルートユーザーが使用されたときに通知する内容について紹介します。
実装手順は上記の 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
にしておきます。
通知の設定で、バージニア北部リージョンから、サインインイベントのトピックを選択します。
設定後、テストメッセージを送信することもできます。
もしプライベートチャネルを選択し、テストメッセージが届かない場合には、以下のブログを参考に設定してみてください。
これで Slack への通知設定も完了です。
AWS Health AWS_RISK_CREDENTIALS_EXPOSED
2 つ目に紹介するのは、IAM アクセスキーが漏洩した際に、アクセスキーを自動的に削除し、通知を行うという内容です。
こちらも設定は簡単で、上記 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 の設定が必要なのですが、設定方法については以下の記事を参考にしてください。
実施するのは「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 の項目通りに実施して下さい。
- test-user という IAM ユーザーを作成し、アクセスキーをコピーする
- Step Functions で
ExposedKeyStepFunction
という名前で始まるステートマシンで、「実行の開始」をクリックする - ステートマシンの入力に以下の 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"
}
]
}
}
- ステートマシンを実行する
- test-user のアクセスキーが削除されていることを確認する
- 指定のメールに通知が来ていることを確認する
Slack への通知設定を行った場合は、 Slack に通知が来ることも確認してください。
これで IAM アクセスキーが漏洩した時の、アクセスキー自動削除と通知の設定は完了です。
まとめ
今回は、設計原則の 1 つである「セキュリティイベントに備える」に関連して、AWS 公式から公開されている、 CloudFormation を使用した、AWS アカウントのセキュリティ対策を 2 つ紹介しました。
いずれも用意されたテンプレートを使用するだけですぐに設定できますし、Slack への通知も簡単なので、セキュリティイベントへの備えとしていかがでしょうか。
参考になれば幸いです。
Discussion