複数の AWS アカウントに対して IAM ロールが特定のアクションを許可しているかどうか確認するシェルスクリプトを作成してみた

複数の AWS アカウントに対して IAM ロールが特定のアクションを許可しているかどうか確認するシェルスクリプトを作成してみた

Clock Icon2024.09.29

複数の AWS アカウントの IAM ロールに対して、特定のアクションが許可されているかどうかを確認するシェルスクリプトを作成したため、備忘録も兼ねてブログにします。

以前に公開した次のブログの内容を複数のアカウントで確認できるようにしました。

https://dev.classmethod.jp/articles/output-whether-iam-roles-have-permission-for-specified-actions/

IAM ロールが特定アクションを許可しているか確認するスクリプト

複数のアカウントに対して IAM ロールが特定アクションを許可しているか確認するシェルスクリプトです。例外処理は含めていないため、あくまでサンプルと理解していただけますと幸いです。

#!/bin/bash

# 調査対象のAWSアカウント一覧
ACCOUNT_ID_LIST=(111122223333 444455556666)

# 調査対象のAWSアカウントで事前に作成しているIAMロール名
ROLE_NAME="test-tool-access-role"

# AWS CloudTrailに記録されるセッション名
ROLE_SESSION_NAME=" test-tool"

# IAMロールで許可されているかどうか確認するアクション
ACTION_NAME="iam:CreateRole iam:AttachRolePolicy iam:PutRolePolicy"

for account_id in "${ACCOUNT_ID_LIST[@]}"; do
    echo "### Account ID: ${account_id}"

    # AssumeRoleにより一時的なクレデンシャルを取得
    assume_role_output=$(aws sts assume-role --role-arn arn:aws:iam::$account_id:role/$ROLE_NAME --role-session-name $ROLE_SESSION_NAME)

    access_key_id=$(echo "${assume_role_output}" | jq -r '.Credentials.AccessKeyId')
    secret_access_key=$(echo "${assume_role_output}" | jq -r '.Credentials.SecretAccessKey')
    session_token=$(echo "${assume_role_output}" | jq -r '.Credentials.SessionToken')

    # IAMロール一覧を取得してIAM Policy SimulatorでACTION_NAMEの許可があるか確認
    AWS_ACCESS_KEY_ID=$access_key_id AWS_SECRET_ACCESS_KEY=$secret_access_key AWS_SESSION_TOKEN=$session_token \
    aws iam list-roles --query='Roles[?!(starts_with(RoleName,`AWSServiceRoleFor`))].[Arn]' --output text \
    | while read role_arn; do
        echo "${role_arn}"
        AWS_ACCESS_KEY_ID=$access_key_id AWS_SECRET_ACCESS_KEY=$secret_access_key AWS_SESSION_TOKEN=$session_token \
        aws iam simulate-principal-policy \
            --policy-source-arn ${role_arn} \
            --action-names ${ACTION_NAME} \
            --query EvaluationResults[].[EvalActionName,EvalDecision] \
            --output text
    done
done

本スクリプトを実行するアカウントから調査対象のアカウントに AssumeRole して調査します。そのため、事前に調査対象のアカウントでスクリプト実行アカウントを信頼する IAM ロールを作成しておく必要があります。

2024 年 9 月 28 日時点の AWS CloudShell では追加のソフトウェアのインストールの必要なく実行できます。

実行結果例を一部抜粋して掲載します。
allowed は許可、implicitDeny は暗黙的な拒否を示します。

$ sh test-tool.sh
### Account ID: 444455556666
()
arn:aws:iam::444455556666:role/test-access-role
iam:CreateRole  implicitDeny
iam:AttachRolePolicy    implicitDeny
iam:PutRolePolicy       implicitDeny
arn:aws:iam::444455556666:role/test-admin-role-for-idc
iam:CreateRole  allowed
iam:AttachRolePolicy    allowed
iam:PutRolePolicy       allowed
()
### Account ID: 111122223333
()
arn:aws:iam::111122223333:role/test-access-role
iam:CreateRole  implicitDeny
iam:AttachRolePolicy    implicitDeny
iam:PutRolePolicy       implicitDeny
arn:aws:iam::111122223333:role/test-org-aggregator-role
iam:CreateRole  implicitDeny
iam:AttachRolePolicy    implicitDeny
iam:PutRolePolicy       implicitDeny
()

変数は値を変更して利用する必要があります。

変数名 説明
ACCOUNT_ID_LIST 調査対象の AWS アカウント一覧を指定
ROLE_NAME 調査対象の AWS アカウントで事前に作成している IAM ロール名を指定
ROLE_SESSION_NAME AWS CloudTrail に記録されるセッション名を指定
ACTION_NAME IAM ロールで許可されているかどうか確認するアクションを指定

ACCOUNT_ID_LIST

調査対象の AWS アカウント一覧を指定します。
AWS アカウント数が多い場合は、別ファイルで管理したほうが楽かもしれません。

また、AWS Organizations 環境の場合は AWS Organizations の API を利用してアカウント一覧を取得する方法もあります。次のブログがその方法を利用しています。

https://dev.classmethod.jp/articles/aws-cli-multi-account-execution/

ROLE_NAME

調査対象の AWS アカウントで利用する IAM ロール名を指定します。IAM ロールは事前に作成しておく必要があります。

本ブログのスクリプトで実行している IAM ロールを対象とした IAM Policy Simulator の実行に必要な権限は次のユーザーガイドに記載があります。

IAM ロールにアタッチする IAM ポリシーのポリシー例です。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "iam:GetContextKeysForCustomPolicy",
                "iam:GetRole",
                "iam:GetPolicyVersion",
                "iam:SimulatePrincipalPolicy",
                "iam:SimulateCustomPolicy",
                "iam:GetPolicy",
                "iam:ListAttachedRolePolicies",
                "iam:ListRoles",
                "iam:ListRolePolicies",
                "iam:GetRolePolicy",
                "iam:GetContextKeysForPrincipalPolicy"
            ],
            "Resource": "*"
        }
    ]
}

IAM ロールの信頼ポリシー例です。スクリプトを実行するアカウントを信頼します。下記例の root の記載はアカウント内の全ての IAM ユーザーや IAM ロールなどに対する信頼のため、スクリプトを実行する主体が限られている場合は信頼する条件を絞ったほうが良いと思います。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::111122223333:root"
            },
            "Action": "sts:AssumeRole"
        }
    ]
}

上記の内容を設定する CloudFormation テンプレートも掲載します。パラメータの TrustedAccountID は信頼ポリシーで指定するスクリプト実行アカウントの ID を指定します。

AWSTemplateFormatVersion: 2010-09-09
Description: Create IAM Role

Parameters:
  IAMRoleName:
    Type: String
    Description: IAM Role Name
    Default: test-tool-access-role
  IAMPolicyName:
    Type: String
    Description: IAM Policy Name
    Default: test-tool-access-policy
  TrustedAccountID:
    Type: String
    Description: Trusted Account ID
    Default: 111122223333

Metadata:
  AWS::CloudFormation::Interface:
    ParameterGroups:
      - Label:
          default: AWS IAM Role
        Parameters:
          - IAMRoleName
          - IAMPolicyName
          - TrustedAccountID

Resources:
  IAMRole:
    Type: "AWS::IAM::Role"
    Properties:
      RoleName: !Ref IAMRoleName
      Path: "/"
      AssumeRolePolicyDocument:
        Version: "2012-10-17"
        Statement:
        - Effect: "Allow"
          Principal:
            AWS:
            - !Sub "arn:aws:iam::${TrustedAccountID}:root"
          Action: "sts:AssumeRole"
      ManagedPolicyArns:
        - !Ref IAMPolicy
  IAMPolicy:
    Type: 'AWS::IAM::ManagedPolicy'
    Properties:
      ManagedPolicyName: !Ref IAMPolicyName
      PolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Effect: Allow
            Action:
              - 'iam:GetContextKeysForCustomPolicy'
              - 'iam:GetRole'
              - 'iam:GetPolicyVersion'
              - 'iam:SimulatePrincipalPolicy'
              - 'iam:SimulateCustomPolicy'
              - 'iam:GetPolicy'
              - 'iam:ListAttachedRolePolicies'
              - 'iam:ListRoles'
              - 'iam:ListRolePolicies'
              - 'iam:GetRolePolicy'
              - 'iam:GetContextKeysForPrincipalPolicy'
            Resource: '*'

ROLE_SESSION_NAME

AssumeRole により調査対象アカウントで AWS CLI を実行する際に AWS CloudTrail に記録されるセッション名を指定します。

調査対象アカウントで記録される IAM Policy Simulator の CloudTrail イベント例ですイベント名は SimulatePrincipalPolicy であり、イベント履歴画面では「ユーザー名」として記録されています。

multi-account-iam-policy-simulator-script-1

1 つの SimulatePrincipalPolicy イベントの詳細です。

{
    "eventVersion": "1.10",
    "userIdentity": {
        "type": "AssumedRole",
        "principalId": "AROAYS2EXAMPLEEXAMPLE:test-tool",
        "arn": "arn:aws:sts::444455556666:assumed-role/test-tool-access-role/test-tool",
        "accountId": "444455556666",
        "accessKeyId": "ASIAYS2NR3GH7D7EFJVR",
        "sessionContext": {
            "sessionIssuer": {
                "type": "Role",
                "principalId": "AROAYS2EXAMPLEEXAMPLE",
                "arn": "arn:aws:iam::444455556666:role/test-tool-access-role",
                "accountId": "444455556666",
                "userName": "test-tool-access-role"
            },
            "attributes": {
                "creationDate": "2024-09-28T14:35:37Z",
                "mfaAuthenticated": "false"
            }
        }
    },
    "eventTime": "2024-09-28T14:36:52Z",
    "eventSource": "iam.amazonaws.com",
    "eventName": "SimulatePrincipalPolicy",
    "awsRegion": "us-east-1",
    "sourceIPAddress": "18.176.236.26",
    "userAgent": "aws-cli/2.17.57 md/awscrt#0.21.2 ua/2.0 os/linux#6.1.109-118.189.amzn2023.x86_64 md/arch#x86_64 lang/python#3.12.6 md/pyimpl#CPython exec-env/CloudShell cfg/retry-mode#standard md/installer#exe md/distrib#amzn.2023 md/prompt#off md/command#iam.simulate-principal-policy",
    "requestParameters": {
        "policySourceArn": "arn:aws:iam::444455556666:role/test-tool-access-role",
        "actionNames": [
            "iam:CreateRole",
            "iam:AttachRolePolicy",
            "iam:PutRolePolicy"
        ]
    },
    "responseElements": null,
    "requestID": "44430e83-9474-471a-a9a3-9d67e89f85ca",
    "eventID": "9829d500-6d6e-4b96-8d12-967247c56d0c",
    "readOnly": true,
    "eventType": "AwsApiCall",
    "managementEvent": true,
    "recipientAccountId": "444455556666",
    "eventCategory": "Management",
    "tlsDetails": {
        "tlsVersion": "TLSv1.3",
        "cipherSuite": "TLS_AES_128_GCM_SHA256",
        "clientProvidedHostHeader": "iam.amazonaws.com"
    }
}

ACTION_NAME

IAM ロールで許可されているかどうか確認するアクションを指定します。複数指定できます。
aws iam simulate-principal-policyコマンドのaction-namesオプションで指定する値となります。

以上で、シェルスクリプトに関する説明は終わりです。

さいごに

AssumeRole を利用して、複数の AWS アカウントの IAM ロールに対して IAM Policy Simulator を実行する機会があったため、作成したシェルスクリプトを紹介しました。今回は IAM Policy Simulator の利用でしたが、調査したい内容によってはシェルスクリプトで AWS CLI 実行ではなく、AWS Config の高度なクエリで楽に実現できる場合もあると思います。また、AWS Organizations 環境の場合は、AWS Resource Explorer も活用できるかもしれません。

https://dev.classmethod.jp/articles/advanced-queries-in-aws-config-to-find-resources-in-organizations/

https://dev.classmethod.jp/articles/aws-resource-explorer-multi-account-view/

以上、このブログがどなたかのご参考になれば幸いです。

Share this article

facebook logohatena logotwitter logo

© Classmethod, Inc. All rights reserved.