0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

設定ミスを自動で防ぐ!AWS Configで非準拠DBを自動修復

0
Posted at

設定ミスを自動で防ぐ!AWS-Configで非準拠DBを自動修復_eyecatch.png

はじめに

「各リソースの設定が適切か、確認するのが大変だった」「手作業で適切な設定に修正するのが大変だった」、皆さんはこんな経験ありませんか? このような状況では、作業者の確認漏れや設定の修正ミスが起こる可能性があります。

例えば、暗号化されていないDBインスタンスを放置した場合、ユーザーの個人情報や企業の重要なデータを平文で保存することとなり、情報漏洩のリスクを伴います。

作業者が暗号化のルールを徹底することも重要ですが、ルール非準拠の構成を検知し自動で修正する仕組みがあるとセキュリティリスクがぐっと下がります。

本記事では、AWS Configを利用し、ルール非準拠のDBインスタンスを検知しAmazon SNSで担当者に通知、SSM Automationで該当インスタンスを停止する手順を紹介します。

サービス概要

今回のハンズオンに使用するAWSサービスについて、簡単に概要を説明します。

AWS Config

AWS Configは、AWSアカウント内のリソース構成を管理するサービスです。リソースの作成、変更、削除を継続的に記録し、設定したルールと照らし合わせて評価します。

AWS Configがサポートしているリソースには様々なものがあります。EC2、S3、RDSなどのイメージしやすいものだけでなく、IAMポリシーなどもサポートしています。サポート対象のリソースタイプは随時追加されています。

AWS Configに設定できるルールには大きく2種類あります。

AWS Config マネージドルール

AWS Config マネージドルールはAWSが予め定義したConfigルールです。多くのマネージドルールが用意されており、設定するだけですぐに運用開始することができます。また、マネージドルールはカスタマイズすることも可能です。

以下はマネージドルールの例です。

ルール名 ルール内容
access-keys-rotated アクティブなIAMアクセスキーが指定された日数内にローテーションされるかどうか
cloudfront-s3-origin-access-control-enabled S3オリジンタイプを使用するCloudFrontディストリビューションで、オリジンアクセスコントロール(OAC)が有効かどうか
rds-storage-encrypted RDS DBインスタンスでストレージの暗号化が有効になっているかどうか

本記事ではrds-storage-encryptedを使用してハンズオンを実施します。

AWS Config カスタムルール

AWS Config カスタムルールは、ゼロから作成するConfigルールです。カスタムルールにはAWS Config カスタム Lambda ルール(Java または Python を使用したLambda関数で定義したルール)と、AWS Config カスタムポリシールール(Guardというpolicy-as-code言語で定義したルール)の2種類があります。

詳しくは公式のデベロッパーガイドをご覧ください。

Amazon SNS

Amazon SNS(Simple Notification Service)は、完全マネージド型のメッセージングサービスです。発信元(パブリッシャー)が「トピック」と呼ばれるチャネルにメッセージを送り、そこに登録された宛先(サブスクライバー)へ一斉に通知を配信する仕組みを提供します。

Amazon SNSのパブリッシャーには、EC2やECS上で動くアプリケーション開発、Lambda関数、Amazon CloudWatchのアラートなど様々なAWSサービスがなり得ます。

サブスクライバーにはAmazon SQSやLambdaなどのAWSサービス、EメールやSMSなどの通知、HTTP/HTTPSによるWebサーバへJSONメッセージをプッシュ送信などが挙げられます。

より詳しく知りたい方はこちらの記事もご参照ください。

今すぐできる!Amazon SNSでイベントのメール通知を実装しよう

Amazon EventBridge

Amazon EventBridgeは、AWSサービスや独自のアプリケーションで発生したイベントを受け取り、あらかじめ定義したルールに従って別のサービスへ振り分けるサーバーレスのイベントバスサービスです。

ルールには受け取りたいイベントの種類やイベントパターン(内容の条件)を指定します。条件に一致したイベントは、ターゲットとして設定したAmazon SNSやSSM Automationなど複数のAWSサービスへ配信することができます。

また、「入力変換」という機能を使うと、イベント本文の一部を変数として取り出し、ターゲットに渡すペイロードを任意の形式に加工できます。本記事でも、AWS Configから送られてくるイベントを読みやすい通知メッセージや、SSM Automationのランブックに渡すパラメータ形式に変換するために、この入力変換を活用します。

SSM Automation

SSM Automationは、AWSのサービス(EC2、RDS、S3など)のメンテナンスやデプロイなどのタスクを自動化するためのAWS Systems Manager(SSM)のツールです。

SSM Automationで実行したい操作はランブックというものに定義します。ランブックには順次実行されるステップ(操作)が1つ以上含まれます。AWSが事前定義したランブックを使用したり、ユーザーがPythonやPowerShellスクリプトを直接埋め込んだ独自のランブックを作成して使用することができます。今回のハンズオンでは独自ランブックを使用します。

ランブックはAmazon EventBridgeイベントのターゲットとして指定することもできます。これにより、ある操作を定期的に実行させたり、特定のAWSシステムイベントが発生したときに実行させることが可能です。

実装

実装の手順は以下の通りです。 前提として必要なVPC、サブネット、セキュリティグループなどは作成されているものとします。

  1. AWS Configでrds-storage-encryptedルールを使用するよう設定する
  2. Amazon SNSでルール非準拠インスタンス検知の通知用トピックを作成する
  3. Amazon EventBridgeからAmazon SNSをターゲットにし、メール通知を行う
  4. Amazon EventBridgeからSSM Automationランブックをターゲットにし、自動でインスタンス停止を行う
  5. DBインスタンスを作成し、Configが検知して非準拠のインスタンスのみが停止になっていることを確認する

今回のハンズオンでの構成図は以下のようになります。

202608ブログ構成図.drawio.png

AWS Configでrds-storage-encryptedルールを使用するよう設定する

AWS Configのダッシュボードにアクセスすると以下のような画面が表示されます。

AWS_Config_ダッシュボード.png

画面左側のパネルにある「ルール」からルールを作成していきます。

AWS_Config_ルール.png

「ルールを追加」をクリックし、AWSマネージドルールが選択された状態でrds-storage-encrypted を検索します。

AWS_Config_ルール_rds-storage-encrypted.png

表示されたルールを選択し「次へ」をクリックすると、評価モードなどの設定画面が表示されます。 リソースをデプロイする前に検知するプロアクティブモードもありますが、今回は検知モードを使用します。 「変更範囲」を「リソース」、「リソースタイプ」を「AWS RDS DBInstance」と設定します。

AWS_Config_ルール_評価モード.png

AWS Configルールの中にはパラメータを受け取るものもあります。 以下はルールのパラメータとタグを設定する画面です。 rds-storage-encryptedにはkmsKeyIdというパラメータがあり、ストレージの暗号化に使用するKMSキーIDまたはAmazonリソースネーム(ARN)を渡すことが可能です。これにより特定のキーでの暗号化がなされているかどうか検知できます。 今回は特に指定せずこのまま作成します。

AWS_Config_ルール_パラメータとタグ.png

以下は確認画面です。

AWS_Config_ルール_確認.png

作成後は以下のようにルール一覧画面に表示されます。

AWS_Config_ルール_作成後.png

Amazon SNSでルール非準拠インスタンス検知の通知用トピックを作成する

AWS Configで非準拠リソースを検知した際に、管理者としてメールで通知を受け取るようAmazon SNSを設定していきます。 まず、SNSのページからトピックを作成します。

今回はEメールで通知を受け取りたいため、「スタンダード」を選択します。 その他の設定はデフォルトのままです。

Amazon_SNS_トピック作成.png

トピックを作成すると詳細ページに遷移します。 ここからサブスクリプションを設定していきます。

Amazon_SNS_トピック詳細.png

サブスクリプション作成ページでサブスクライブプロトコルを選択できます。 今回はメール通知を受け取りたいので「Eメール」を選択し、エンドポイントにメールアドレスを入力します。

Amazon_SNS_サブスクリプション作成.png

サブスクリプションを作成すると以下のように表示され、該当メールアドレスに確認メールが送信されます。

Amazon_SNS_サブスクリプション詳細.png

Amazon_SNS_確認メール-1.png

確認メール内の「Confirm subscription」をクリックすると確認ページが表示されます。 その後サブスクリプション詳細ページを更新すると、ステータスが「確認済み」に変わっているのが確認できます。 これでAmazon SNSの準備は完了です。

Amazon_SNS_サブスクリプションメール確認後.png

Amazon EventBridgeからAmazon SNSをターゲットにし、メール通知を行う

Amazon EventBridgeの設定

ここから、Amazon EventBridgeを設定していきます。 トップページから「イベントパターンを含むEventBridgeルール」を選択しルールを作成します。

Amazon_EventBridge_トップページ.png

ルール作成に進むと、以下のような画面が表示されます。 「トリガーイベント」にルール実行のきっかけとなるイベントを、ターゲットに最終的に実行させたい処理を設定します。

Amazon_EventBridge_ルール作成①.png

今回作成したConfigルールが該当するイベントは「Config Rules Compliance Change」なのでそれをトリガーイベントに設定します。

Amazon_EventBridge_ルール作成②.png

次にターゲットに先ほど設定したSNSトピックを選択します。

Amazon_EventBridge_ルール作成③.png

EventBridgeのルールを作成するとき、EventBridgeが引き受ける実行ロールを作成してくれます。

Amazon_EventBridge_ルール作成④.png

作られたロールは以下のようになっています。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "sns:Publish"
            ],
            "Resource": [
                "arn:aws:sns:ap-northeast-1:{{accountID}}:MyHandsonTopic"
            ]
        }
    ]
}

これでEventBridgeルールの作成は完了です。

Amazon EventBridgeからSSM Automationランブックをターゲットにし、自動でインスタンス停止を行う

SSM Automation ランブックの作成

自動でルール非準拠DBインスタンスを停止させるためにSSM Automationのランブック(ドキュメント)を作成していきます。 以下の画像は実行したオートメーション(自動処理)の一覧ページです。 ここの「Create runbook」からランブックを作成できます。

SSM_automation_一覧.png

もしくはドキュメントのページから作成ページに飛ぶことも可能です。 こちらではAWSが事前に作成しているドキュメントや、自分が作成したドキュメント、共有されたドキュメントを確認することができます。

SSM_automation_ドキュメント作成.png

「AWS-StopRdsInstance」という、いかにもおあつらえ向きなAWSドキュメントがあるのですが、残念なことに今回の構成ではそのまま使用することはできません… というのも、AWS-StopRdsInstanceはパラメータとしてインスタンスIDを受け取るのですが、Configから送られてくるイベントにインスタンスIDは存在しません。 なのでイベントで送られてくるリソースIDをインスタンスIDに変換する必要があります。 今回はそれも含めてオリジナルのランブックを作成していきます。

ランブック作成画面は以下のようになっております。 左のパネルから基本的なアクションやAWS API、定義済みランブックを真ん中のパネルにドラッグしていき処理を組み立てていきます。

SSM_automation_ランブック作成.png

今回のランブックの構成は以下の通りです。 前段のスクリプトで「リソースID → インスタンスID」の変換を行います。 そのスクリプトの出力をAWS-StopRdsInstanceに渡し、該当インスタンスを停止させます。

SSM_automation_StopRDSInstanceFromResourceId.png

リソースIDからインスタンスIDへの変換は以下のスクリプトで行っています。 RDSのdescribe_db_instancesにリソースIDを渡し、インスタンスIDを取得しています。

import boto3
def script_handler(events, context):
    rds = boto3.client('rds', region_name='ap-northeast-1')
    response = rds.describe_db_instances(
        Filters=[
            {
                'Name': 'dbi-resource-id',
                'Values': [
                    events['rdsResourceId']
                ]
            }
        ]
    )
    instanceId = response['DBInstances'][0]['DBInstanceIdentifier']
    return {'InstanceId': instanceId, 'AutomationAssumeRole': events['automationAssumeRole']}

ランブックの定義はyamlコードで作成することも可能です。 今回のランブックのコードは以下のようになっています。

schemaVersion: '0.3'
description: Stop RDS instance from a resource ID.
assumeRole: '{{ AutomationAssumeRole }}'
parameters:
  ResourceId:
    type: String
    description: (Required) RDS Resource Id to stop
    allowedPattern: ^[a-zA-Z]*([-]?[\w]+)*$
  AutomationAssumeRole:
    type: String
    description: (Optional) The ARN of the role that allows Automation to perform the actions on your behalf.
    default: ''
    allowedPattern: ^$|arn:(aws[a-zA-Z-]*)?:iam::\d{12}:role\/?[a-zA-Z_0-9+=,.@\-_\/]+
mainSteps:
  - name: TransformResourceId2InstanceId
    action: aws:executeScript
    nextStep: AWS_StopRdsInstance
    isEnd: false
    inputs:
      Runtime: python3.12
      Handler: script_handler
      InputPayload:
        rdsResourceId: '{{ ResourceId }}'
        automationAssumeRole: '{{ AutomationAssumeRole }}'
      Script: |-
        import boto3
        def script_handler(events, context):
          rds = boto3.client('rds', region_name='ap-northeast-1')
          response = rds.describe_db_instances(
              Filters=[
                  {
                      'Name': 'dbi-resource-id',
                      'Values': [
                          events['rdsResourceId']
                      ]
                  }
              ]
          )
          instanceId = response['DBInstances'][0]['DBInstanceIdentifier']
          return {'InstanceId': instanceId, 'AutomationAssumeRole': events['automationAssumeRole']}
    outputs:
      - Type: String
        Name: InstanceId
        Selector: $.Payload.InstanceId
      - Type: String
        Name: AutomationAssumeRole
        Selector: $.Payload.AutomationAssumeRole
  - name: AWS_StopRdsInstance
    action: aws:executeAutomation
    isEnd: true
    inputs:
      DocumentName: AWS-StopRdsInstance
      RuntimeParameters:
        InstanceId: '{{ TransformResourceId2InstanceId.InstanceId }}'
        AutomationAssumeRole: '{{ AutomationAssumeRole }}'

詳しいランブックの作成方法は公式ドキュメントに載っています。

独自のランブックの作成

AutomationAssumeRoleにはSSMが処理を実行するために必要な権限ロールを渡します。 今回の権限は以下のように設定しております。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "HandsonStopRDSInstance",
            "Effect": "Allow",
            "Action": [
                "rds:DescribeDBInstances",
                "rds:StopDBInstance"
            ],
            "Resource": "arn:aws:rds:*:{accountId}:db:*"
        }
    ]
}

インスタンス停止用EventBridgeルールの作成

作成したランブックを使用してインスタンス停止用のEventBridgeルールを作成します。 ターゲットに「Systems Manager オートメーション」をドラッグで挿入し、先ほど作成したランブックを選択します。

Amazon_EventBridge_ルール作成_インスタンス停止.png

入力変換を利用してランブックに必要な情報を抽出します。

注意点

ランブックのパラメータに値を渡すとき、そのまま値を渡しても動作しません。 パラメータに値を渡すときは各キーに対する値をリストにする必要があります。

SSM Automationは内部的にStartAutomationExecutionAPIを呼び出しており、そのシンタックスではParametersをリストで受け取っています。

NG:

{
   "ResourceId": "<resourceId>"
}

OK:

{
   "ResourceId": ["<resourceId>"]
}

参照: StartAutomationExecution

Amazon_EventBridge_ルール作成_インスタンス停止_入力変換.png

これでインスタンス停止用ルールの作成は完了です。

DBインスタンスを作成し、Configが検知して非準拠のインスタンスのみ停止になっていることを確認する

RDS DBインスタンスの作成

ここまでで、非準拠となるインスタンスを検知し、自動で停止させるルールを作成しました。 作成したルールを検証するため、実際にRDS DBインスタンスを作成していきます。

Amazon_RDS_データベース.png

右上の「データベースを作成」ボタンからインスタンスを作成していきます。 「エクスプレス設定」を選ぶと数秒でAurora PostgreSQLサーバーレスデータベースを作成することができますが、今回は普通のDBインスタンスを作成したいため「フル設定」を選択します。

Amazon_RDS_データベースの作成ボタン.png

「フル設定」を選択すると、データベースの各種設定ができます。 今回のデータベースエンジンはPostgreSQLを選択しました。(今回のハンズオンではデータベースの操作はしないのでエンジンによる差はないかと思います。) 「簡単に作成」を選択するとインスタンス(ストレージ)の暗号化が自動で設定されます。今回は暗号化されないよう設定したいので「フル設定」を選択します。 テンプレートは「無料利用枠」を選択しました。今回のハンズオンではこれで十分です。

Amazon_RDS_データベースの作成①.png

下記ではエンジンのバージョンや、データベースの認証情報を設定できます。 認証情報管理で「AWS Secrets Manager」を選択すると安全かつ簡単にパスワードなどを管理できます。 今回はコスト面から「セルフマネージド」を選択しましたが、実際にデータベースを使用する際は「AWS Secrets Manager」の使用が推奨されます。

Amazon_RDS_データベースの作成②.png

以下ではDBインスタンスのネットワークについて設定します。 ハンズオン用に作成したVPCやサブネット、セキュリティグループを選択します。

Amazon_RDS_データベースの作成③.png

最後にバックアップや暗号化などの設定をします。 デフォルトでは「暗号を有効化」にチェックが入っていますが、今回は検証のため暗号化せずにインスタンスを作成します。

Amazon_RDS_データベースの作成④.png

「データベースを作成」ボタンをクリックすると、データベース一覧画面で作成したインスタンスが「作成中」の状態になっていることが確認できます。 インスタンスの作成には数分かかり、完了後は以下の画像のようにステータスが「利用可能」に変わります。

Amazon_RDS_データベースの作成後.png

ルール非準拠インスタンスの検知

ルール非準拠のインスタンスを作成してから数分後にAWS Configのダッシュボードを確認すると以下のようになっていました。 ルールに引っかかっているものが検知されたことがわかります。

AWS_Config_ダッシュボード_検知.png

まずルールの方を確認してみましょう。 作成したルールに反しているリソースが1件あることが確認できます。

AWS_Config_ルール_非準拠.png

次にリソースを確認してみます。 先ほど作成した「database-1」が検出され、コンプライアンスの状態が「非準拠」となっています。

AWS_Config_リソース_非準拠.png

Amazon SNSからのメール受信

非準拠インスタンスの検知がトリガーとなり、以下のようなメールが届きます。

Amazon_SNS_Configメール.png

先ほど作成したDBインスタンスがルール非準拠だということがわかります。 ただ、びっくりするほど読みづらい…

なのでEventBridgeの入力変換を活用して読みやすいメッセージに直していきます。 先ほどのルール作成画面中、ターゲット内の「入力変換」を有効化し、以下の画面で編集していきます。

  1. 一番左のパネルでサンプルイベントを選択します。今回は「Config Rules Compliance Change」。
  2. その次のパネルで、テンプレート上で使いたい値を変数として定義します。$.を使うことでイベントからの値を使用することができます。
  3. 次のテンプレートパネルで定義した変数を使い出力させたい文字列を作成していきます。
  4. 最後のパネルで最終的な出力が確認できます。

Amazon_EventBridge_ルール作成_SNS入力テンプレート.png

また非準拠DBインスタンスを作成してみると以下のメールが届きました。 入力変換を利用することで必要な情報のみに絞ることができました。

Amazon_SNS_Configメール改良版.png

SSM Automationによるインスタンスの自動停止

メールが送られてきたのを確認し、RDSのインスタンスページにアクセスすると以下のようになっていました。

Amazon_RDS_データベース_インスタンス停止.png

非準拠インスタンスの検知がトリガーとなりSSM Automationによりインスタンスの停止が確認できました。

ルールに準拠しているDBインスタンスの作成

ルールに準拠しているDBインスタンスを作成してみます。 手順は非準拠インスタンスとほぼ同じで、暗号の有効化のみ違いがあります。

Amazon_RDS_データベースの作成_暗号化.png

AWS Configのダッシュボードを確認してみます。 ルールには引っかかっておらず、準拠リソースとして表示されています。

AWS_Config_ダッシュボード_準拠_検知.png

リソースの画面を見るとdatabase-2のコンプライアンス状態が「準拠」となっていることが確認できます。

AWS_Config_リソース_準拠.png

すべてのDBインスタンスを表示すると以下のようになります。

AWS_Config_リソース.png

おわりに

今回、Configで非準拠のDBインスタンスを検知して自動で停止してみました。AWS Configを利用することでルールに違反しているリソースや構成を検知してくれます。 また、Amazon SNSで通知を行ったりSSM Automationを利用して様々な操作を自動で実行させることができ、実際の運用にも活用することができます。

このような構成にすることでセキュリティリスクとなるリソースをいち早く検知し、人の手を介さず応急処置をすることが可能で被害を最小限に食い止められるでしょう。

実運用では、SCPや様々なポリシーでルールに違反しているリソースを作らせない「予防的ガードレール」と、実際に作られてしまった際に検知し、責任者への通知やインスタンス停止などの応急処置を行う「発見的ガードレール」を組み合わせることでよりセキュアな環境を構築することができます。

今回のハンズオンを通して、AWS Configの便利さを体感しましたが、どちらかというとAmazon EventBridgeの便利さに感動しました。様々なイベントをトリガーにして処理を実行することもできますし、スケジュールを設定して実行することもできるので多くの場面で利用できるサービスだと実感しました。

ハンズオンで苦労した点はSSM Automationへのパラメータの渡し方です。SSM Automationが内部的にStartAutomationExecutionAPIを呼び出していることを知らなかったので、実行できない原因を突き止めるのに時間がかかりました。

この記事が同じような構成を試そうとしている方への助けとなれば幸いです。

We Are Hiring!

AWSマネージドサービスを活用したセキュリティ自動化の学びを、実践的な現場で活かしてみませんか?

FindConsultingには、異業種から転身してAWSエンジニアとして活躍するメンバーや、SQLのみのスキルからPython・Reactでの開発案件に挑戦するメンバーなど、入社後にキャリアを大きく広げた社員が多くいます。資格取得支援や実案件への早期参画など、次のステップへ踏み出すための環境が整っています。

「今の環境では設計・構築の経験を積む機会が少ない」「AWSを使った運用自動化のスキルを深めていきたい」と感じている方は、ぜひ一度話を聞きに来ませんか?

現在、FindConsultingではキャリアチェンジ・スキルアップを目指す仲間を募集しています。
まずはカジュアル面談からでも、ぜひお気軽にお声がけください。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?