概要
IAMユーザーグループのアクセスアドバイザーから直近1年にアクセスしたサービスのアクションを持つIAMポリシーを作成します。
jqコマンドで完結できるのが一番いいのですが、心が折れたのでPythonプログラムで実装しています。
結論
STEP1 : アドバイザーの情報を一覧を取得(CLI)
JOBID=`aws iam generate-service-last-accessed-details \
--granularity ACTION_LEVEL \
--arn arn:aws:iam::xxxxxxxxxx:group/hogehoge --output text`
aws iam get-service-last-accessed-details --job-id $JOBID > input.json
STEP2 : PythonプログラムでIAMポリシーを作成
リソースまでは絞れなさそうなので*
固定としています。
また、6144文字の制限を超えるポリシーは作成できないのでその考慮も必要です。
import json
from datetime import datetime, timedelta, timezone
# JSONファイルの読み込み
with open('input.json', 'r') as f:
data = json.load(f)
# 直近1年間の日時を取得
one_year_ago = datetime.now(timezone.utc) - timedelta(days=365)
def is_within_last_year(date_str):
date = datetime.fromisoformat(date_str.replace('Z', '+00:00'))
return date >= one_year_ago
# IAMポリシーのテンプレート
policy_template = {"Version": "2012-10-17", "Statement": []}
# ポリシーを保存するリスト
policies = []
for service in data['ServicesLastAccessed']:
if 'TrackedActionsLastAccessed' in service:
actions = [
action['ActionName']
for action in service['TrackedActionsLastAccessed']
if 'LastAccessedTime' in action
and is_within_last_year(action['LastAccessedTime'])
]
if actions:
statement = {
"Effect": "Allow",
"Action": [
f"{service['ServiceNamespace']}:{action}" for action in actions
],
"Resource": "*",
}
policy_template["Statement"].append(statement)
# ポリシーのサイズをチェックし、超えた場合は新しいポリシーを作成
policy_str = json.dumps(policy_template)
if len(policy_str) > 6144:
# 現在のポリシーを保存
policies.append(policy_template.copy())
# 新しいポリシーを開始
policy_template["Statement"] = [statement]
# 最後のポリシーも追加
if policy_template["Statement"]:
policies.append(policy_template.copy())
# 各ポリシーをファイルに保存
for idx, policy in enumerate(policies):
with open(f'iam_policy_{idx+1}.json', 'w') as f:
json.dump(policy, f, indent=4)
print(f'{len(policies)}個のIAMポリシーファイルが生成されました。')
コマンドライン引数にして1回の処理にする
pythonをちょっと修正してコマンドを繋げるだけですが、JOB生成に時間がかかるのでsleepを挟んでいる点に注意です。
JOBID=`aws iam generate-service-last-accessed-details \
--granularity ACTION_LEVEL \
--arn arn:aws:iam::xxxxxxxxxx:group/hogehoge --output text` \
&& sleep 10 \
&& aws iam get-service-last-accessed-details --job-id $JOBID > input.json \
&& python index.py input.json
生成途中のjsonファイルの中身
{
"JobStatus": "IN_PROGRESS",
"JobCreationDate": "2024-06-10T22:23:59.288000+00:00",
"IsTruncated": false
}
修正したPythonコード
import json
from datetime import datetime, timedelta, timezone
import sys
# コマンドライン引数を取得
args = sys.argv
input_json_path = args[1]
# JSONファイルの読み込み
with open(input_json_path, 'r') as f:
data = json.load(f)
以下は同じ
作成したIAMポリシーの例
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"access-analyzer:ListAnalyzers",
"access-analyzer:ListPolicyGenerations",
"access-analyzer:ValidatePolicy"
],
"Resource": "*"
},
{
"Effect": "Allow",
"Action": [
"account:ListRegions"
],
"Resource": "*"
},
{
"Effect": "Allow",
"Action": [
"acm:ListCertificates"
],
"Resource": "*"
},
{
"Effect": "Allow",
"Action": [
"amplify:CreateApp",
"amplify:CreateBranch",
"amplify:DeleteApp",
"amplify:GetApp",
"amplify:GetBranch",
"amplify:GetDomainAssociation",
"amplify:GetJob",
"amplify:ListApps",
"amplify:ListBackendEnvironments",
"amplify:ListBranches",
"amplify:ListDomainAssociations",
"amplify:ListJobs",
"amplify:ListWebHooks",
"amplify:StartJob",
"amplify:UpdateApp"
],
"Resource": "*"
},
(中略)
{
"Effect": "Allow",
"Action": [
"cognito-sync:GetBulkPublishDetails",
"cognito-sync:GetCognitoEvents",
"cognito-sync:GetIdentityPoolConfiguration",
"cognito-sync:ListDatasets"
],
"Resource": "*"
},
{
"Effect": "Allow",
"Action": [
"compute-optimizer:GetEnrollmentStatus"
],
"Resource": "*"
},
{
"Effect": "Allow",
"Action": [
"config:DescribeConfigurationRecorderStatus",
"config:DescribeConfigurationRecorders"
],
"Resource": "*"
},
{
"Effect": "Allow",
"Action": [
"dax:DescribeClusters"
],
"Resource": "*"
},
{
"Effect": "Allow",
"Action": [
"devops-guru:GetResourceCollection",
"devops-guru:SearchInsights"
],
"Resource": "*"
}
]
}
参考