Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

pubsys: use base region for contacting STS #1064

Merged
merged 1 commit into from
Aug 23, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions tools/pubsys/src/aws/ami/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -111,11 +111,11 @@ async fn _run(args: &Args, ami_args: &AmiArgs) -> Result<HashMap<String, String>
})?;

// Build EBS client for snapshot management, and EC2 client for registration
let ebs_client = build_client::<EbsClient>(&base_region, &aws).context(error::Client {
let ebs_client = build_client::<EbsClient>(&base_region, &base_region, &aws).context(error::Client {
client_type: "EBS",
region: base_region.name(),
})?;
let ec2_client = build_client::<Ec2Client>(&base_region, &aws).context(error::Client {
let ec2_client = build_client::<Ec2Client>(&base_region, &base_region, &aws).context(error::Client {
client_type: "EC2",
region: base_region.name(),
})?;
Expand Down Expand Up @@ -172,6 +172,7 @@ async fn _run(args: &Args, ami_args: &AmiArgs) -> Result<HashMap<String, String>
wait_for_ami(
&image_id,
&base_region,
&base_region,
"available",
successes_required,
&aws,
Expand All @@ -187,7 +188,7 @@ async fn _run(args: &Args, ami_args: &AmiArgs) -> Result<HashMap<String, String>
// live until the future is resolved.
let mut ec2_clients = HashMap::with_capacity(regions.len());
for region in regions.iter() {
let ec2_client = build_client::<Ec2Client>(&region, &aws).context(error::Client {
let ec2_client = build_client::<Ec2Client>(&region, &base_region, &aws).context(error::Client {
client_type: "EC2",
region: base_region.name(),
})?;
Expand Down
3 changes: 2 additions & 1 deletion tools/pubsys/src/aws/ami/wait.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ use std::time::Duration;
pub(crate) async fn wait_for_ami(
id: &str,
region: &Region,
sts_region: &Region,
state: &str,
successes_required: u8,
aws: &AwsConfig,
Expand Down Expand Up @@ -49,7 +50,7 @@ pub(crate) async fn wait_for_ami(
};
// Use a new client each time so we have more confidence that different endpoints can see
// the new AMI.
let ec2_client = build_client::<Ec2Client>(&region, &aws).context(error::Client {
let ec2_client = build_client::<Ec2Client>(&region, &sts_region, &aws).context(error::Client {
client_type: "EC2",
region: region.name(),
})?;
Expand Down
17 changes: 13 additions & 4 deletions tools/pubsys/src/aws/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,14 @@ impl NewWith for Ec2Client {
}

/// Create a rusoto client of the given type using the given region and configuration.
pub(crate) fn build_client<T: NewWith>(region: &Region, aws: &AwsConfig) -> Result<T> {
pub(crate) fn build_client<T: NewWith>(
region: &Region,
sts_region: &Region,
aws: &AwsConfig,
) -> Result<T> {
let maybe_regional_role = aws.region.get(region.name()).and_then(|r| r.role.clone());
let assume_roles = aws.role.iter().chain(maybe_regional_role.iter()).cloned();
let provider = build_provider(&region, assume_roles.clone(), base_provider(&aws.profile)?)?;
let provider = build_provider(&sts_region, assume_roles.clone(), base_provider(&aws.profile)?)?;
Ok(T::new_with(
rusoto_core::HttpClient::new().context(error::HttpClient)?,
provider,
Expand All @@ -61,8 +65,13 @@ impl ProvideAwsCredentials for CredentialsProvider {
}

/// Chains credentials providers to assume the given roles in order.
/// The region given should be the one in which you want to talk to STS to get temporary
/// credentials, not the region in which you want to talk to a service endpoint like EC2. This is
/// needed because you may be assuming a role in an opt-in region from an account that has not
/// opted-in to that region, and you need to get session credentials from an STS endpoint in a
/// region to which you have access in the base account.
fn build_provider<P>(
region: &Region,
sts_region: &Region,
assume_roles: impl Iterator<Item = String>,
base_provider: P,
) -> Result<CredentialsProvider>
Expand All @@ -74,7 +83,7 @@ where
let sts = StsClient::new_with(
HttpClient::new().context(error::HttpClient)?,
provider,
region.clone(),
sts_region.clone(),
);
let expiring_provider = StsAssumeRoleSessionCredentialsProvider::new(
sts,
Expand Down
5 changes: 4 additions & 1 deletion tools/pubsys/src/aws/publish_ami/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,9 @@ pub(crate) async fn run(args: &Args, publish_args: &PublishArgs) -> Result<()> {
} else {
aws.regions.clone().into()
};
ensure!(!regions.is_empty(), error::MissingConfig { missing: "aws.regions" });
let base_region = region_from_string(&regions[0], &aws).context(error::ParseRegion)?;

// Check that the requested regions are a subset of the regions we *could* publish from the AMI
// input JSON.
let requested_regions = HashSet::from_iter(regions.iter());
Expand Down Expand Up @@ -121,7 +124,7 @@ pub(crate) async fn run(args: &Args, publish_args: &PublishArgs) -> Result<()> {
// live until the future is resolved.
let mut ec2_clients = HashMap::with_capacity(amis.len());
for region in amis.keys() {
let ec2_client = build_client::<Ec2Client>(&region, &aws).context(error::Client {
let ec2_client = build_client::<Ec2Client>(&region, &base_region, &aws).context(error::Client {
client_type: "EC2",
region: region.name(),
})?;
Expand Down