如何使用python boto3从多个AWS账户生成EC2库存



我正在尝试从AWS帐户生成库存并将其写入单个CSV文件中。

我有5个帐户,如Dev, Test, DevOps, Prepared和Prod。通常我使用下面的bash脚本生成,这需要一些手动任务;

#!/bin/bash
reg="ap-south-1"
input="profile.txt" ##This file contain all the profile name which configured on ~/.aws/credentials file
while IFS= read -r line
do
aws ec2 describe-instances --profile ${line} --region ${reg} --query "Reservations[*].Instances[*].[Tags[?Key=='Name']|[0].Value,InstanceId,InstanceType,PrivateIpAddress,State.Name,Platform,Placement.AvailabilityZone]" --output text >> ec2_inventory.csv
done < "$input"

所以,这里我写了一个python boto3脚本来生成ec2库存;

对于单个AWS配置文件,它按预期工作。下面的脚本;

import boto3
session = boto3.Session(profile_name='dev')
ec2 = session.client('ec2', region_name='ap-south-1')
response = ec2.describe_instances()
import datetime
import csv
time = datetime.datetime.now().strftime ('%Y-%m-%d-%H-%M-%S')
filename_describe_instances = ('ec2_inventory_me-south-1_' + time + '.csv')
fieldnames = ['Instance_Name','ImageId', 'InstanceId', 'InstanceType', 'Availability_Zone', 'Platform', 'PrivateIpAddress','PublicIpAddress', 'State', 'SubnetId','VpcId', 'Environment', 'AccountId']

with open(filename_describe_instances, 'w', newline='') as csvFile:
writer = csv.writer(csvFile, dialect='excel')
writer.writerow(fieldnames)
for Reserv in response['Reservations']:
for Insta in Reserv['Instances']:
instance_imageid = Insta.get('ImageId', 'NULL')
instance_InstanceId = Insta.get('InstanceId', 'NULL')
instance_InstanceType = Insta.get('InstanceType', 'NULL')
instance_Availability_Zone = Insta['Placement'].get('AvailabilityZone', 'NULL')
instance_Platform = Insta.get('Platform', 'Linux')
instance_Private_IP = Insta.get('PrivateIpAddress', 'NULL')
instance_Public_IP = Insta.get('PublicIpAddress', 'NULL')
instance_State = Insta['State'].get('Name', 'NULL')
instance_Subnet = Insta.get('SubnetId', 'NULL')
instance_VPCID = Insta.get('VpcId', 'NULL')
instance_OwnerId = Reserv.get('OwnerId', 'NULL')
tags_list = []
for n in Insta.get('Tags', 'NULL'):
if n.get('Key', 'NULL') == 'Name':
instance_Name = n.get('Value', 'NULL')
if n.get('Key', 'NULL') == 'Environment':
instance_Environment = n.get('Value', 'NULL')
raw = [instance_Name,
instance_imageid,
instance_InstanceId,
instance_InstanceType,
instance_Availability_Zone,
instance_Platform,
instance_Private_IP,
instance_Public_IP,
instance_State,
instance_Subnet,
instance_VPCID,
instance_Environment,
instance_OwnerId]
writer.writerow(raw)
for o in raw:
o = 'NULL'
raw = []
csvFile.close()

那么,有人能帮我用这个脚本从多个AWS帐户生成库存并将其写入单个CSV文件中吗?

EDIT -修改一些基本细节。

最简单的事情,如果你已经配置了你的配置文件,就是循环它们,并使用boto3Session对象在循环中获取你的实例细节。

# set up your .csv writer, etc outside the loop
# iterate over your profiles
profiles = ['Dev', 'Test', 'DevOps', 'Prepared', 'Prod']
for name in profiles:
session = boto3.Session(profile_name=name)
ec2 = session.client('ec2')
response = ec2.describe_instances()
#format your row and write to the .csv

您可以硬编码配置文件列表,或者查看argparse以从命令行获取它们。

配置文件方法很好,我广泛使用它来编写跨帐户的报告和审计工具。但是,有必要深入研究一下交叉帐户设置应该是什么样子。您有两个基本选项:

  • 通过IAM跨帐户访问每个帐户中的用户-每个帐户都有一个具有自己密钥和秘密的唯一用户
  • 在每个帐户中通过IAM Role进行跨帐户访问-您在一个帐户中创建一个唯一的用户(例如,中央"管理")。帐户),并在目标帐户中创建执行实际工作的角色。

强烈推荐后者作为更安全、更灵活的替代方案(除非您的组织已经在使用某种形式的SSO,它在概念上是类似的,但超出了本文的回答范围)。使用角色更安全,因为您只提供/管理单个凭据,并将自己设置为从中央认证存储库管理所有帐户。

为了设置这个,SDK支持通过引用其他配置文件来隐式调用sts:AssumeRole

的配置文件。例如:In~/.aws/credentials:

[management]
region=us-west-2
aws_access_key_id=...
aws_secret_access_key=...

In~/.aws/config:

[profile foo-account]
source_profile=management
role_arn=arn:aws:iam::[foo-account-id]:role/Inventory

(注意两个文件的节头名称的差异—这是故意的)

鉴于上述情况,如果运行aws --profile foo-account ec2 describe-instances, CLI将使用配置文件management下的密钥/秘密来调用sts:AssumeRole,目标是Inventory角色。如果设置了AWS_PROFILEenv变量,则可以省略--profile标志。同样的事情将在您的Python脚本中工作,使用profile_name参数Session

该角色定义在您想要处理的每个帐户中(使用相应的配置文件),具有足够的权限来读取您需要的EC2数据,必须有一个AssumeRolePolicyDocument,允许您的IAM用户调用sts:AssumeRole上的库存角色。

{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::[foo-account-id]:user/[your-user]"
},
"Action": "sts:AssumeRole"
}
]
}

同样,IAM用户需要一个允许其调用sts:AssumeRole的策略:

{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "sts:AssumeRole",
"Resource": "*"
}
]
}

可以将"*"资源引用替换为角色arn列表。AssumeRolePolicyDocument允许指定的主体承担这个角色;用户策略允许用户根据指定的资源调用presumerole。这似乎有点违反直觉,但请记住,授权需要回答两个问题:用户是否可以这样做,以及资源是否允许这样做。

最后,当您变得更高级时,一旦您有了基本的帐户/角色设置,您实际上可以省略配置文件,并使用帐户列表直接调用sts:AssumeRole

accounts = ['123...789', '234...890',]
sts = boto3.client('sts') #assumes you have a default profile set
for id in accounts:
role_arn = f'arn:aws:iam::{id}:role/Inventory'
creds = sts.assume_role(role_arn=role_arn, role_session_name='some-name')
session = boto3.Session(aws_access_key_id=creds['AccessKeyId'], ...)
ec2 = session.client('ec2')

如果你必须做很多跨帐户的工作,花点时间考虑和配置中央授权绝对是值得的。其副作用是,一旦您拥有了跨帐户角色,您可以通过在管理帐户的Lambda函数中运行它来自动化此操作,并对该执行角色进行相同的权限设置(将.csv写入S3)。

有一个云管理平台可以做到这一点。它使用户能够从单个仪表板管理多个AWS帐户,并提供AWS库存管理。成本优化。它是免费的:https://cloudplexo.com。

最新更新