![[レポート]KMS暗号化キーの利用状況を分析する #AWSreInforce #DAP353](https://images.ctfassets.net/ct0aopd36mqt/6vZd9zWZvlqOEDztYoZCro/7349aaad8d597f1c84ffd519d0968d43/eyecatch_awsreinforce2025_1200x630-crunch.png)
[レポート]KMS暗号化キーの利用状況を分析する #AWSreInforce #DAP353
はじめに
こんにちは、コンサルティング部の神野です。
AWS re:Inforce 2025で参加したBuilders' Session「DAP353: Leveraging generative AI for data protection insights」について、実際に手を動かして学んだ内容を共有します。
このセッションを選んだ理由は、AWS KMSの暗号化キーの使用状況や権限設定を効率的に可視化する方法ってどんなものか知りたく、このセッションを選んでみました。
セッション概要
タイトル: DAP353: Leveraging generative AI for data protection insights
概要:
Discover practical methods for managing encryption keys and access policies across multiple organizational accounts through natural language queries. This session demonstrates how to gain data protection insights by combining serverless functions with audit logs and analytics tools to create interactive dashboards. Learn to visualize enterprise-wide encryption key usage and answer critical questions about key utilization and resource protection. Walk away with implementable solutions for improving encryption key visibility and control across your accounts. You must bring your laptop to participate.
- セッション種別: Builders' session
- Level: 300 - Advanced
- サービス: Amazon Athena, AWS Key Management Service (AWS KMS), Amazon QuickSight
会場の雰囲気
セッションはPennsylvania Convention CenterのTerrace Ballroomで開催されました。参加者は1テーブル約8名と比較的少人数で、じっくりとハンズオンに取り組める環境でした。
講師の方がスイスのチューリッヒから来られていて、参加者もカナダ、ヨーロッパなど様々な国から集まっており、国際的な雰囲気の中でのワークショップとなりました。最初に参加者同士の自己紹介タイムがあり、それぞれがKMS管理に関する課題意識を持って参加していることがわかりました。
講師の方が実際のお客様事例(10年間でKMSキーが無秩序に増えてしまい、セキュリティ監査で問題が発覚した企業)を共有してくださったのは印象的でした。この課題は多くの企業で共通しているようで、参加者からも共感の声が上がっていました。
セッション内容
背景:Example Corp社の課題
ワークショップでは、架空の企業「Example Corp」のシナリオを使って学習を進めました。Example Corp社は以下のような課題を抱えていました。
- 数百のAWSアカウント、数千のKMSキーを保有
- 各チームが独自にKMSキーを管理し、全体像が把握できない状態
- セキュリティ監査で過度に広い権限設定が発覚
- KMSの使用状況やコストの最適化ができない
アーキテクチャ
今回構築したソリューションは、マルチアカウント環境でKMSキーの情報を収集・分析し、QuickSightで可視化するものです。
アーキテクチャの主要コンポーネント
-
Member Accounts(メンバーアカウント)
-
各アカウントのKMSキー情報とCloudTrailログを収集
-
Cross-Account Roleを使用して中央アカウントからアクセス
-
-
KMS Governance Account(ガバナンスアカウント)
-
Step Functionsでワークフローを制御
-
Lambda関数でデータ収集と分析を実行
-
S3にデータを保存(KMSKeys、KMSLastUsed)
-
AthenaとQuickSightで分析・可視化
-
Step Functionsによる処理フロー
ワークショップでは、既にデプロイされた環境でStep Functionsがどのように動作するかを確認しました。
基本的な流れは以下の3ステップです。
- ListAccounts Lambda: AWS Organizationsからアカウントリストを取得
- Map State: 各アカウントに対して最大10並列で処理を実行
- GetKMSData Lambda: 各アカウントからKMSデータを収集・分析
Map Stateで10並列まで処理できるようにしていました。数百のアカウントを処理する必要があるExample Corp社のような大規模環境では、この並列処理機能で時間短縮を図るためかと思いました。
Workflowの定義
{
"Comment": "KMS Insights Data Collection Workflow",
"StartAt": "ListAccounts",
"States": {
"ListAccounts": {
"Type": "Task",
"Resource": "arn:aws:states:::lambda:invoke",
"Parameters": {
"FunctionName": "kms-insights-list-accounts"
},
"Next": "ProcessAccounts"
},
"ProcessAccounts": {
"Type": "Map",
"MaxConcurrency": 10,
"ItemsPath": "$.accounts",
"Iterator": {
"StartAt": "GetKMSData",
"States": {
"GetKMSData": {
"Type": "Task",
"Resource": "arn:aws:states:::lambda:invoke",
"Parameters": {
"FunctionName": "kms-insights-get-data",
"Payload.$": "$"
},
"End": true
}
}
},
"End": true
}
}
}
ハンズオン:実際に手を動かしてみて
ワークショップのメインパートは、Lambda関数のコードを修正して機能を追加することでした。最初は「コード修正」と聞いて少し緊張しましたが、実際にやってみると既存のコードがよく整理されていて、何をどこに追加すればいいかがわかりやすかったです。
データ収集機能の理解及び実装
最初に取り組んだのは、KMSキーの情報収集部分でした。generate-kms-insights.py
を開いてみると、すでにKMSキーのエイリアス取得は実装されていましたが、実は他の部分は骨組みだけで、実装が必要でした。
具体的には以下の3つの関数を実装する必要がありました。
_get_key_policies()
- キーポリシーの取得_get_creation_date()
- キー作成日の取得_get_tags()
- タグ情報の取得
思ったより修正作業が多いなと感じましたが、それぞれの実装はパターンが似ていて理解しやすかったです。
ポリシー取得の実装
def _get_key_policies(self, key_id: str):
try:
policy_names = self.kms.list_key_policies(KeyId=key_id)["PolicyNames"]
policies = []
for policy_name in policy_names:
policy = self.kms.get_key_policy(KeyId=key_id, PolicyName=policy_name)
policies.append(json.loads(policy["Policy"]))
return policies
except botocore.exceptions.ClientError as e:
logger.warning(f"Error getting policies for key {key_id}: {e}")
return []
作成日取得の実装
def _get_creation_date(self, key_id: str):
try:
response = self.kms.describe_key(KeyId=key_id)
return response["KeyMetadata"]["CreationDate"].strftime("%Y-%m-%d %H:%M:%S")
except botocore.exceptions.ClientError as e:
logger.warning(f"Error getting creation date for key {key_id}: {e}")
return None
タグ取得の実装
タグを取得する処理は実装済みであったので、呼び出しだけ追記しました。
# Get tags
tags = self._get_tags(key_id)
key_object["Tags"] = tags
これで4つのデータタイプ(エイリアス、ポリシー、作成日、タグ)をすべて収集できるようになりました。
CloudTrailとの連携
CloudTrailからKMS使用履歴を取得する部分では、少し躓きました。最初、どのイベントをフィルタリングすればいいのか迷ったんですが、ハンズオンでは「まずはDecrypt、Encrypt、GenerateDataKeyの3つから始めましょう」とアドバイスがあったのでそこから進めていきました。
config.py
ファイルを見てみると、VALID_ACTIONS
という変数にこれらのアクションがすでに定義されていて、「あ、ここに追加すればいいんだ」とすぐに理解できました。
# デフォルトの設定
VALID_ACTIONS = ['Decrypt', 'Encrypt', 'GenerateDataKey']
# 権限変更系のアクションも追加
VALID_ACTIONS = ['Decrypt', 'Encrypt', 'GenerateDataKey',
'CreateGrant', 'DisableKeyRotation',
'GetKeyPolicy', 'PutKeyPolicy']
実際に、CreateGrantやPutKeyPolicyなど、権限変更系のアクションも追加してみました。
セキュリティ分析ロジックの実装
今回のワークショップで一番勉強になったのは、KMSキーポリシーの分析ロジックを実装する部分でした。Example Corp社が定めた4つのガイドラインに基づいて、セキュリティ上の懸念事項を検出する処理を追加する必要がありました。
特に印象的だったのは、以下のようなチェックポイントでした。
- アカウントrootへの権限付与:一見便利そうですが、IAM経由で誰でも管理できてしまうリスクがある
- ワイルドカード権限(kms:*):必要以上に広い権限は避けるべき
- IAMユーザーへの直接権限付与:ロールベースのアクセス管理が推奨される
- 外部アカウントからのアクセス:意図しないクロスアカウントアクセスのリスク
実装自体はシンプルな条件分岐でしたが、「なぜこれがリスクなのか」を理解しながらコードを書けたのが良かったです。実際に実装したコードはこんな感じです。
def _insight_filler(self, principal_service, account_number,
current_account_number, action):
concern_list = []
# アカウントrootへの権限付与をチェック
# IAM経由で誰でも管理できてしまうリスク
if principal_service.endswith(":root"):
concern_list.append("Principal is account")
# 過度に広い権限(kms:*)をチェック
if "kms:*" in action:
concern_list.append("Key policy overly permissive")
# IAMユーザーへの直接権限付与をチェック
# ロールベースが推奨される
if ":user" in principal_service:
concern_list.append("Access provided to IAM user")
# 外部アカウントアクセスをチェック
if account_number != current_account_number:
concern_list.append("External account")
return ";".join([x for x in concern_list if x != ""])
Step Functionsを実行してデータ収集
Lambda関数の修正が完了したら、Step Functionsを実行してデータを収集します。
並列処理で問題なく実行完了となりました。
Athenaでのデータ分析とQuickSightでの可視化
データ収集が完了したら、Athenaでクエリを実行してみました。事前に用意されていたビューがとても便利で、KMSキーの設定情報と使用履歴を結合して分析できるようになっていました。
実際のビューは、KMSキーテーブルと最終使用日テーブルをJOINした構造になっていました。
SELECT
kms_keys.keyid, -- KMSキーID
kms_keys.alias, -- キーのエイリアス
kms_keys.accountnumber, -- アカウント番号
kms_keys.principal, -- アクセス許可されたプリンシパル
kms_keys.action, -- 許可されたアクション
kms_keys.concern, -- 検出された懸念事項
kms_keys.creationdate, -- キー作成日
last_used.eventtime, -- 最終使用日時
last_used.username, -- 使用したユーザー
last_used.eventname -- 実行されたKMSアクション
FROM
kms_insights_database.kms_keys_table kms_keys
LEFT JOIN
kms_insights_database.kms_key_last_used_table last_used
ON (kms_keys.keyid = last_used.keyid)
このクエリをベースに以下のような分析が可能になりました。
不要なキーや不適切な権限などがわかるようになりましたね!
-
一度も使われていないKMSキーの特定
WHERE last_used.eventtime IS NULL
-
外部アカウントアクセスが許可されているキーの一覧
先ほどコードで実装したExternal account
を抽出します。WHERE concern LIKE '%External account%'
-
過度に広い権限(kms:*)を持つキーの検出
先ほどコードで実装したoverly permissive
を抽出します。WHERE concern LIKE '%overly permissive%'
-
特定期間使用されていないキーの抽出
WHERE last_used.eventtime < date_add('day', -90, current_date)
残念ながら、QuickSightでのダッシュボード作成は時間切れで完成まで至りませんでしたが、どんなビジュアライゼーションができるかの画面は見ることができました。円グラフで懸念事項別の分布を表示したり、テーブルで詳細情報を確認可能な見栄えの良いダッシュボードでした。
時間がある時に自分でも可視化を再現してみたいですね。
おわりに
このセッションを通じて、KMS管理の課題とその解決アプローチについて実践的に学びました。
セキュリティチェックのロジックを実装する過程で、なぜこれがリスクなのかを考えて実装する体験ができたのはよかったです。特に以下のような場面で活用できそうです。
- 定期的なセキュリティ監査:四半期ごとにKMSキーの権限設定をチェックし、過度に広い権限や意図しない外部アクセスを検出
- コスト最適化:使われていないKMSキーを特定して削除
- インシデント対応:「このキーが不正に使われた可能性がある」といった際に、使用履歴を素早く確認
英語でのセッションでしたが、実際にコードを書いたり、画面を見ながら進めたりする部分が多かったので、思ったより理解しやすかったです。
最後に、このようなハンズオンセッションは、ドキュメントを読むだけでは得られない実践的な知識を身につける絶好の機会でした。
以上、セッションレポートでした!
少しでもお役に立てたら幸いです!!
補足
本ハンズオンで使用したAWS環境を再現するCloudFormationファイルや実装などは下記GitHubに格納されているので、もし興味がある方は確認いただくと良いかと思います!