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

feat(aws): add a fallback for expiration key #4455

Merged
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 3 additions & 0 deletions docs/config/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -326,6 +326,9 @@ When using [AWSume](https://awsu.me) the profile
is read from the `AWSUME_PROFILE` env var and the credentials expiration
date is read from the `AWSUME_EXPIRATION` env var.

When using [saml2aws](https://github.com/Versent/saml2aws) the expiration information obtained from `~/.aws/credentials`
falls back to the `x_security_token_expires` key.

### Options

| Option | Default | Description |
Expand Down
99 changes: 55 additions & 44 deletions src/modules/aws.rs
Original file line number Diff line number Diff line change
Expand Up @@ -131,8 +131,10 @@ fn get_credentials_duration(
let creds = get_creds(context, aws_creds)?;
let section = get_profile_creds(creds, aws_profile)?;

section
.get("expiration")
let expiration_keys = ["expiration", "x_security_token_expires"];
expiration_keys
.iter()
.find_map(|expiration_key| section.get(expiration_key))
.and_then(|expiration| DateTime::parse_from_rfc3339(expiration).ok())
}?;

Expand Down Expand Up @@ -655,54 +657,63 @@ credential_process = /opt/bin/awscreds-retriever

let expiration_date = now_plus_half_hour.to_rfc3339_opts(chrono::SecondsFormat::Secs, true);

file.write_all(
format!(
"[astronauts]
let expiration_keys = ["expiration", "x_security_token_expires"];
expiration_keys.iter().for_each(|key| {
file.write_all(
format!(
"[astronauts]
aws_access_key_id=dummy
aws_secret_access_key=dummy
expiration={}
{}={}
",
expiration_date
)
.as_bytes(),
)?;

let actual = ModuleRenderer::new("aws")
.env("AWS_PROFILE", "astronauts")
.env("AWS_REGION", "ap-northeast-2")
.env(
"AWS_SHARED_CREDENTIALS_FILE",
credentials_path.to_string_lossy().as_ref(),
key, expiration_date
)
.as_bytes(),
)
.collect();

let actual_variant = ModuleRenderer::new("aws")
.env("AWS_PROFILE", "astronauts")
.env("AWS_REGION", "ap-northeast-2")
.env(
"AWS_CREDENTIALS_FILE",
credentials_path.to_string_lossy().as_ref(),
)
.collect();

assert_eq!(
actual, actual_variant,
"both AWS_SHARED_CREDENTIALS_FILE and AWS_CREDENTIALS_FILE should work"
);

// In principle, "30m" should be correct. However, bad luck in scheduling
// on shared runners may delay it. Allow for up to 2 seconds of delay.
let possible_values = ["30m", "29m59s", "29m58s"];
let possible_values = possible_values.map(|duration| {
let segment_colored = format!("☁️ astronauts (ap-northeast-2) [{}] ", duration);
Some(format!(
"on {}",
Color::Yellow.bold().paint(segment_colored)
))
.unwrap();

let actual = ModuleRenderer::new("aws")
.env("AWS_PROFILE", "astronauts")
.env("AWS_REGION", "ap-northeast-2")
.env(
"AWS_SHARED_CREDENTIALS_FILE",
credentials_path.to_string_lossy().as_ref(),
)
.collect();

let actual_variant = ModuleRenderer::new("aws")
.env("AWS_PROFILE", "astronauts")
.env("AWS_REGION", "ap-northeast-2")
.env(
"AWS_CREDENTIALS_FILE",
credentials_path.to_string_lossy().as_ref(),
)
.collect();

assert_eq!(
actual, actual_variant,
"both AWS_SHARED_CREDENTIALS_FILE and AWS_CREDENTIALS_FILE should work"
);

// In principle, "30m" should be correct. However, bad luck in scheduling
// on shared runners may delay it.
let possible_values = [
"30m2s", "30m1s", "30m", "29m59s", "29m58s", "29m57s", "29m56s", "29m55s",
];
let possible_values = possible_values.map(|duration| {
let segment_colored = format!("☁️ astronauts (ap-northeast-2) [{}] ", duration);
Some(format!(
"on {}",
Color::Yellow.bold().paint(segment_colored)
))
});

assert!(
possible_values.contains(&actual),
"time is not in range: {actual:?}"
);
});

assert!(possible_values.contains(&actual));

dir.close()
}

Expand Down