我已经使用 python 做过很多次了,但在 Rust 中,我很难从假定的角色凭证创建客户端并根据区域过滤 ec2。这是我尝试用 Rust 重写的工作 python 代码:
assumed_role_object = sts.assume_role(
RoleArn=f"arn:aws:iam::{account}:role/role",
RoleSessionName="lambdaSession"
)
# get regions using global assumed role credentials
ec2_client = boto3.client('ec2',
aws_access_key_id=assumed_role_object['Credentials']['AccessKeyId'],
aws_secret_access_key=assumed_role_object['Credentials']['SecretAccessKey'],
aws_session_token=assumed_role_object['Credentials']['SessionToken'])
regions = [region['RegionName'] for region in ec2_client.describe_regions()['Regions']]
# for each region get ec2 instances
for region in regions:
try:
# try global sts with region filter
filters = [{'Name':'region-name', 'Values':[region]}]
ec2_response = ec2_client.describe_instances(Filters=filters)
# Catch ClientError exception
except botocore.exceptions.ClientError as _error:
try: #try regional sts
# create regional sts session
sts_regional_client = boto3.client('sts', region_name=region)
regional_assumed_role_object = sts_regional_client.assume_role(
RoleArn=f"arn:aws:iam::{account}:role/role",
RoleSessionName="regionallambdasession"
)
ec2_client = boto3.client(
"ec2",
region_name=region,
aws_access_key_id=regional_assumed_role_object["Credentials"]["AccessKeyId"],
aws_secret_access_key=regional_assumed_role_object["Credentials"]["SecretAccessKey"],
aws_session_token=regional_assumed_role_object["Credentials"]["SessionToken"],
)
ec2_response = ec2_client.describe_instances()
except botocore.exceptions.ClientError as _error2:
print(f"skipping {region} bc of error {_error2}\n")
continue
在 Rust 中,sts 假定角色不起作用,按区域过滤也不起作用,我可以列出区域并循环它们。
use aws_sdk_ec2 as ec2;
use ec2::{Client as Ec2Client, Error as Ec2Error, config::Region};
use aws_config::meta::Region;
use aws_config::meta::region::RegionProviderChain;
use aws_config::Region;
fn main(){
let config = aws_config::load_from_env().await;
// This might work - I need to get these credentials and list ec2 instances in this account
let sts_client = StsClient::new(&config);
let assume_role_response = sts_client.assume_role()
.role_arn(format!("arn:aws:iam::{}:role/role", account_id))
.role_session_name("inventorySession".to_string())
.send()
.await;
// I want to use the assumed_role_response when creating this client
let ec2_client = ec2::Client::new(&config);
// get regions
let regions = ec2_client.describe_regions().send().await;
for region in regions?.regions(){
let region_name = region.region_name().unwrap();
println!("loop Region: {:?}", region_name);
let region_provider = RegionProviderChain::first_try(Region::new(region_name.to_string()))
.or_default_provider()
.or_else(Region::new(region_name.to_string()));
// This works - I'm able to create the region_provider
println!(
"Region: {}",
region_provider.region().await.unwrap().as_ref()
);
// I want to use credentials from assumed_role_response and new region to create ec2_regional_config ???
let new_config = config.region(Region::new(region_name.to_string())).unwrap();
let ec2_regional_client = Ec2Client::new(&new_config); // This isn't using the region or the assumed_role credentials.
let ec2_instances = ec2_regional_client
.describe_instances()
.send()
.await;
println!("{:?}", ec2_instances);
}
}
当我最初开始这个项目时,我使用的是 rusoto 板条箱,并且能够完成所有这些工作,但在 apse4 上捕获错误,这是 rusoto 板条箱不包含的较新区域! rusoto 不会添加该区域,因为它现在不再维护:(。如果您知道如何使用 aws-sdk-rust 执行此操作,请有人帮忙!谢谢!
这是我找到的适合我的解决方案。除了
.region()
之外,我还需要包含 .credentials_provider(provider)
。还需要将 regional_config
转换为静态字符串引用('reg'),它是一个堆分配的指针,指向辅助函数中的静态字符串,这样每次我们循环区域循环时,就不会重新创建 region_name
变量.region_name