Files
Triple-C/app/src-tauri/src/commands/aws_commands.rs
Josh Knapp ef67b447b3
All checks were successful
Build App / compute-version (push) Successful in 3s
Build App / build-linux (push) Successful in 4m46s
Build App / build-windows (push) Successful in 6m57s
Build App / build-macos (push) Successful in 9m9s
Build App / create-tag (push) Successful in 3s
Build App / sync-to-github (push) Successful in 12s
Pre-validate AWS SSO session on host during container startup
For Bedrock Profile projects, SSO credentials are now checked and
refreshed on the host before the container starts, so the entrypoint
copies already-valid tokens. This eliminates the delay where users
had to wait for the terminal to open before being prompted to login.

The terminal-time fallback remains for mid-session credential expiry.
Also consolidates duplicated profile resolution logic into a shared
helper in aws_commands.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 06:54:59 -07:00

82 lines
2.6 KiB
Rust

use tauri::State;
use crate::models::Project;
use crate::AppState;
/// Resolve AWS profile: project-level → global settings → "default".
pub fn resolve_profile_for_project(project: &Project, global_profile: Option<&str>) -> String {
project
.bedrock_config
.as_ref()
.and_then(|b| b.aws_profile.clone())
.or_else(|| global_profile.map(|s| s.to_string()))
.unwrap_or_else(|| "default".to_string())
}
/// Check if the AWS session is valid for the given profile on the host.
/// Returns `Ok(true)` if valid, `Ok(false)` if expired/invalid.
pub async fn check_sso_session(profile: &str) -> Result<bool, String> {
let output = tokio::process::Command::new("aws")
.args(["sts", "get-caller-identity", "--profile", profile])
.output()
.await
.map_err(|e| format!("Failed to run aws sts get-caller-identity: {}", e))?;
Ok(output.status.success())
}
/// Check if the given AWS profile uses SSO (has sso_start_url or sso_session configured).
pub async fn is_sso_profile(profile: &str) -> Result<bool, String> {
let check_start_url = tokio::process::Command::new("aws")
.args(["configure", "get", "sso_start_url", "--profile", profile])
.output()
.await;
if let Ok(out) = check_start_url {
if out.status.success() {
return Ok(true);
}
}
let check_session = tokio::process::Command::new("aws")
.args(["configure", "get", "sso_session", "--profile", profile])
.output()
.await;
if let Ok(out) = check_session {
if out.status.success() {
return Ok(true);
}
}
Ok(false)
}
/// Run `aws sso login --profile X` on the host. This is interactive (opens a browser).
pub async fn run_sso_login(profile: &str) -> Result<(), String> {
log::info!("Running host-side AWS SSO login for profile '{}'", profile);
let status = tokio::process::Command::new("aws")
.args(["sso", "login", "--profile", profile])
.status()
.await
.map_err(|e| format!("Failed to run aws sso login: {}", e))?;
if !status.success() {
return Err("SSO login failed or was cancelled".to_string());
}
Ok(())
}
#[tauri::command]
pub async fn aws_sso_refresh(
project_id: String,
state: State<'_, AppState>,
) -> Result<(), String> {
let project = state.projects_store.get(&project_id)
.ok_or_else(|| format!("Project {} not found", project_id))?;
let profile = resolve_profile_for_project(
&project,
state.settings_store.get().global_aws.aws_profile.as_deref(),
);
run_sso_login(&profile).await
}