IAM Access Analyzerで外部アクセスポリシーを検出しよう(発展編)

記事タイトルとURLをコピーする

以前にIAM Access Analyzerを紹介する記事を書きましたが、今回はその発展編です。 blog.serverworks.co.jp

複数リージョンでIAM Access Analyzerを有効化

IAM Access Analyzerはリージョンリソースです。
S3バケット等が各リージョンで作成される可能性がある以上、全リージョンでIAM Access Analyzerを有効化が推奨されます。

Analyzerは、S3 バケット・KMS キー・Lambda関数とLambdaレイヤー・SQS キューといった各リージョンのリソースと、IAM ロールといったグローバルリソースを分析します。 メール通知の仕組みも追加すると、以下の構成図になります。

f:id:swx-watanabe:20210107112841p:plain

S3バケット等(リージョンリソース)で問題を検出すると、所属リージョンのAnalyzerからイベント通知が出て、SNS経由でメール送信されます。

しかし、IAMロール(グローバルリソース)で問題を検出すると、全リージョンのAnalyzerが検出します。これにより重複したメール通知を受け取ることがありますが、そんな仕様のようです。

スペースの都合上、構成図では3リージョンしか書いてませんが、実際は現在10以上のリージョンがあります。このような場合、CloudFormation StackSetsを使って設定すると便利です。

CloudFormationで設定する

試した結果、以下のようなテンプレートとなりました。

AWSTemplateFormatVersion: 2010-09-09
Description: Create IAM Access Analzer

Parameters:
  EnableIAMAccessAnalyzer:
    Type: String
    Default: true
    AllowedValues: [true, false]
  TrustedAccountId:
    Type: String
    AllowedPattern: ^\d{12}$|^$
  SNSNotificationIAMAccessAnalyzer:
    Description: Presence of SNS notification of IAMAccessAnalyzer
    Type: String
    Default: true
    AllowedValues: [true, false]
  Email:
    Description: Email address to notify when finding analyzer
    Type: String
    AllowedPattern: ^[a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$

Metadata:
  AWS::CloudFormation::Interface:
    ParameterGroups:
      -
        Label:
          default: "IAMAccessAnalyzerConfiguration"
        Parameters:
          - EnableIAMAccessAnalyzer
          - TrustedAccountId
          - SNSNotificationIAMAccessAnalyzer
      -
        Label:
          default: "Notification Email address"
        Parameters:
          - Email

Conditions:
  CreateIAMAccessAnalyzer: !Equals [!Ref EnableIAMAccessAnalyzer, "true"]
  CreateIAMAccessAnalyzerSNS: !Equals [!Ref SNSNotificationIAMAccessAnalyzer, "true"]
  CreateIAMAccessAnalyzerTrustedAccountId: !Not [!Equals [!Ref TrustedAccountId, ""]]

Resources:
  Analyzer:
    Type: AWS::AccessAnalyzer::Analyzer
    Condition: CreateIAMAccessAnalyzer
    Properties:
      AnalyzerName: AccessAnalyzer
      Type: ACCOUNT
      ArchiveRules:
        !If
        - CreateIAMAccessAnalyzerTrustedAccountId
        - 
          - RuleName: 'TrustedAccounts'
            Filter:
              - Property: 'principal.AWS'
                Eq:
                  - Ref: TrustedAccountId
        - !Ref "AWS::NoValue"
  AnalyzerNotificationTopic:
    Type: AWS::SNS::Topic
    Condition: CreateIAMAccessAnalyzerSNS
    Properties:
      TopicName: AccessAnalyzerTopic
      Subscription:
        - Endpoint: !Ref Email
          Protocol: email
  AnalyzerEventRule:
    Type: AWS::Events::Rule
    Condition: CreateIAMAccessAnalyzerSNS
    Properties:
      Name: AlertAccessAnalyzerFindings
      EventPattern:
        source:
          - aws.access-analyzer
        detail-type:
          - Access Analyzer Finding
      Targets:
        - Arn: !Ref AnalyzerNotificationTopic
          Id: AccessAnalyzer
          InputTransformer:
            InputPathsMap:
              account: $.account
              region: $.region
              resourceType: $.detail.resourceType
              resourceName: $.detail.resource
              CreatAt: $.detail.createdAt
              updatedAt: $.detail.updatedAt
            InputTemplate: |
              "IAM Access Analzerの結果を検出しました。"
              "アカウント: <account>"
              "リージョン: <region>"
              "リソースタイプ: <resourceType>"
              "リソース名: <resourceName>"
              "作成日: <CreatAt>"
              "更新日: <updatedAt>"
              "詳細(外部プリンシパル等)はIAM Access Analyzer コンソール( https://<region>.console.aws.amazon.com/access-analyzer/home?region=<region>#/findings )を確認してください。"
  AnalyzerEventTopicPolicy:
    Type: AWS::SNS::TopicPolicy
    Condition: CreateIAMAccessAnalyzerSNS
    Properties:
      PolicyDocument:
        Statement:
          - Effect: Allow
            Principal:
              Service: events.amazonaws.com
            Action: 'sns:Publish'
            Resource: '*'
      Topics:
        - !Ref AnalyzerNotificationTopic

Outputs:
  AnalyzerOutput:
    Description: The ID of the Analyzer
    Value: !Ref Analyzer
  AnalyzerNotificationTopicOutput:
    Description: The ID of the AnalyzerNotificationTopic
    Value: !Ref AnalyzerNotificationTopic
  AnalyzerEventRuleOutput:
    Description: The ID of the AnalyzerEventRule
    Value: !GetAtt AnalyzerEventRule.Arn
  AnalyzerTrustedAccountsOutput:
    Description: The ID of the AnalyzerTrustedAccounts
    Value: !Ref TrustedAccountId

上記のテンプレート使用時の画面は以下の通りです。

f:id:swx-watanabe:20210107141516p:plain

検出時の通知メール

以下のような感じのメール通知がされます。

"IAM Access Analzerの結果を検出しました。"
"アカウント: 123456789012"
"リージョン: ap-northeast-1"
"リソースタイプ: AWS::S3::Bucket"
"リソース名: arn:aws:s3:::xxxxxxxxx"
"作成日: 2021-01-07T05:57:21.293Z"
"更新日: 2021-01-07T05:57:21.293Z"
"詳細(外部プリンシパル等)はIAM Access Analyzer コンソール( https://ap-northeast-1.console.aws.amazon.com/access-analyzer/home?region=ap-northeast-1#/findings )を確認してください。"


--
If you wish to stop receiving notifications from this topic, please click or visit the link below to unsubscribe:
https://sns.ap-northeast-1.amazonaws.com/unsubscribe.html?SubscriptionArn=arn:aws:sns:ap-northeast-1:123456789012:AccessAnalyzerTopic:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx&Endpoint=xxxxxxxxxx@xxxxxx.co.jp

Please do not reply directly to this email. If you have any questions or comments regarding this email, please contact us at https://aws.amazon.com/support

なお、下記仕様のため、メールが送信されるまで時間がかかります。

  • Access Analyzerが結果を更新するのに最大30分かかる。

ポリシーが変更されてから Access Analyzer がリソースを分析して結果を更新するまで、最大で 30 分かかる場合があります。
結果を使用する - AWS Identity and Access Management

  • Access AnalyzerがEventBridgeにイベント送信するのに1時間かかる。

Access Analyzer は、アカウント内でイベントが発生してから約 1 時間以内に新しい結果や、既存の結果のステータス更新に関するイベントを EventBridge に送信します。
Amazon EventBridge による AWS IAM Access Analyzer のモニタリング - AWS Identity and Access Management

スイッチロールについて

Analyzerは、いわゆる スイッチロール 設定がある場合に検出をします。 あらかじめ、わかっている場合は問題のないアカウントIDとしてホワイトリスト的な意味合いでアーカイブルールに登録します。 そうすれば検出しても自動的にアーカイブされます。

設定箇所は以下の画面のところなのですが、既に述べたようにIAMロールに関しては、全てのリージョンで検出されるため全てのリージョンでアーカイブする必要があります。 それでは大変なので、CloudFormation実行時に信頼するアカウントIDとしてパラメータで渡し、アーカイブルールを設定しています。

f:id:swx-watanabe:20210107124240p:plain

このテンプレートの既知の問題点

  1. SNSの登録確認メールをリージョンごとに受信し、Subscription Confirmationボタンをクリックする必要があります。少し面倒ですね。

  2. パラメータから入力できる「信頼するアカウント」と「メールアドレス」は1つだけです。CloudFormationで任意の数のパラメータを受け付けて上手く設定できる方法がなさそうでした。もし複数ある場合は、パラメータからの入力は諦めた方が良さそうです。

まとめ

  • IAM Access Analyzerはリージョンリソースである
  • 全てのリージョンで設定するにはCloudFormationStackSetsがお勧め
  • 全てのリージョンのAnalyzerが個別にIAMロールを分析するので結果が重複する
  • アーカイブルールを上手く使うと運用が楽になるかもしれない

渡辺 信秀 (記事一覧)