#[derive(clap::Args)]
pub struct BindArgs {
#[clap(value_parser)]
name: String,
#[clap(long, min_values = 1)]
certificate: Vec<String>,
#[clap(long)]
private_key: String,
#[clap(long)]
profile_arn: String,
#[clap(long)]
trust_anchor_arn: String,
#[clap(long)]
role_arn: String,
#[clap(long)]
session_duration: Option<u32>,
#[clap(long)]
session_name: Option<String>,
#[clap(long, action = clap::ArgAction::SetTrue)]
no_validate: bool,
#[clap(arg_enum, long)]
mode: Option<EnvironmentModeArg>,
#[clap(long)]
region: Option<String>,
}
#[derive(Clone, Debug, clap::ValueEnum)]
pub enum EnvironmentModeArg {
EcsFull,
EcsRelative,
EcsFullQuery,
EcsRelativeQuery,
}
impl EnvironmentModeArg {
fn with_opts(&self, opts: crate::binding::EnvironmentOpts) -> crate::binding::EnvironmentMode {
match self {
EnvironmentModeArg::EcsFull => crate::binding::EnvironmentMode::EcsFull(opts),
EnvironmentModeArg::EcsFullQuery => crate::binding::EnvironmentMode::EcsFullQuery(opts),
EnvironmentModeArg::EcsRelative => crate::binding::EnvironmentMode::EcsRelative(opts),
EnvironmentModeArg::EcsRelativeQuery => {
crate::binding::EnvironmentMode::EcsRelativeQuery(opts)
}
}
}
}
#[tokio::main]
pub async fn run(config: &crate::config::Config, args: &BindArgs) -> Result<(), anyhow::Error> {
let _span = tracing::info_span!("bind").entered();
let req = crate::client::CreateSessionRequest {
role_arn: args.role_arn.clone(),
profile_arn: args.profile_arn.clone(),
trust_anchor_arn: args.trust_anchor_arn.clone(),
duration_seconds: args.session_duration.map(|v| v.into()),
session_name: args.session_name.clone(),
};
let env_opts = crate::binding::EnvironmentOpts::default();
let env_mode = match args.mode {
Some(ref ma) => ma.with_opts(env_opts),
None => crate::binding::EnvironmentMode::EcsFull(env_opts),
};
let binding = crate::binding::RoleBinding::new(
args.name.clone(),
args.certificate.clone(),
args.private_key.clone(),
env_mode,
req,
)?;
tracing::debug!(role_binding = ?binding);
let validate = !args.no_validate;
if validate {
tracing::info!("Validating configuration...");
let identity = binding.identity().await?;
let client = crate::client::Client::new(args.region.as_ref().map(|v| v.as_ref()))?;
let session = client.create(&identity, &binding.request).await?;
let assumed_role = session.credential_set.get(0).ok_or_else(|| {
crate::error::Error::Unknown("returned CredentialSet is missing item".to_string())
})?;
tracing::info!(message = "Configuration validated and looks okay", access_key_id = ?assumed_role.credentials.access_key_id, expiration = ?assumed_role.credentials.expiration, assumed_role_user_arn= ?assumed_role.assumed_role_user.arn);
}
binding.save(config).await?;
tracing::info!(message = "Saved a role binding and rendered an environment file", environment_file = ?binding.env_path(config));
Ok(())
}