CI部1課の山﨑です。
今回はAmazon Athenaを利用してS3に保管されているAWS Config のログを調査する方法を調べてみたので整理します。
おさらい
AWS Config
AWS Config とは
AWS Config は、AWS リソースの設定を評価、監査、審査できるサービスです。Config では、AWS リソースの設定が継続的にモニタリングおよび記録され、望まれる設定に対する記録された設定の評価を自動的に実行できます。
※引用元:AWS Config(リソースのインベントリと変更の追跡)| AWS
AWS Config は一般的にAWSマネージドの構成管理サービスとして認知されています。具体的には「いつ、どのリソースに、どのような設定変更が行われたのか」といったことを記録・管理することができます。ただし、AWS Config はAWSで提供されている全てのサービスをサポートしているわけではないためご注意ください。AWS Config でサポートされているリソースタイプについては以下のリンクをご確認ください。
AWS Config のログの種類
S3バケットに出力されるAWS Config のログには Configuration History と Configuration Snapshot の2種類があります。それぞれの違いを要約したものが以下の表です。
※参考ドキュメント:
Configuration History | Configuration Snapshot | |
---|---|---|
概要 | 任意の期間における特定のリソースタイプのConfiguration Item を収集 | アカウント内の全てのサポート対象リソースのConfiguration Itemを収集。アカウント内のリソース構成のPoint-in-timeのキャプチャ。EC2で例えるとAMIのようなもの。 |
設定方法 | AWS Config を有効化したら自動で有効化 | CLIを使って手動設定 |
取得頻度 | 6時間間隔 | 1, 3, 6, 12 or 24 時間間隔 |
トリガー | リソースに変更が発生した場合のみ | 設定した取得頻度で定期実行 |
ユースケース | 特定のリソースタイプの過去の設定状態を確認したい時 例) ・EBSボリュームに起こった変更(Configuration Item)の数をリストアップする。 ・AWS Configで1ヶ月間に記録されたConfiguration Itemの数を取得する。 |
アカウント内の全てのリソースタイプの現構成を確認したい場合 例 ・アカウント内の全てのサポート対象リソースの最新の構成状態を確認する。 特定のRegionのみでAWS Configが記録している全てのリソースのリストを取得する。 |
そのほかAWS Config 自体の設定方法等については以下のブログをご覧ください。
Amazon Athena
Amazon Athena とは
Amazon Athena は、標準的な SQL を使用して Amazon Simple Storage Service (Amazon S3) 内のデータを直接分析することを容易にするインタラクティブなクエリサービスです。AWS Management Console でいくつかのアクションを実行するだけで、Athena にデータの保存先の Amazon S3 を設定し、標準 SQL を使用してアドホッククエリの実行を開始できます。結果は数秒で返されます。
Athena はサーバーレスであるため、インフラストラクチャの設定や管理は不要です。また、実行したクエリにのみ課金されます。自動的にスケールしてクエリを並列実行するため、大規模なデータベースや複雑なクエリでも結果がすぐに返されます。 ※引用元:https://docs.aws.amazon.com/ja_jp/athena/latest/ug/what-is.html
Amazon Athenaは Apache Hiveのデータ定義言語(DDL)を使ってテーブルを作成し、Hadoopの分散型SQLエンジンでアドホックな分析を行うのに適しているPrestoを使ってクエリを実行しています。S3バケットはオブジェクトストレージであり、非構造化データあるいはスキーマレスデータが保管されています。Amazon Athena でクエリを実行する際はCREATE TABLEを使ってS3内のデータを構造化データに整形した上で、SQLを使ってクエリをかけていきます。
執筆時期が古いですが、Athenaについては以下のブログもご覧ください。
S3のログを調査してみる
Athena でクエリを実行するテーブルを作成
テーブルを作成する前にS3に保管されているログの構造をある程度把握しておきます。「ある程度」と言っているのはサポートされているAWSリソースタイプによってログの構造が異なるためです。
以下はリソース対応がAWS::S3::Bucketの場合のログの例です。
Configuration History
{ "fileVersion": "1.0", "configurationItems": [ { "relatedEvents": [], "relationships": [], "supplementaryConfiguration": {}, "tags": {}, "configurationItemVersion": "1.3", "configurationItemCaptureTime": "2021-08-01T01:31:29.866Z", "configurationStateId": 1627781489866, "awsAccountId": "アカウントID", "configurationItemStatus": "ResourceDeleted", "resourceType": "AWS::S3::Bucket", "resourceId": "バケット名", "resourceName": "バケット名", "ARN": "arn:aws:s3:::バケット名", "awsRegion": "ap-northeast-1", "configurationStateMd5Hash": "" } ] }
Configuration Snapshot
{ "fileVersion": "1.0", "configSnapshotId": "80296636-f5de-429b-a654-788936567671", "configurationItems": [ { "relatedEvents": [], "relationships": [], "configuration": { "name": "バケット名", "owner": { "id": "123456788900987654321234567890" }, "creationDate": "2021-08-01T01:52:42.000Z" }, "supplementaryConfiguration": { "AccessControlList": "{}", "BucketAccelerateConfiguration": {}, "BucketLoggingConfiguration": {}, "BucketNotificationConfiguration": { "configurations": {} }, "BucketPolicy": { "policyText": "{}" }, "BucketVersioningConfiguration": { "status": "Off" }, "IsRequesterPaysEnabled": false, "PublicAccessBlockConfiguration": { "blockPublicAcls": true, "ignorePublicAcls": true, "blockPublicPolicy": true, "restrictPublicBuckets": true }, "ServerSideEncryptionConfiguration": { "rules": [ { "applyServerSideEncryptionByDefault": { "sseAlgorithm": "AES256" }, "bucketKeyEnabled": false } ] } }, "tags": {}, "configurationItemVersion": "1.3", "configurationItemCaptureTime": "2021-08-10T12:40:53.558Z", "configurationStateId": 1628599253558, "awsAccountId": "アカウントID", "configurationItemStatus": "OK", "resourceType": "AWS::S3::Bucket", "resourceId": "バケット名", "resourceName": "バケット名", "ARN": "arn:aws:s3:::バケット名", "awsRegion": "ap-northeast-1", "availabilityZone": "Regional", "configurationStateMd5Hash": "", "resourceCreationTime": "2021-08-01T01:52:42.000Z" } ] }
上記のログの構造を踏まえて今回は以下のようなテーブルを作成してみます。
CREATE EXTERNAL TABLE awsconfig ( fileversion string, configSnapshotId string, configurationitems ARRAY < STRUCT < configurationItemVersion : STRING, configurationItemCaptureTime : STRING, configurationStateId : BIGINT, configuration: STRUCT < name : STRING > , awsAccountId : STRING, configurationItemStatus : STRING, resourceType : STRING, resourceId : STRING, resourceName : STRING, ARN : STRING, awsRegion : STRING, availabilityZone : STRING, configurationStateMd5Hash : STRING, resourceCreationTime : STRING > > ) ROW FORMAT SERDE 'org.apache.hive.hcatalog.data.JsonSerDe' LOCATION 's3://バケット名/AWSLogs/アカウント名/Config/ap-northeast-1/2021/';
Athena でクエリを記述する際に指定する ROW FORMAT SERDE の「SERDE」はSerialize と Deserialize の頭文字を取っているものでデータソースからAthenaテーブルへのデータの読み書きに使用するSerialize と Deserialize の対応を明示的に指定するものです。
Amazon Athenaは Apache Hiveのデータ定義言語(DDL)を使ってテーブルを作成しますが、Apache Hive は JSON 形式のファイルをネイティブにサポートしていません。そのためSerDe(Serialize と Deserialize) を使用して Hive がJSONで記述されたレコードをどのように処理すべきかを理解できるようにする必要があります。Deserialize はデータを取得してJavaオブジェクトに変換し、Serialize はJavaオブジェクトを使用可能な表現に変換します。
テーブルの作成に関するスキーマ情報などのメタデータはAWS Glue Data Catalog のテーブルに保管されます。
Athena でクエリを実行する
1. 変更があったConfiguration Itemの数をカウント
SELECT configurationItem.resourceType, configurationItem.resourceId, COUNT(configurationItem.resourceId) AS NumberOfChanges FROM default.awsconfig CROSS JOIN UNNEST(configurationitems) AS t(configurationItem) WHERE "$path" LIKE '%ConfigHistory%' AND configurationItem.configurationItemCaptureTime >= '2021-06-01T%' AND configurationItem.configurationItemCaptureTime <= '2021-06-03T%' GROUP BY configurationItem.resourceType, configurationItem.resourceId ORDER BY NumberOfChanges DESC
上記のクエリを実行することで、ある任意の期間内にどのAWSリソースタイプの、どのAWSリソースに対して、何回の構成変更があったのかを調べることができます。
このクエリを実行することでAWS Config のコスト増の原因を分析することも可能です。詳細は以下のブログをご覧ください。
2. 実際にどのような構成変更があったのかを調べる
SELECT configurationItem.resourceType, configurationItem.resourceId, configurationItem.configurationItemStatus, configurationItem.configurationItemCaptureTime FROM default.awsconfig CROSS JOIN UNNEST(configurationitems) AS t(configurationItem) WHERE "$path" LIKE '%ConfigHistory%' AND configurationItem.configurationItemCaptureTime >= '2021-06-01T%' AND configurationItem.configurationItemCaptureTime <= '2021-06-03T%' AND configurationItem.resourceType = 'AWS::EC2::Instance' ORDER BY configurationItem.resourceId DESC
上記のクエリを実行することで、ある任意の期間内にどのAWSリソースタイプの、どのAWSリソースに対して、いつ、どのような構成変更があったのかを調べることができます。この例ではAWSリソースタイプとしてEC2を指定しています。configurationItemStatus が何を示しているのかは以下をご覧ください。
- OK – リソース構成の更新
- ResourceDiscovered – 新規構築されたリソースの検出
- ResourceNotRecorded – リソースは検出されたが、Config Recorder がこのタイプのリソースの記録を除外しているため、その構成は記録されていない
- ResourceDeleted – リソースの削除
- ResourceDeletedNotRecorded – リソースは削除されたが、Config Recorde がこのタイプのリソースの記録を除外しているため、その構成は記録されていない
ConfigurationItem - AWS Config
Athena で実行したクエリを使い回す
実行するクエリを毎回記述するのは面倒ですが、Athena では実行するクエリを保存しておくことが可能です。
まとめ
今回はAmazon Athenaを利用してS3に保管されているAWS Config のログを調査する方法を調べてみました。Athena を初めて使ったため検証に苦戦してしまいましたが、私と同様にこれからAthena を使ってログ調査を行う予定がある方のお役に立てれば幸いです。
また、AWS CloudTrailとVPC Flow Logs のログを調査する方法についても別ブログでまとめていますので是非ご覧ください。
山﨑 翔平 (Shohei Yamasaki) 記事一覧はコチラ
2019/12〜2023/2までクラウドインテグレーション部でお客様のAWS導入支援を行っていました。現在はIE(インターナルエデュケーション)課にて採用周りのお手伝いや新卒/中途オンボーディングの業務をしています。2023 Japan AWS Top Engineers/2023 Japan AWS Ambassadors