AWS Organizations と AWS Config を利用した複数アカウントのリソース監視

はじめに

こんにちは、フォルシア SRE ユニットの高嶋です。
本記事では、AWS Organizations と AWS Config を利用した複数アカウントのリソース監視についての一例をご紹介します。監視の実現にあたっては、 Config アグリゲータという複数アカウントの AWS Config 設定や評価情報を集約してくれる機能を利用しています。大変便利な機能なのですが、集約した情報を利用して通知をするなど発展的な利用法に関する情報が少なく苦労したため、似たようなことを実現したい方の助けとなることを期待してこの記事を執筆をします。

AWS Organizations とは

https://docs.aws.amazon.com/ja_jp/organizations/latest/userguide/orgs_introduction.html
複数の AWS アカウントを一元的に管理するためのサービスです。
代表的な活用方法としては、企業の持つ AWS アカウントに対する請求の一括化や各アカウントのアクセス権限の中央管理などが挙げられるかと思います。他の AWS サービスとの連携機能もあり、組織内の全アカウントに対して一括で行いたい操作がある場合などにも役立ちます。

連係可能なサービスはこちら

AWS Config とは

https://docs.aws.amazon.com/ja_jp/config/latest/developerguide/WhatIsConfig.html
AWS リソースやその設定、リソース同士の関係性などを記録・評価するサービスです。AWS リソースの変更履歴の追跡や、ユーザーの設定するルールを逸脱したリソースがないか(例えばある日数以上停止している EC2 インスタンスがないか?)などのチェックが可能です。

実現したかったこと

AWS Certificate Manager (ACM) に取り込んだ SSL/TLS 証明書の有効期限が近付いたときに検知できる仕組みが欲しいというモチベーションで監視の設定をしました。

SSL/TLS 証明書はセキュアな通信には欠かせず、有効期限が切れてしまえば web サイトの安全性が損なわれたり場合によってはサービスが止まるなど大変なことになります。大切なものなので期限についてもきちんと管理するのは当然のことですが、弊社ではテスト系を含めて 50 弱の証明書を複数の AWS アカウントで管理しており、個別に期限を確認していくのは大変です。

ACM では ACM 発行の証明書に関しては自動更新も行えますが、ACM 外部で発行した証明書を取り込んでいるケースもあり、そのような場合には自動更新は行えません。

以上のような理由から、アカウント横断的に SSL/TLS 証明書の期限を監視できるような仕組みが求められていました。

監視設定をするにあたり意識したのは以下の点です。

  • 複数アカウントを横断的に監視できること
  • AWS アカウントが増えた場合の追加設定を最小限にできること(できれば 0 にしたい)
  • 社内の slack ワークスペースに通知を飛ばせること

どのような構成にしたか

ざっくりと下記のような手順で証明書の有効期限を通知できるようにしました。

  1. 監視対象のアカウントに AWS Config のルールを配布する
  2. 各アカウントの AWS Config から評価情報を集約する
  3. 集約した情報をもとに AWS Lambda を用いて slack 通知する

ではそれぞれについて詳細をご紹介します。

ステップ 1 監視対象のアカウントに AWS Config のルールを配布する

AWS Config のルールを配布する

AWS Config と AWS Organizations の連携機能を利用して組織内の AWS アカウントへの一括ルール配布をしました。

AWS Config には AWS リソースのあるべき構成を定義した AWS Config ルールという概念があり、AWS Organizations を利用している場合にはさらにそれを組織内のすべてのアカウントに適用する組織設定ルールを利用できます。

組織内の全てのアカウントに一括でルールをデプロイできるだけでなく、組織にアカウントが増えた場合には増えたアカウントにも組織設定ルールが自動適用されます。

組織設定ルールは API または CLI からのみ作成可能であるため、 AWS Organizations の管理アカウントのコンソールから CloudShell を起動して設定しました。

aws configservice put-organization-config-rule \
--organization-config-rule-name "acm-certificate-expiration-check" \
--organization-managed-rule-metadata '{
  "Description": "Checks whether ACM Certificates are marked for expiration within the specified number of days. Certificates provided by ACM are automatically renewed. ACM does not automatically renew certificates that you import.",
  "RuleIdentifier": "ACM_CERTIFICATE_EXPIRATION_CHECK",
  "InputParameters": "{\"daysToExpiration\":\"60\"}",
  "ResourceTypesScope": ["AWS::ACM::Certificate"]
}' \

CLI のリファレンスはこちらです。
https://docs.aws.amazon.com/cli/latest/reference/configservice/put-organization-config-rule.html

特徴的な設定値について簡単にご紹介します。

  • RuleIdentifier
    • AWS Config の提供するマネージドなルールの識別子です。今回は ACM で管理する証明書の有効期限までの日数を確認してくれるACM_CERTIFICATE_EXPIRATION_CHECKというルールを利用しました。
  • InputParameters
    • マネージドルールの評価に利用されるパラメータです。どのようなパラメータが設定できるかはルールによって異なります。ACM_CERTIFICATE_EXPIRATION_CHECK の場合は「有効期限まで何日を切ると非準拠とするか」を指定できます。

組織設定ルールと自アカウントを対象とした通常の AWS Config ルールの基本的な設定項目は似ています。CLI や API からルール作成する際の指定はなかなか難しいため、一度 AWS Config コンソール上で自アカウントを対象としたルールを作成し、下記のように CLI から設定値を確認してみると参考にしやすいと思いました。

# コンソールからacm-certificate-expiration-checkというルールを作成したうえで設定値を確認してみます
aws configservice describe-config-rules --config-rule-names  acm-certificate-expiration-check

# このように詳細を確認できるのでCLIでの組織設定ルール作成時の参考になります
{
    "ConfigRules": [
        {
            "ConfigRuleName": "acm-certificate-expiration-check",
            "ConfigRuleArn": "arn:aws:config:xxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
            "ConfigRuleId": "config-rule-xxxxxx",
            "Description": "Checks whether ACM Certificates in your account are marked for expiration within the specified number of days. Certificates provided by ACM are automatically renewed. ACM does not automatically renew certificates that you import.",
            "Scope": {
                "ComplianceResourceTypes": [
                    "AWS::ACM::Certificate"
                ]
            },
            "Source": {
                "Owner": "AWS",
                "SourceIdentifier": "ACM_CERTIFICATE_EXPIRATION_CHECK"
            },
            "InputParameters": "{\"daysToExpiration\":\"14\"}",
            "MaximumExecutionFrequency": "TwentyFour_Hours",
            "ConfigRuleState": "ACTIVE",
            "EvaluationModes": [
                {
                    "Mode": "DETECTIVE"
                }
            ]
        }
    ]
}

ステップ 2 各アカウントの AWS Config から評価情報を集約する

AWS Config から評価情報を集約

ここで AWS Config の一機能である Config アグリゲータを利用しました。AWS Config のスコープはリージョンですが、アグリゲータを利用することでマルチアカウント・マルチリージョンの AWS Config から情報を集約できます。この機能を利用してステップ 1 で作成した組織設定ルールの評価情報を AWS Organizations の管理アカウントへ集約しました。

アグリゲータを作成する際には集約対象として個別のアカウント ID を指定する方法と、組織を指定する方法があります。前者の場合は集約対象の各アカウント側で承認の操作が必要となりますが、後者では管理アカウントから一括での指定が可能であり組織内にアカウントが増えた場合にも追加設定なしで集約対象となります。今回は追加設定の手間をなるべく減らしたかったため、組織を集約対象に指定しています。

AWS Config コンソールからアグリゲータを作成ししばらく待つと、各アカウントの AWS Config から情報が集約されていることを確認できます。下図のように証明書の有効期限まで 60 日以内となったリソースが非準拠として表示されました!

コンソール上でみたアグリゲータの集約した情報

ステップ 3 集約した情報をもとに AWS Lambda を用いて slack 通知する

AWS Lambda を用いて slack 通知

AWS Config の評価情報を通知させるには Amazon Simple Notification Service (Amazon SNS)と連携させる方法や、Amazon EventBridge で AWS Config のイベントを検知して通知させる方法などがありますが、アグリゲータで集約した情報を通知させることは難しそうでした。

アグリゲータは、ソースアカウントからアグリゲータアカウントにデータをレプリケートすることで、アグリゲータが表示を許可されているソースアカウントとリージョンへの読み取り専用ビューを提供します。

公式ドキュメントにはこのような説明があり、現状のアグリゲータはあくまでも読み取り専用のリソースでそれを契機とした通知も難しいということかと考えています。(誤りがありましたらご指摘いただけると助かります)

そこで、AWS Lambda でアグリゲータの集めてきた情報を取得し、slack への投稿まで行うことにしました。アグリゲータからの情報取得に関してはAWS SDK for JavaScript v3 の ConfigServiceClient を利用することで簡単に行うことができました。JavaScript 以外の SDK にも同様のモジュールがあります。

こちらは AWS Lambda の Node.js ランタイムでのデータ取得例です。

// Node.jsランタイムに含まれているためimport不要で実行できました
// import { ConfigServiceClient, DescribeAggregateComplianceByConfigRulesCommand } from "@aws-sdk/client-config-service";

export const handler = async (event) => {
  const client = new ConfigServiceClient({});
  const input = {
    ConfigurationAggregatorName: "acm-certificate-expiration-check", // required
    Filters: {
      ComplianceType: "NON_COMPLIANT"
    }
    // NextToken: "STRING_VALUE",
  };
  const command = new DescribeAggregateComplianceByConfigRulesCommand(input);
  const result = await client.send(command);

  const response = {
    statusCode: 200,
    body: JSON.stringify(result)
  };
  return response;
};

上記では非準拠となったアカウントやリソースの数(証明書の数)が取得できます。ここでは割愛しますが、他のクラスも合わせて活用することで非準拠としてマークされた証明書の有効期限なども取得可能です。

slack へ POST するデータの整形についてもそのまま Lambda 関数内で行い、最終的には以下のような通知を投稿できました!

slackへの通知

また、作成した Lambda 関数は Amazon EventBridge スケジューラから週に一度トリガーするようにしました。

今後の展望

一方的に通知をするだけでなく、すでに担当チームで対応済み・確認済みの証明書に関しては通知をスキップできるような仕組みについても検討を進めています。

また、今回は ACM で管理している SSL/TLS 証明書の有効期限を対象として監視を設定しましたが、その他のリソースにも横展開したいと考えています。

この記事を書いた人

高嶋 ありさ
2021 年新卒入社
最近ワッサーという果物にハマっています。

FORCIA Tech Blog

Discussion