IAMポリシーをチェックできるスクリプトを作った
定義済みのIAMポリシーに対して、構文エラーや警告がないか、チェックするAPIをつくったので、紹介します。
Motivation
IAMポリシーをTerraformなどで作成していると、たとえ間違ったアクションを許可していてもエラーなく作成できてしまいます。
実際に使うタイミングで発覚することも多いです。
AWSマネジメントコンソールのJSONエディタでは、きちんとエラー表示してくれます。
ポリシーが多くなってくると、1件1件このように確認していくのは大変です。

幸いにも「accessanalyzer」サービスの「validate-policy」APIが公開されているので、こちらを使えば一括でチェックするスクリプトが作れそうなので、今回作ってみました。 AWSドキュメント:https://docs.aws.amazon.com/cli/latest/reference/accessanalyzer/validate-policy.html
validate_policy.py
import json
import boto3
aa = boto3.client('accessanalyzer')
iam = boto3.client('iam')
list_policies = iam.list_policies()
# https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/iam.html#IAM.Client.list_policies
LIMIT = 10000
cnt = 0
for policy in list_policies["Policies"]:
# filter policy
if not ("<system-name>" in policy["Arn"]):
continue
get_policy = iam.get_policy(
PolicyArn=policy["Arn"]
)
print(policy["Arn"])
policy_version = iam.get_policy_version(
PolicyArn=policy["Arn"],
VersionId=get_policy['Policy']['DefaultVersionId']
)
doc = json.dumps(policy_version['PolicyVersion']['Document'])
validate = aa.validate_policy(
locale='JA',
policyDocument=doc,
policyType='IDENTITY_POLICY', # | 'RESOURCE_POLICY' | 'SERVICE_CONTROL_POLICY',
# validatePolicyResourceType='AWS::S3::Bucket' | 'AWS::S3::AccessPoint' | 'AWS::S3::MultiRegionAccessPoint' | 'AWS::S3ObjectLambda::AccessPoint' | 'AWS::IAM::AssumeRolePolicyDocument'
)
# https://docs.aws.amazon.com/cli/latest/reference/accessanalyzer/validate-policy.html
for find in validate['findings']:
exclude_code = ["REDUNDANT_STATEMENT", "EMPTY_SID_VALUE"]
if find["issueCode"] in exclude_code:
continue
vars = ["findingDetails", "findingType", "issueCode", "locations"]
for v in vars:
print(f"\t{v}: {find[v]}")
print("\t---")
cnt = cnt + 1
if cnt > LIMIT:
breakvalidate_policy メソッドのコール時に PpolicyType を IDENTITY_POLICY を指定して、「IDベースのポリシーである」前提でチェックしています。
また、 exclude_code のところで、 REDUNDANT_STATEMENT , EMPTY_SID_VALUE を指定し、このエラーコードは無視するよう設定しています。
適宜カスタマイズしてご利用ください。
実行方法
$ python validate_policy.py動作例
arn:aws:iam::xxxxxxxxxxx:policy/lambda-readwrite-policy
findingDetails: アクション evenmts:DeauthorizeConnection で指定されたサービスは存在しません。
findingType: ERROR
issueCode: INVALID_SERVICE_IN_ACTION
locations: [{'path': [{'value': 'Statement'}, {'index': 1}, {'value': 'Action'}, {'index': 12}], 'span': {'end': {'column': 386, 'line': 1, 'offset': 386}, 'start': {'column': 355, 'line': 1, 'offset': 355}}}]
---
arn:aws:iam::xxxxxxxxxxx:policy/rds-auto-start-lambda-policy
arn:aws:iam::xxxxxxxxxxx:policy/rds-auto-stop-lambda-policy
arn:aws:iam::xxxxxxxxxxx:policy/rds-kms-access-policy
findingDetails: アクション kms:ReEncrypt は存在しません。 kms:ReEncryptFrom と kms:ReEncryptTo を意味しましたか? ReEncrypt と呼ばれる API は、ソースキーの kms:ReEncryptFrom とターゲットキーの kms:ReEncryptTo の両方に対して認証を行います。API を正常に呼び出すには、呼び出し元に両方が必要です。
findingType: ERROR
issueCode: INVALID_ACTION
locations: [{'path': [{'value': 'Statement'}, {'index': 0}, {'value': 'Action'}, {'index': 0}], 'span': {'end': {'column': 42, 'line': 1, 'offset': 42}, 'start': {'column': 27, 'line': 1, 'offset': 27}}}]
---
arn:aws:iam::xxxxxxxxxxx:policy/rds-readonly-policyエラーがあれば、その内容が表示されます。