You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python提取AWS SSO账户信息存CSV报错:'Organizations'无对应属性

解决AWS SSO账户信息提取脚本的AttributeError问题

问题根源

  1. 客户端混用:list_permission_sets_provisioned_to_account是AWS SSO Admin的API方法,原脚本错误使用了AWS Organizations客户端调用;即便切换到sso-admin客户端,也未区分两个服务的职责——Organizations负责获取账户列表,SSO Admin负责处理权限集与账户分配。
  2. 缺失必填参数:list_permission_sets_provisioned_to_account必须传入InstanceArn参数,原脚本定义了该变量但未传入调用。
  3. API返回值处理错误:list_permission_sets_provisioned_to_account返回的PermissionSets是权限集ARN数组,并非包含名称的对象,需额外调用describe_permission_set获取名称。
  4. CSV写入逻辑错误:原脚本用csv.writer处理字典列表,会导致格式异常,需改用csv.DictWriter。
  5. 未处理分页:AWS列表类API默认分页返回,原脚本未处理分页会遗漏数据。

修正后的完整脚本

import boto3
import csv

# 替换为你的AWS SSO实例ARN
INSTANCE_ARN = 'arn:aws:sso:::instance/ssoins-xxxxxxxxxxxxxx'

def get_all_accounts():
    """从AWS Organizations获取所有账户(处理分页)"""
    org_client = boto3.client('organizations')
    accounts = []
    next_token = None
    while True:
        if next_token:
            response = org_client.list_accounts(NextToken=next_token)
        else:
            response = org_client.list_accounts()
        accounts.extend(response['Accounts'])
        next_token = response.get('NextToken')
        if not next_token:
            break
    return accounts

def get_permission_sets_for_account(sso_admin_client, account_id):
    """获取指定账户的所有权限集ARN(处理分页)"""
    permission_sets = []
    next_token = None
    while True:
        if next_token:
            response = sso_admin_client.list_permission_sets_provisioned_to_account(
                InstanceArn=INSTANCE_ARN,
                AccountId=account_id,
                NextToken=next_token
            )
        else:
            response = sso_admin_client.list_permission_sets_provisioned_to_account(
                InstanceArn=INSTANCE_ARN,
                AccountId=account_id
            )
        permission_sets.extend(response['PermissionSets'])
        next_token = response.get('NextToken')
        if not next_token:
            break
    return permission_sets

def get_permission_set_name(sso_admin_client, permission_set_arn):
    """通过权限集ARN获取名称"""
    response = sso_admin_client.describe_permission_set(
        InstanceArn=INSTANCE_ARN,
        PermissionSetArn=permission_set_arn
    )
    return response['PermissionSet']['Name']

def get_account_assignments(sso_admin_client, permission_set_arn):
    """获取权限集下的所有账户分配(处理分页)"""
    assignments = []
    next_token = None
    while True:
        if next_token:
            response = sso_admin_client.list_account_assignments(
                InstanceArn=INSTANCE_ARN,
                PermissionSetArn=permission_set_arn,
                NextToken=next_token
            )
        else:
            response = sso_admin_client.list_account_assignments(
                InstanceArn=INSTANCE_ARN,
                PermissionSetArn=permission_set_arn
            )
        assignments.extend(response['AccountAssignments'])
        next_token = response.get('NextToken')
        if not next_token:
            break
    return assignments

def main():
    # 初始化客户端
    sso_admin_client = boto3.client('sso-admin')
    accounts = get_all_accounts()
    account_info = []

    # 遍历所有账户
    for account in accounts:
        account_id = account['Id']
        print(f"处理账户: {account_id}")
        
        # 获取该账户的所有权限集ARN
        permission_set_arns = get_permission_sets_for_account(sso_admin_client, account_id)
        
        # 遍历每个权限集
        for ps_arn in permission_set_arns:
            ps_name = get_permission_set_name(sso_admin_client, ps_arn)
            
            # 获取该权限集的账户分配
            assignments = get_account_assignments(sso_admin_client, ps_arn)
            
            # 提取用户名并整理数据
            for assignment in assignments:
                # 注意:账户分配可能包含UserName或GroupName,这里只处理UserName
                if 'UserName' in assignment:
                    account_info.append({
                        "AccountId": account_id,
                        "Username": assignment['UserName'],
                        "PermissionSetName": ps_name
                    })

    # 写入CSV文件
    with open("sso_accounts.csv", "w", newline='', encoding='utf-8') as csvfile:
        fieldnames = ["AccountId", "Username", "PermissionSetName"]
        writer = csv.DictWriter(csvfile, fieldnames=fieldnames)
        
        writer.writeheader()
        writer.writerows(account_info)

    print("Done! CSV文件已生成。")

if __name__ == "__main__":
    main()

关键修改说明

  • 分离客户端职责:用organizations客户端获取账户列表,sso-admin客户端处理SSO权限相关操作,避免API调用混淆。
  • 传入必填参数:所有SSO Admin的API调用都传入了InstanceArn参数,符合AWS API要求。
  • 正确处理权限集数据:通过describe_permission_set从权限集ARN中提取名称,修正原脚本直接读取Name的错误。
  • 修复CSV写入:使用csv.DictWriter适配字典格式的数据,确保表头与内容对应。
  • 添加分页逻辑:所有列表类API都处理了NextToken,保证获取全量数据,不会遗漏账户、权限集或分配记录。

内容的提问来源于stack exchange,提问作者shubh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 12:07:11