マルチアカウント環境で非推奨のAWS管理ポリシーを使っているかを高度なクエリで検索してみた

2023.12.27

みなさんこんにちは、杉金です。
少し前にIAMのAWS管理ポリシーCloudWatchFullAccessは廃止予定となりCloudWatchFullAccessV2を使用するよう案内されました。

Identity and access management for Amazon CloudWatch - Amazon CloudWatch

解説したブログもありますので詳細気になる方はご確認ください。

AWSをマルチアカウントで管理している場合、非推奨のAWS管理ポリシーを使っているかのチェックをアカウントごとにしていくのは大変です。
AWS Configで組織のアグリゲータを設定しておくことで、高度なクエリを使ってマルチアカウントのリソース検索ができます。これを利用して検索できないか試してみます。

高度なクエリの使い方については以下のブログを参照ください。

先に結論

高度なクエリから以下3つのクエリによって検索できます。

  • IAMユーザーに対して対象のAWS管理ポリシーを使っているかを検索
  • IAMグループに対して対象のAWS管理ポリシーを使っているかを検索
  • IAMロールに対して対象のAWS管理ポリシーを使っているかを検索

対象のAWS管理ポリシーから利用しているエンティティを逆引きできれば一発で検索できますが、確認する限り高度なクエリではできなさそうでした。また、非推奨という属性はないため、非推奨となっているAWS管理ポリシーをまとめて検索することはできません。あくまで非推奨となっている管理ポリシーを指定した検索となりますのでご了承ください。

IAMユーザーに対して対象のAWS管理ポリシーを使っているかを検索

SELECT
  accountId,
  configuration.userName,
  configuration.attachedManagedPolicies.policyName
WHERE
  resourceType = 'AWS::IAM::User'
  AND configuration.attachedManagedPolicies.policyName = 'CloudWatchFullAccess'

IAMグループに対して対象のAWS管理ポリシーを使っているかを検索

SELECT
  accountId,
  configuration.groupName,
  configuration.attachedManagedPolicies.policyName
WHERE
  resourceType = 'AWS::IAM::Group'
  AND configuration.attachedManagedPolicies.policyName = 'CloudWatchFullAccess'

IAMロールに対して対象のAWS管理ポリシーを使っているかを検索

SELECT
  accountId,
  configuration.roleName,
  configuration.attachedManagedPolicies.policyName
WHERE
  resourceType = 'AWS::IAM::Role'
  AND configuration.attachedManagedPolicies.policyName = 'CloudWatchFullAccess'

高度なクエリの実行例

クエリを実行するとどんな結果が返ってくるのか、AWSマネジメントコンソールから高度なクエリを実行してみます。まずはAWS Configから[高度なクエリ]→[新しいクエリ]を選択します。

IAMユーザーに対する検索

最初にIAMユーザーを検索します。冒頭で紹介したクエリを実行します。

SELECT
  accountId,
  configuration.userName,
  configuration.attachedManagedPolicies.policyName
WHERE
  resourceType = 'AWS::IAM::User'
  AND configuration.attachedManagedPolicies.policyName = 'CloudWatchFullAccess'

クエリスコープに組織のアグリゲータを選び、クエリを貼り付け実行します。
実行結果は以下です。

結果が出力されました。アカウントIDはマスクしていますが左から

  • アカウントID
  • ユーザー名
  • アタッチしているAWS管理ポリシー

を抽出します。この例では、組織内AWSアカウントのtest-userというIAMユーザーがCloudWatchFullAccessを使用していることが分かります。

IAMグループに対する検索

次はIAMグループです。以下、実行するクエリです。

SELECT
  accountId,
  configuration.groupName,
  configuration.attachedManagedPolicies.policyName
WHERE
  resourceType = 'AWS::IAM::Group'
  AND configuration.attachedManagedPolicies.policyName = 'CloudWatchFullAccess'

実行結果は以下です。

テスト的に2つのAWSアカウントでグループを作成したため、2行出力されています。出力される項目は同じで、ユーザー名の部分がグループ名に変わっただけです。

IAMロールに対する検索

最後にIAMロールです。以下、実行するクエリです。

SELECT
  accountId,
  configuration.roleName,
  configuration.attachedManagedPolicies.policyName
WHERE
  resourceType = 'AWS::IAM::Role'
  AND configuration.attachedManagedPolicies.policyName = 'CloudWatchFullAccess'

実行結果は以下です。

アタッチしているAWS管理ポリシー列に「2項目」と表示されています。これは対象のIAMロールに複数のAWS管理ポリシーをアタッチしているとその数が表示されます。IAMユーザーやグループの例では、対象のAWS管理ポリシーのみアタッチしていました。「2項目」となっているリンクをクリックすると以下のように出力されます。

複数のAWS管理ポリシーをアタッチしていても検索できることが分かりました。configuration.attachedManagedPolicies.policyNameの列はあくまでアタッチしているAWS管理ポリシーを示すものでインラインポリシーやカスタマー管理ポリシーは含まれません。IAMユーザーの例で対象ユーザーにインラインポリシーを設定していましたが、この検索においては特にカスタマー管理ポリシーやインラインポリシーの有無を気にする必要はありません。

高度なクエリを使った検索例は以上です。

(おまけ)どうやって高度なクエリで検索できることを確認したか

高度なクエリで検索できるかをどのように確認したかについて少し紹介します。
今後、高度なクエリで検索できるか試したくなったときのヒントになれば、という想いでここに記します。

前提として、高度なクエリで検索可能なリソースは決まっています。以下のサイトから確認します。

AWSのサービス名で検索します。今回の例ではIAMで検索して、検索可能なIAMリソースを確認します。

試しにAWS::IAM::Policy.properties.jsonを見てみます。この各プロパティの名前から目的の要素を抽出できそうかを確認します。

AWS::IAM::Policy.properties.json

{
  "accountId": "string",
  "arn": "string",
  "availabilityZone": "string",
  "awsRegion": "string",
  "configuration.arn": "string",
  "configuration.attachmentCount": "integer",
  "configuration.createDate": "date",
  "configuration.defaultVersionId": "string",
  "configuration.description": "string",
  "configuration.isAttachable": "boolean",
  "configuration.path": "string",
  "configuration.permissionsBoundaryUsageCount": "integer",
  "configuration.policyId": "string",
  "configuration.policyName": "string",
  "configuration.policyVersionList.createDate": "date",
  "configuration.policyVersionList.isDefaultVersion": "boolean",
  "configuration.policyVersionList.versionId": "string",
  "configuration.updateDate": "date",
  "configurationItemCaptureTime": "string",
  "configurationItemDeliveryTime": "date",
  "configurationItemStatus": "string",
  "configurationStateId": "string",
  "recordingFrequency": "string",
  "relationships.resourceId": "string",
  "relationships.resourceName": "string",
  "relationships.resourceType": "string",
  "resourceCreationTime": "string",
  "resourceId": "string",
  "resourceName": "string",
  "resourceType": "string",
  "tags.key": "string",
  "tags.tag": "string",
  "tags.value": "string",
  "version": "string"
}

ここに記載されているプロパティ名をSELECTやWHERE句で指定してクエリを実行します。 この中からrelationships.resourceNamerelationships.resourceTypeあたりでエンティティを抽出できそうかも?と当たりをつけます。抽出したい情報としてaccountIdconfiguration.policyNameをメモします。あとはこのプロパティをもとにクエリを用意して試してみるだけです。

まずはアカウントIDとポリシー名で検索します。

SELECT
  accountId,
  configuration.policyName
WHERE
  resourceType = 'AWS::IAM::Policy'
  AND accountId = '0123456789012'

大量にリソースが抽出されることを避けるため、アカウントIDを絞って検索します。すると、以下のような結果になりました。

これは該当アカウントで作成したカスタマー管理ポリシーで、AWS管理ポリシーは抽出されません。AWS::IAM::Policy.properties.jsonにある他のプロパティを見てもAWS管理ポリシーの抽出はできなさそうでした。そこで、別の検索方法がないかを同様の方法で調べて、今回の方法(3つのクエリ)を見つけるに至ったというわけです。

さらにおまけですがAWS::IAM::Policyに対して、当たりをつけたrelationships.resourceNamerelationships.resourceTypeでの検索も試してみます。

SELECT
  configuration.policyName,
  relationships.resourceName,
  relationships.resourceType
WHERE
  resourceType = 'AWS::IAM::Policy'
  AND accountId = '0123456789012'

対象のカスタマー管理ポリシーを使用しているエンティティが表示されました。

カスタマー管理ポリシーを使っているエンティティの検索には使えることが分かりました。
参考として、高度なクエリが対応していないリソースの検索について紹介したブログもあります。

さいごに

高度なクエリを使って、AWS管理ポリシーを使っているエンティティを検索してみました。高度なクエリは便利なので私のお気に入りです。高度なクエリに関する参考資料をいくつか記載しますので興味を持たれた方は合わせてご確認ください。

ついでに宣伝ですが、技術評論社 刊行のSoftware Design でAWS活用ジャーニーという記事を連載しています。先日発売された2024年1月号ではAmazon VPCを紹介しています。VPCはそこかしこで紹介されていますので、分析や機能の活用、IPv6対応など少し踏み込んだ内容を記載してみました。他にも面白い記事がたくさんあります。よかったら読んでね!

参考資料