どのアカウントにルートユーザー認証情報が存在しているか一覧を取得して、スプシやスクリプトで処理したくなるけど、マネコンだと取れないし、ググってもよくわかんな~い
という訳で考えてみた、という記事です
→ 本編はこちら
前提
AWS Organization マスターアカウントでマネジメントコンソールへログインし、IAMコンソールの「アカウント設定」で「メンバーアカウントのための一元化されたルートアクセス」が有効であること。
あと、本記事に記載のAWS CLIコマンドは、AWS CLIバージョンが古いと出来ないようです。(AWS CLI 2.15.4 on Windowsだと出来なくて、2.24.13 on Windowsだと出来ることは確認できています)
マネコンで見れる
IAMコンソールの「ルートアクセス管理」で、添付画像のような形で見ることができる。
アカウントごとに、ルートユーザーアクセスキーおよびコンソールパスワードの存在有無の一覧が欲しくても、いちいちクリックして転記しなければならないのか。
AWS CLIでがんばる
以下のAWS CLIコマンド①~②をスクリプト等でメンバーアカウントごとにループ処理する;
①AWS Organization マスターアカウントでは、ルートユーザー認証情報の存在有無にかかわらずメンバーアカウントのルートユーザー認証情報を取得可能
$ aws sts assume-root --target-principal <member account id> --task-policy-arn "arn=arn:aws:iam::aws:policy/root-task/IAMAuditRootUserCredentials" --profile <cli profile name of master account>
{
"Credentials": {
"AccessKeyId": "*******",
"SecretAccessKey": "*******",
"SessionToken": "*******",
"Expiration": "*******"
}
}
※注意:メンバーアカウントの一時的認証情報が帰ってきているが、これをもって当該アカウントにルートユーザーアクセスキーが存在すると見なすことは出来ない
※注釈:ここで取れる認証情報はルートユーザーの一時的認証情報ではあるものの、--task-policy-arn
で指定されたポリシーに記載のオペレーションしか出来ない。しかしながら、ルートユーザーにしか出来ない操作が出来る認証情報ではあるため、ルートユーザーアクセスキーと同じくらい厳重に管理すべき
②ルートユーザーの認証情報/MFAデバイス/コンソールパスワード、およびデジタル署名用証明書の存在を確認する
aws iam get-account-summary --profile <member account root user profile name by above temporary credential>
{
"SummaryMap": {
"GroupPolicySizeQuota": 5120,
"InstanceProfilesQuota": 1000,
"Policies": 10,
"GroupsPerUserQuota": 10,
"InstanceProfiles": 0,
"AttachedPoliciesPerUserQuota": 10,
"Users": 2,
"PoliciesQuota": 1500,
"Providers": 1,
"AccountMFAEnabled": 1,
"AccessKeysPerUserQuota": 2,
"AssumeRolePolicySizeQuota": 2048,
"PolicyVersionsInUseQuota": 10000,
"GlobalEndpointTokenVersion": 1,
"VersionsPerPolicyQuota": 5,
"AttachedPoliciesPerGroupQuota": 10,
"PolicySizeQuota": 6144,
"Groups": 1,
"AccountSigningCertificatesPresent": 0,
"UsersQuota": 5000,
"ServerCertificatesQuota": 20,
"MFADevices": 3,
"UserPolicySizeQuota": 2048,
"PolicyVersionsInUse": 49,
"ServerCertificates": 0,
"Roles": 48,
"RolesQuota": 1000,
"SigningCertificatesPerUserQuota": 2,
"MFADevicesInUse": 3,
"RolePolicySizeQuota": 10240,
"AttachedPoliciesPerRoleQuota": 10,
"AccountAccessKeysPresent": 0,
"AccountPasswordPresent": 1,
"GroupsQuota": 300
}
}
AccountMFAEnabled
:1ならばルートユーザーのMFAが有効である
AccountAccessKeysPresent
:1ならばルートユーザーのアクセスキーが存在している
AccountPasswordPresent
:1ならばルートユーザーのコンソールサインイン用パスワードが存在している
AccountSigningCertificatesPresent
:1ならばデジタル署名用証明書が存在している
※注意:ルートユーザーアクセスキーが無効化されていても、存在していればAccountAccessKeysPresent
は1になる
リストするサンプルコード
# pip install boto3
# pip install -U boto3
import boto3
ORGANIZATION_MASTER_ACCOUNT_ID = '<enter your organization master account id>'
_session = boto3.Session(profile_name='organization master account')
_orgclient = _session.client('organizations')
_stsclient = _session.client('sts', region_name='us-east-1', endpoint_url="https://sts.us-east-1.amazonaws.com")
def list_organizations_accounts(NextToken=None):
response = _orgclient.list_accounts(NextToken=NextToken) if NextToken else _orgclient.list_accounts()
accounts =response['Accounts']
if 'NextToken' in response:
accounts.extend(list_organizations_accounts(response['NextToken']))
return accounts
with open('member_account_rootuser_credential_summary.tsv', 'w') as f:
f.write(f'accountId\taccountName\tAccountMFAEnabled\tAccountAccessKeysPresent\tAccountPasswordPresent\tAccountSigningCertificatesPresent\n')
for account in list_organizations_accounts():
accountId = account['Id']
accountName = account['Name']
if accountId == ORGANIZATION_MASTER_ACCOUNT_ID:
continue
print(f'Account ID: {accountId}, Account Name: {accountName}')
rootUserCredential = _stsclient.assume_root(
TargetPrincipal=accountId,
TaskPolicyArn={
'arn': 'arn:aws:iam::aws:policy/root-task/IAMAuditRootUserCredentials'
},
DurationSeconds=123
)
# {'Credentials': {'AccessKeyId': '***', 'SecretAccessKey': '***', 'SessionToken': '***'}}
iam_client = boto3.Session(
aws_access_key_id=rootUserCredential['Credentials']['AccessKeyId'],
aws_secret_access_key=rootUserCredential['Credentials']['SecretAccessKey'],
aws_session_token=rootUserCredential['Credentials']['SessionToken'],
region_name='us-east-1'
).client('iam')
account_summary = iam_client.get_account_summary()
summaryMap = account_summary['SummaryMap']
AccountMFAEnabled = summaryMap['AccountMFAEnabled']
AccountAccessKeysPresent = summaryMap['AccountAccessKeysPresent']
AccountPasswordPresent = summaryMap['AccountPasswordPresent']
AccountSigningCertificatesPresent = summaryMap['AccountSigningCertificatesPresent']
print(f'AccountMFAEnabled: {AccountMFAEnabled}, AccountAccessKeysPresent: {AccountAccessKeysPresent}, AccountPasswordPresent: {AccountPasswordPresent}, AccountSigningCertificatesPresent: {AccountSigningCertificatesPresent}')
with open('member_account_rootuser_credential_summary.tsv', 'a') as f:
f.write(f'{accountId}\t{accountName}\t{AccountMFAEnabled}\t{AccountAccessKeysPresent}\t{AccountPasswordPresent}\t{AccountSigningCertificatesPresent}\n')
boto3でやる時の注意点
2025年2月27日現在、STSのグローバルエンドポイントではAssumeRoleオペレーションに対応していないので、APIからエラーが返ってくる。
なので、以下のようにboto3 clientオブジェクトを生成する際にリージョンとエンドポイントURLを指定する必要がある。
_stsclient = _session.client('sts', region_name='us-east-1', endpoint_url="https://sts.us-east-1.amazonaws.com")
結果
以下のような、アカウントIDごとにアカウント名と、ルートユーザー認証情報およびコンソールサインインパスワードの存在有無、ルートユーザーMFA、デジタル署名用証明書の有無がのったTSVファイルが得られる。
accountId accountName AccountMFAEnabled AccountAccessKeysPresent AccountPasswordPresent AccountSigningCertificatesPresent
**** **** 0 0 1 0
**** **** 0 0 1 0
**** **** 0 0 1 0
**** **** 0 0 0 0
ちなみに わたしは ねこちゃん 大好きマンです