Skip to content

Commit

Permalink
Merge pull request #2414 from jpculp/aws-sdk-rust-infrasys
Browse files Browse the repository at this point in the history
infrasys: update to AWS SDK Rust
  • Loading branch information
rpkelly authored Oct 6, 2022
2 parents 8237c86 + 19fb48c commit 5f7ac20
Show file tree
Hide file tree
Showing 9 changed files with 342 additions and 364 deletions.
379 changes: 149 additions & 230 deletions tools/Cargo.lock

Large diffs are not rendered by default.

3 changes: 0 additions & 3 deletions tools/deny.toml
Original file line number Diff line number Diff line change
Expand Up @@ -63,9 +63,6 @@ skip = [
]

skip-tree = [
# rusoto_signature uses an older version of sha2
{ name = "rusoto_signature" },

# structopt pulls in an older version of clap
{ name = "structopt", version = "0.3.26" },

Expand Down
7 changes: 4 additions & 3 deletions tools/infrasys/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,10 @@ clap = "3.1"
hex = "0.4.0"
log = "0.4.14"
pubsys-config = { path = "../pubsys-config/", version = "0.1.0" }
rusoto_cloudformation = { version = "0.48.0", default-features = false, features = ["rustls"] }
rusoto_core = { version = "0.48.0", default-features = false, features = ["rustls"] }
rusoto_s3 = { version = "0.48.0", default-features = false, features = ["rustls"] }
aws-config = "0.48.0"
aws-types = "0.48.0"
aws-sdk-cloudformation = "0.18.0"
aws-sdk-s3 = "0.18.0"
serde_json = "1.0.66"
serde_yaml = "0.8.17"
sha2 = "0.10"
Expand Down
22 changes: 13 additions & 9 deletions tools/infrasys/src/error.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use aws_sdk_s3::types::SdkError;
use snafu::Snafu;
use std::io;
use std::path::PathBuf;
Expand All @@ -14,7 +15,7 @@ pub enum Error {
CreateStack {
stack_name: String,
region: String,
source: rusoto_core::RusotoError<rusoto_cloudformation::CreateStackError>,
source: SdkError<aws_sdk_cloudformation::error::CreateStackError>,
},

#[snafu(display(
Expand All @@ -40,6 +41,9 @@ pub enum Error {
))]
CreateStackTimeout { stack_name: String, region: String },

#[snafu(display("No stack data returned for CFN stack '{}' in {}", stack_name, region))]
MissingStack { stack_name: String, region: String },

#[snafu(display(
"Failed to fetch stack details for CFN stack '{}' in '{}': {}",
stack_name,
Expand All @@ -49,7 +53,7 @@ pub enum Error {
DescribeStack {
stack_name: String,
region: String,
source: rusoto_core::RusotoError<rusoto_cloudformation::DescribeStacksError>,
source: SdkError<aws_sdk_cloudformation::error::DescribeStacksError>,
},

#[snafu(display("Missing environment variable '{}'", var))]
Expand Down Expand Up @@ -117,11 +121,11 @@ pub enum Error {
source: std::num::ParseIntError,
},

#[snafu(display("Failed to parse '{}' to a valid rusoto region: {}", what, source))]
ParseRegion {
what: String,
source: rusoto_core::region::ParseRegionError,
},
#[snafu(display("Failed to find default region"))]
DefaultRegion,

#[snafu(display("Unable to parse stack status"))]
ParseStatus,

#[snafu(display(
"Failed to find field '{}' after attempting to create resource '{}'",
Expand All @@ -139,7 +143,7 @@ pub enum Error {
#[snafu(display("Failed to push object to bucket '{}': {}", bucket_name, source))]
PutObject {
bucket_name: String,
source: rusoto_core::RusotoError<rusoto_s3::PutObjectError>,
source: SdkError<aws_sdk_s3::error::PutObjectError>,
},

#[snafu(display(
Expand All @@ -149,7 +153,7 @@ pub enum Error {
))]
PutPolicy {
bucket_name: String,
source: rusoto_core::RusotoError<rusoto_s3::PutBucketPolicyError>,
source: SdkError<aws_sdk_s3::error::PutBucketPolicyError>,
},

#[snafu(display("Failed to create async runtime: {}", source))]
Expand Down
44 changes: 23 additions & 21 deletions tools/infrasys/src/keys.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
use async_trait::async_trait;
use aws_sdk_cloudformation::Client as CloudFormationClient;
use aws_types::region::Region;
use pubsys_config::{KMSKeyConfig, SigningKeyConfig};
use rusoto_cloudformation::{CloudFormation, CloudFormationClient, CreateStackInput};
use rusoto_core::Region;
use snafu::{OptionExt, ResultExt};
use std::fs;
use std::str::FromStr;

use super::{error, shared, Result};

Expand Down Expand Up @@ -34,7 +33,7 @@ pub fn check_signing_key_config(signing_key_config: &SigningKeyConfig) -> Result
SigningKeyConfig::file { .. } => (),
SigningKeyConfig::kms { config, .. } => {
let config = config.as_ref().context(error::MissingConfigSnafu {
missing: "config field for a kms key",
missing: "config field for kms keys",
})?;

match (
Expand Down Expand Up @@ -89,9 +88,13 @@ impl KMSKeyConfigExt for KMSKeyConfig {
missing: "key_alias",
})?
);
let cfn_client = CloudFormationClient::new(
Region::from_str(region).context(error::ParseRegionSnafu { what: region })?,
);

let config = aws_config::from_env()
.region(Region::new(region.to_owned()))
.load()
.await;
let cfn_client = CloudFormationClient::new(&config);

let cfn_filepath = format!(
"{}/infrasys/cloudformation-templates/kms_key_setup.yml",
shared::getenv("BUILDSYS_TOOLS_DIR")?
Expand All @@ -100,20 +103,19 @@ impl KMSKeyConfigExt for KMSKeyConfig {
.context(error::FileReadSnafu { path: cfn_filepath })?;

let stack_result = cfn_client
.create_stack(CreateStackInput {
parameters: Some(vec![shared::create_parameter(
"Alias".to_string(),
self.key_alias
.as_ref()
.context(error::KeyConfigSnafu {
missing: "key_alias",
})?
.to_string(),
)]),
stack_name: stack_name.clone(),
template_body: Some(cfn_template.clone()),
..Default::default()
})
.create_stack()
.parameters(shared::create_parameter(
"Alias".to_string(),
self.key_alias
.as_ref()
.context(error::KeyConfigSnafu {
missing: "key_alias",
})?
.to_string(),
))
.stack_name(stack_name.clone())
.template_body(cfn_template.clone())
.send()
.await
.context(error::CreateStackSnafu {
stack_name: &stack_name,
Expand Down
53 changes: 42 additions & 11 deletions tools/infrasys/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,13 @@ mod root;
mod s3;
mod shared;

use aws_sdk_cloudformation::Region;
use error::Result;
use log::{error, info};
use pubsys_config::{InfraConfig, RepoConfig, S3Config, SigningKeyConfig};
use sha2::{Digest, Sha512};
use shared::KeyRole;
use simplelog::{Config as LogConfig, LevelFilter, SimpleLogger};
use simplelog::{CombinedLogger, Config as LogConfig, ConfigBuilder, LevelFilter, SimpleLogger};
use snafu::{ensure, OptionExt, ResultExt};
use std::collections::HashMap;
use std::num::NonZeroUsize;
Expand Down Expand Up @@ -62,7 +63,35 @@ fn run() -> Result<()> {
// Parse and store the args passed to the program
let args = Args::from_args();

SimpleLogger::init(args.log_level, LogConfig::default()).context(error::LoggerSnafu)?;
match args.log_level {
// Set log level for AWS SDK to error to reduce verbosity.
LevelFilter::Info => {
CombinedLogger::init(vec![
SimpleLogger::new(
LevelFilter::Info,
ConfigBuilder::new()
.add_filter_ignore_str("aws_config")
.add_filter_ignore_str("aws_smithy")
.add_filter_ignore_str("tracing::span")
.build(),
),
SimpleLogger::new(
LevelFilter::Warn,
ConfigBuilder::new()
.add_filter_allow_str("aws_config")
.add_filter_allow_str("aws_smithy")
.add_filter_allow_str("tracing::span")
.build(),
),
])
.context(error::LoggerSnafu)?;
}

// Set the supplied log level across the whole crate.
_ => {
SimpleLogger::init(args.log_level, LogConfig::default()).context(error::LoggerSnafu)?
}
}

match args.subcommand {
SubCommand::CreateInfra(ref run_task_args) => {
Expand Down Expand Up @@ -124,7 +153,7 @@ async fn create_infra(toml_path: &Path, root_role_path: &Path) -> Result<()> {
// Upload root.json.
info!("Uploading root.json to S3 bucket...");
s3::upload_file(
repo_info.s3_region,
&repo_info.s3_region,
&bucket_name,
&repo_info.prefix,
root_role_path,
Expand Down Expand Up @@ -187,7 +216,7 @@ struct ValidRepoInfo<'a> {
root_key_threshold: &'a NonZeroUsize,
root_keys: &'a mut SigningKeyConfig,
root_role_url: &'a mut Option<Url>,
s3_region: &'a String,
s3_region: Region,
s3_stack_name: String,
signing_keys: &'a mut SigningKeyConfig,
stack_arn: &'a mut Option<String>,
Expand All @@ -204,20 +233,22 @@ impl<'a> ValidRepoInfo<'a> {
let s3_stack_name =
repo_config
.file_hosting_config_name
.as_ref()
.to_owned()
.context(error::MissingConfigSnafu {
missing: "file_hosting_config_name",
})?;
let s3_info = s3_info_map
.get_mut(s3_stack_name)
.get_mut(&s3_stack_name)
.context(error::MissingConfigSnafu {
missing: format!("aws.s3 config with name {}", s3_stack_name),
})?;
Ok(ValidRepoInfo {
s3_stack_name: s3_stack_name.to_string(),
s3_region: s3_info.region.as_ref().context(error::MissingConfigSnafu {
missing: format!("region for '{}' s3 config", s3_stack_name),
})?,
s3_region: Region::new(s3_info.region.as_ref().cloned().context(
error::MissingConfigSnafu {
missing: format!("region for '{}' s3 config", s3_stack_name),
},
)?),
bucket_name: &mut s3_info.bucket_name,
stack_arn: &mut s3_info.stack_arn,
vpce_id: s3_info
Expand Down Expand Up @@ -262,11 +293,11 @@ async fn create_repo_infrastructure(
// Create S3 bucket
info!("Creating S3 bucket...");
let (s3_stack_arn, bucket_name, bucket_rdn) =
s3::create_s3_bucket(repo_info.s3_region, &repo_info.s3_stack_name).await?;
s3::create_s3_bucket(&repo_info.s3_region, &repo_info.s3_stack_name).await?;

// Add Bucket Policy to newly created bucket
s3::add_bucket_policy(
repo_info.s3_region,
&repo_info.s3_region,
&bucket_name,
&repo_info.prefix,
repo_info.vpce_id,
Expand Down
39 changes: 26 additions & 13 deletions tools/infrasys/src/root.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use super::{error, KeyRole, Result};
use aws_config::meta::region::RegionProviderChain;
use log::{trace, warn};
use pubsys_config::SigningKeyConfig;
use rusoto_core::Region;
use snafu::{ensure, OptionExt, ResultExt};
use std::collections::HashMap;
use std::fs;
Expand Down Expand Up @@ -39,6 +39,21 @@ pub fn check_root(root_role_path: &Path) -> Result<()> {
});
Ok(())
}
pub fn get_region() -> Result<String> {
let rt = tokio::runtime::Runtime::new().context(error::RuntimeSnafu)?;
rt.block_on(async { async_get_region().await })
}

async fn async_get_region() -> Result<String> {
let default_region_fallback = "us-east-1";
let default_region = RegionProviderChain::default_provider()
.or_else(default_region_fallback)
.region()
.await
.context(error::DefaultRegionSnafu)?
.to_string();
Ok(default_region)
}

/// Creates the directory where root.json will live and creates root.json itself according to details specified in root-role-path
pub fn create_root(root_role_path: &Path) -> Result<()> {
Expand All @@ -48,22 +63,20 @@ pub fn create_root(root_role_path: &Path) -> Result<()> {
thing: "root role",
})?;
fs::create_dir_all(role_dir).context(error::MkdirSnafu { path: role_dir })?;
let default_region = get_region()?;

// Initialize root
tuftool!(&default_region, "root init '{}'", root_role_path.display());
tuftool!(
Region::default().name(),
"root init '{}'",
root_role_path.display()
);
tuftool!(
Region::default().name(),
&default_region,
// TODO: expose expiration date as a configurable parameter
"root expire '{}' 'in 52 weeks'",
root_role_path.display()
);
Ok(())
}

/// Adds keys to root.json according to key type
/// Adds keys to root.json according to key type
pub fn add_keys(
signing_key_config: &mut SigningKeyConfig,
role: &KeyRole,
Expand Down Expand Up @@ -108,11 +121,11 @@ fn add_keys_kms(
num_keys: (*available_keys).len(),
}
);

let default_region = get_region()?;
match role {
KeyRole::Root => {
tuftool!(
Region::default().name(),
&default_region,
"root set-threshold '{}' root '{}' ",
filepath,
threshold.to_string()
Expand All @@ -128,19 +141,19 @@ fn add_keys_kms(
}
KeyRole::Publication => {
tuftool!(
Region::default().name(),
&default_region,
"root set-threshold '{}' snapshot '{}' ",
filepath,
threshold.to_string()
);
tuftool!(
Region::default().name(),
&default_region,
"root set-threshold '{}' targets '{}' ",
filepath,
threshold.to_string()
);
tuftool!(
Region::default().name(),
&default_region,
"root set-threshold '{}' timestamp '{}' ",
filepath,
threshold.to_string()
Expand Down
Loading

0 comments on commit 5f7ac20

Please sign in to comment.