Skip to content

Commit 3cb80f0

Browse files
committed
feat: add cloudtrail tracking to execute_bash
1 parent 19f7456 commit 3cb80f0

File tree

3 files changed

+86
-0
lines changed

3 files changed

+86
-0
lines changed

crates/chat-cli/src/cli/chat/tools/execute/mod.rs

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,12 @@ use crate::cli::chat::tools::{
2323
use crate::cli::chat::util::truncate_safe;
2424
use crate::os::Os;
2525

26+
/// The environment variable name where we set additional metadata for the AWS CLI user agent.
27+
const USER_AGENT_ENV_VAR: &str = "AWS_EXECUTION_ENV";
28+
const USER_AGENT_APP_NAME: &str = "AmazonQ-For-CLI";
29+
const USER_AGENT_VERSION_KEY: &str = "Version";
30+
const USER_AGENT_VERSION_VALUE: &str = env!("CARGO_PKG_VERSION");
31+
2632
// Platform-specific modules
2733
#[cfg(windows)]
2834
mod windows;
@@ -247,6 +253,33 @@ pub fn format_output(output: &str, max_size: usize) -> String {
247253
)
248254
}
249255

256+
/// Helper function to set up environment variables with user agent metadata for CloudTrail tracking
257+
pub fn setup_env_vars() -> std::collections::HashMap<String, String> {
258+
let mut env_vars: std::collections::HashMap<String, String> = std::env::vars().collect();
259+
260+
// Set up additional metadata for the AWS CLI user agent
261+
let user_agent_metadata_value = format!(
262+
"{} {}/{}",
263+
USER_AGENT_APP_NAME, USER_AGENT_VERSION_KEY, USER_AGENT_VERSION_VALUE
264+
);
265+
266+
// If the user agent metadata env var already exists, append to it, otherwise set it
267+
if let Some(existing_value) = env_vars.get(USER_AGENT_ENV_VAR) {
268+
if !existing_value.is_empty() {
269+
env_vars.insert(
270+
USER_AGENT_ENV_VAR.to_string(),
271+
format!("{} {}", existing_value, user_agent_metadata_value),
272+
);
273+
} else {
274+
env_vars.insert(USER_AGENT_ENV_VAR.to_string(), user_agent_metadata_value);
275+
}
276+
} else {
277+
env_vars.insert(USER_AGENT_ENV_VAR.to_string(), user_agent_metadata_value);
278+
}
279+
280+
env_vars
281+
}
282+
250283
#[cfg(test)]
251284
mod tests {
252285
use super::*;
@@ -384,4 +417,47 @@ mod tests {
384417
);
385418
}
386419
}
420+
421+
#[test]
422+
fn test_cloudtrail_tracking() {
423+
// Test that setup_env_vars sets the AWS_EXECUTION_ENV variable correctly
424+
let env_vars = setup_env_vars();
425+
426+
// Check that AWS_EXECUTION_ENV is set
427+
assert!(env_vars.contains_key(USER_AGENT_ENV_VAR));
428+
429+
let user_agent_value = env_vars.get(USER_AGENT_ENV_VAR).unwrap();
430+
431+
// Check that it contains our app name and version
432+
assert!(user_agent_value.contains(USER_AGENT_APP_NAME));
433+
assert!(user_agent_value.contains(USER_AGENT_VERSION_KEY));
434+
assert!(user_agent_value.contains(USER_AGENT_VERSION_VALUE));
435+
436+
// Check the format is correct
437+
let expected_metadata = format!(
438+
"{} {}/{}",
439+
USER_AGENT_APP_NAME, USER_AGENT_VERSION_KEY, USER_AGENT_VERSION_VALUE
440+
);
441+
assert!(user_agent_value.contains(&expected_metadata));
442+
}
443+
444+
#[test]
445+
fn test_cloudtrail_tracking_with_existing_env() {
446+
// Set an existing AWS_EXECUTION_ENV value
447+
unsafe {
448+
std::env::set_var(USER_AGENT_ENV_VAR, "ExistingValue");
449+
}
450+
451+
let env_vars = setup_env_vars();
452+
let user_agent_value = env_vars.get(USER_AGENT_ENV_VAR).unwrap();
453+
454+
// Should contain both the existing value and our metadata
455+
assert!(user_agent_value.contains("ExistingValue"));
456+
assert!(user_agent_value.contains(USER_AGENT_APP_NAME));
457+
458+
// Clean up
459+
unsafe {
460+
std::env::remove_var(USER_AGENT_ENV_VAR);
461+
}
462+
}
387463
}

crates/chat-cli/src/cli/chat/tools/execute/unix.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ use tracing::error;
1313
use super::{
1414
CommandResult,
1515
format_output,
16+
setup_env_vars,
1617
};
1718

1819
/// Run a bash command on Unix systems.
@@ -29,10 +30,14 @@ pub async fn run_command<W: Write>(
2930
) -> Result<CommandResult> {
3031
let shell = std::env::var("AMAZON_Q_CHAT_SHELL").unwrap_or("bash".to_string());
3132

33+
// Set up environment variables with user agent metadata for CloudTrail tracking
34+
let env_vars = setup_env_vars();
35+
3236
// We need to maintain a handle on stderr and stdout, but pipe it to the terminal as well
3337
let mut child = tokio::process::Command::new(shell)
3438
.arg("-c")
3539
.arg(command)
40+
.envs(env_vars)
3641
.stdin(Stdio::inherit())
3742
.stdout(Stdio::piped())
3843
.stderr(Stdio::piped())

crates/chat-cli/src/cli/chat/tools/execute/windows.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ use tracing::error;
1313
use super::{
1414
CommandResult,
1515
format_output,
16+
setup_env_vars,
1617
};
1718

1819
/// Run a command on Windows using cmd.exe.
@@ -27,10 +28,14 @@ pub async fn run_command<W: Write>(
2728
max_result_size: usize,
2829
mut updates: Option<W>,
2930
) -> Result<CommandResult> {
31+
// Set up environment variables with user agent metadata for CloudTrail tracking
32+
let env_vars = setup_env_vars();
33+
3034
// We need to maintain a handle on stderr and stdout, but pipe it to the terminal as well
3135
let mut child = tokio::process::Command::new("cmd")
3236
.arg("/C")
3337
.arg(command)
38+
.envs(env_vars)
3439
.stdin(Stdio::inherit())
3540
.stdout(Stdio::piped())
3641
.stderr(Stdio::piped())

0 commit comments

Comments
 (0)