1
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 Security Hub × IAM Access Analyzer 統合:未使用アクセスの自動検出と最小権限ポリシー自動生成

1
Last updated at Posted at 2026-05-31

はじめに

2026年5月、AWS Security Hub が IAM Access Analyzer と統合し、未使用の IAM 権限・ロール・認証情報を組織全体で自動検出できるようになりました。さらに、検出した未使用アクセスに基づいて最小権限ポリシーをオンデマンドで自動生成する機能も追加されています。

「IAM のクリーンアップは大事だとわかっているが、どこから手をつければいいかわからない」という状況を解消する機能です。本記事では仕組みから実践的な運用設計まで解説します。


1. 背景:なぜ未使用 IAM アクセスが問題なのか

IAM は「設定して終わり」になりがちです。結果として以下の問題が発生します:

ゾンビ権限の蓄積:退職したメンバーのアクセスキー、使われなくなったロール、過剰な権限が付与されたポリシーが長期間放置される。

攻撃対象領域の拡大:使われていない権限でも、それが存在する限り攻撃者に悪用されるリスクがある。s3:* のような過剰権限は典型例。

コンプライアンス上のリスク:PCI DSS・ISO27001 などでは最小権限の原則(Principle of Least Privilege)の遵守が求められる。定期的なアクセス棚卸しを手動で行うのは現実的ではない。


2. 統合の仕組み

2.1 コンポーネントの関係

AWS Organizations
    │
    ▼
Security Hub(管理アカウント)
    │
    ├── 自動作成: IAM Access Analyzer(サービスリンク)
    │       各メンバーアカウントに自動展開
    │       ↓ 90日間のアクティビティを評価
    │       ↓ 未使用アクセスの findings を生成
    │
    ├── 統合コンソール(Identity Risk 専用ビュー)
    │       脅威 / 露出 / ポスチャの findings と同一画面で管理
    │
    └── 最小権限ポリシー生成
            ↓ 実際の使用パターンに基づいて自動生成
            → 管理者がレビュー → IAM ポリシーとして適用

2.2 サービスリンク IAM Access Analyzer の自動作成

Security Hub を AWS Organizations で有効化すると、各メンバーアカウントに サービスリンク IAM Access Analyzer が自動作成されます。追加設定は不要です。

このアナライザーが収集するのは以下です:

  • IAM ロールの最終使用日時
  • IAM ユーザーのアクセスキー・パスワードの最終使用日時
  • 各ロールに付与された権限と実際に使用されたサービス・アクション

90日間のウィンドウ:CloudTrail の記録に基づき、直近90日間で一度も使用されていない権限・認証情報・ロールを「未使用」と判定します。


3. 検出される findings の種類

3.1 Finding の分類

Finding タイプ 説明 重要度
UnusedIAMRole 90日間未使用のロール Medium
UnusedIAMUserAccessKey 90日間未使用のアクセスキー High
UnusedIAMUserPassword 90日間未使用のコンソールパスワード Medium
UnusedPermission ロールに付与されているが使用されていない権限 Low〜Medium

3.2 Finding の例(JSON 形式)

{
  "SchemaVersion": "2018-10-08",
  "Id": "arn:aws:access-analyzer:ap-northeast-1:123456789012:analyzer/security-hub-analyzer/finding/EXAMPLE-FINDING-ID",
  "ProductArn": "arn:aws:securityhub:ap-northeast-1::product/aws/access-analyzer",
  "GeneratorId": "aws/access-analyzer",
  "AwsAccountId": "123456789012",
  "Types": ["Software and Configuration Checks/AWS Security Best Practices/Unused Access"],
  "Severity": {"Label": "HIGH"},
  "Title": "Unused IAM user access key",
  "Description": "IAM user 'deploy-bot' has access key AKIAIOSFODNN7EXAMPLE that has not been used in 90 days.",
  "Resources": [
    {
      "Type": "AwsIamAccessKey",
      "Id": "arn:aws:iam::123456789012:user/deploy-bot",
      "Details": {
        "AwsIamUser": {
          "UserName": "deploy-bot",
          "CreateDate": "2023-01-15T00:00:00Z",
          "UserPolicyList": []
        }
      }
    }
  ]
}

4. 最小権限ポリシーの自動生成

4.1 仕組み

IAM Access Analyzer は、CloudTrail に記録された実際の API 呼び出し履歴を解析し、そのロールが実際に使用した権限だけを含む IAM ポリシーを生成します。

CloudTrail ログ(90日分)
    │
    ▼
IAM Access Analyzer(使用パターン分析)
    │
    ▼ 実際に呼ばれた API のみ抽出
    ├── ec2:DescribeInstances(使用あり)
    ├── s3:GetObject(バケット: my-app-bucket のみ)
    ├── s3:PutObject(バケット: my-app-bucket のみ)
    └── ※ s3:DeleteObject(付与されているが未使用) → 除外
    ▼
最小権限ポリシー(JSON)

4.2 AWS CLI での生成手順

# 1. アナライザーの ARN を確認
aws accessanalyzer list-analyzers \
  --query 'analyzers[?type==`ACCOUNT_UNUSED_ACCESS`].arn' \
  --output text

# 2. 対象ロールの最小権限ポリシーを生成
aws accessanalyzer generate-access-preview \
  --analyzer-arn "arn:aws:accessanalyzer:ap-northeast-1:123456789012:analyzer/security-hub-analyzer" \
  --principal-arn "arn:aws:iam::123456789012:role/MyApplicationRole" \
  --query 'id' \
  --output text
# → access-preview-id が返る

# 3. 生成されたポリシーを取得
aws accessanalyzer get-generated-policy \
  --job-id "<access-preview-id>" \
  --include-service-level-template

4.3 生成されたポリシーの例

既存の過剰なポリシーと生成された最小権限ポリシーの比較:

既存のポリシー(過剰な権限)

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": "s3:*",
      "Resource": "*"
    },
    {
      "Effect": "Allow",
      "Action": "ec2:*",
      "Resource": "*"
    }
  ]
}

自動生成された最小権限ポリシー

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "s3:GetObject",
        "s3:PutObject",
        "s3:ListBucket"
      ],
      "Resource": [
        "arn:aws:s3:::my-app-bucket",
        "arn:aws:s3:::my-app-bucket/*"
      ]
    },
    {
      "Effect": "Allow",
      "Action": [
        "ec2:DescribeInstances",
        "ec2:DescribeSecurityGroups"
      ],
      "Resource": "*"
    }
  ]
}

s3:* が必要最低限のアクションに絞られ、リソースも特定バケットに限定されています。


5. 運用設計:Security Hub との統合を最大限活用する

5.1 EventBridge による自動アクション

Security Hub の findings を EventBridge でキャッチして、自動アクションを設定できます。

# 未使用アクセスキーを自動無効化する Lambda の例
import boto3
import json

iam = boto3.client('iam')

def lambda_handler(event, context):
    detail = event['detail']
    
    # Security Hub finding から情報を抽出
    finding = detail['findings'][0]
    finding_type = finding['Types'][0]
    
    if 'UnusedIAMUserAccessKey' not in finding_type:
        return
    
    # 重要度が HIGH の場合のみ自動対処
    if finding['Severity']['Label'] != 'HIGH':
        return
    
    # リソース情報を取得
    resource = finding['Resources'][0]
    user_name = resource['Details']['AwsIamUser']['UserName']
    
    # アクセスキーの一覧を取得して無効化
    keys = iam.list_access_keys(UserName=user_name)
    for key in keys['AccessKeyMetadata']:
        if key['Status'] == 'Active':
            iam.update_access_key(
                UserName=user_name,
                AccessKeyId=key['AccessKeyId'],
                Status='Inactive'
            )
            print(f"Disabled access key {key['AccessKeyId']} for user {user_name}")
    
    # Security Hub の finding をレビュー済みに更新
    sh_client = boto3.client('securityhub')
    sh_client.batch_update_findings(
        FindingIdentifiers=[{
            'Id': finding['Id'],
            'ProductArn': finding['ProductArn']
        }],
        Note={
            'Text': f'Access key automatically disabled by Lambda.',
            'UpdatedBy': 'auto-remediation-lambda'
        },
        Workflow={'Status': 'RESOLVED'}
    )

5.2 EventBridge ルールの設定

{
  "source": ["aws.securityhub"],
  "detail-type": ["Security Hub Findings - Imported"],
  "detail": {
    "findings": {
      "Types": [{"prefix": "Software and Configuration Checks/AWS Security Best Practices/Unused Access"}],
      "Severity": {
        "Label": ["HIGH", "CRITICAL"]
      },
      "WorkflowState": ["NEW"]
    }
  }
}

5.3 定期レビューワークフローの設計

全自動での修正は危険を伴う場合もあります(例:バッチジョブが月次実行のため90日未使用に見えるケース)。以下のような段階的なアプローチを推奨します。

Week 1: Findings の棚卸し
    │
    ├── UnusedIAMUserAccessKey(HIGH)→ 即時対応(無効化)
    ├── UnusedIAMRole(MEDIUM)→ ロール所有者に確認メール送付
    └── UnusedPermission(LOW)→ 月次レビューキューに追加

Week 2-4: ロール所有者の確認
    │
    ├── 返答あり・不要→ 削除
    ├── 返答あり・必要→ Finding に注釈を付けてサプレス
    └── 返答なし→ エスカレーション

Month 2以降: 最小権限ポリシーの段階的適用
    │
    └── 生成ポリシーをテスト環境で適用 → 問題なければ本番に適用

6. コストについて

本機能は Security Hub Essentials に追加コストなしで含まれます(2026年5月時点)。ただし Security Hub 自体の利用料金は発生します。

コンポーネント コスト
Security Hub Essentials $0.001/finding/month(上限あり)
IAM Access Analyzer(サービスリンク) 追加コストなし
最小権限ポリシー生成 追加コストなし
EventBridge + Lambda(自動修復) 通常の Lambda・EventBridge 料金

7. 注意点

90日ウィンドウの落とし穴:月次・四半期実行のバッチジョブや、障害時のみ使うbreak-glass用ロールは「未使用」と判定されます。必ず所有者への確認フローを設けてください。

CloudTrail が有効である必要がある:IAM Access Analyzer は CloudTrail のデータを元に分析します。CloudTrail が無効なアカウントやリージョンでは正確な分析ができません。必ずマルチリージョンの証跡(Trail)を有効にしてください。

既存の Access Analyzer との共存:外部アクセス検出用(ACCOUNT タイプ)の Access Analyzer と、今回の未使用アクセス検出用(ACCOUNT_UNUSED_ACCESS タイプ)は別のアナライザーです。Security Hub が自動作成するのは後者です。


8. まとめ

Security Hub と IAM Access Analyzer の統合により、これまで手動で行っていた IAM クリーンアップ作業を大幅に効率化できます。

作業 従来 今回の統合後
未使用権限の発見 手動棚卸し(スプレッドシート管理) 自動検出・一元管理
最小権限ポリシーの作成 手動で権限調査・ポリシー記述 CloudTrail 分析から自動生成
対応優先度の判断 担当者の経験に依存 Severity ベースで自動分類
修復アクション 手動実行 EventBridge + Lambda で自動化可能

「最小権限の原則」を継続的に維持する仕組みを構築するための重要なピースが揃いました。AWS Organizations で Security Hub を使っている環境であれば、追加コストなしで使い始められるので、ぜひ有効化してみてください。


参考

1
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
1
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?