commit - 8b43cacff071605d7df7f2c9e7af81a0c78d36aa
commit + 5dd316e79476797a698d46a2e5699033134176a9
blob - d41a3be9a1ce49b0400358313e781c365b7c4a6e
blob + cddf32fda8c3b4f2ffaa843912bcca4858945bf2
--- Cargo.lock
+++ Cargo.lock
]
[[package]]
+name = "cesu8"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c"
+
+[[package]]
name = "cfg-if"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75"
[[package]]
+name = "combine"
+version = "4.6.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ba5a308b75df32fe02788e748662718f03fde005016435c444eea572398219fd"
+dependencies = [
+ "bytes",
+ "memchr",
+]
+
+[[package]]
name = "concurrent-queue"
version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c"
[[package]]
+name = "jni"
+version = "0.21.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1a87aa2bb7d2af34197c04845522473242e1aa17c12f4935d5856491a7fb8c97"
+dependencies = [
+ "cesu8",
+ "cfg-if",
+ "combine",
+ "jni-sys",
+ "log",
+ "thiserror 1.0.69",
+ "walkdir",
+ "windows-sys 0.45.0",
+]
+
+[[package]]
+name = "jni-sys"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130"
+
+[[package]]
name = "jobserver"
version = "0.1.34"
source = "registry+https://github.com/rust-lang/crates.io-index"
version = "0.1.0"
dependencies = [
"anyhow",
+ "aws-config",
+ "aws-types",
"clap",
"dialoguer",
+ "kops_aws_sso",
"kops_log",
"kops_protocol",
"tokio",
"tracing",
+ "webbrowser",
]
[[package]]
version = "0.1.0"
dependencies = [
"anyhow",
+ "chrono",
"clap",
"config",
"daemonize",
]
[[package]]
+name = "ndk-context"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "27b02d87554356db9e9a873add8782d4ea6e3e58ea071a9adb9a2e8ddb884a8b"
+
+[[package]]
name = "nu-ansi-term"
version = "0.50.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
]
[[package]]
+name = "objc2"
+version = "0.6.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b7c2599ce0ec54857b29ce62166b0ed9b4f6f1a70ccc9a71165b6154caca8c05"
+dependencies = [
+ "objc2-encode",
+]
+
+[[package]]
+name = "objc2-encode"
+version = "4.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ef25abbcd74fb2609453eb695bd2f860d389e457f67dc17cafc8b8cbc89d0c33"
+
+[[package]]
+name = "objc2-foundation"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e3e0adef53c21f888deb4fa59fc59f7eb17404926ee8a6f59f5df0fd7f9f3272"
+dependencies = [
+ "bitflags",
+ "objc2",
+]
+
+[[package]]
name = "once_cell"
version = "1.21.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f"
[[package]]
+name = "same-file"
+version = "1.0.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502"
+dependencies = [
+ "winapi-util",
+]
+
+[[package]]
name = "schannel"
version = "0.1.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c3082ca00d5a5ef149bb8b555a72ae84c9c59f7250f013ac822ac2e49b19c64"
[[package]]
+name = "walkdir"
+version = "2.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b"
+dependencies = [
+ "same-file",
+ "winapi-util",
+]
+
+[[package]]
name = "want"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
]
[[package]]
+name = "web-sys"
+version = "0.3.82"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3a1f95c0d03a47f4ae1f7a64643a6bb97465d9b740f0fa8f90ea33915c99a9a1"
+dependencies = [
+ "js-sys",
+ "wasm-bindgen",
+]
+
+[[package]]
+name = "webbrowser"
+version = "1.0.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "00f1243ef785213e3a32fa0396093424a3a6ea566f9948497e5a2309261a4c97"
+dependencies = [
+ "core-foundation 0.10.1",
+ "jni",
+ "log",
+ "ndk-context",
+ "objc2",
+ "objc2-foundation",
+ "url",
+ "web-sys",
+]
+
+[[package]]
+name = "winapi-util"
+version = "0.1.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22"
+dependencies = [
+ "windows-sys 0.61.2",
+]
+
+[[package]]
name = "windows-core"
version = "0.62.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "windows-sys"
+version = "0.45.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0"
+dependencies = [
+ "windows-targets 0.42.2",
+]
+
+[[package]]
+name = "windows-sys"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
[[package]]
name = "windows-targets"
+version = "0.42.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071"
+dependencies = [
+ "windows_aarch64_gnullvm 0.42.2",
+ "windows_aarch64_msvc 0.42.2",
+ "windows_i686_gnu 0.42.2",
+ "windows_i686_msvc 0.42.2",
+ "windows_x86_64_gnu 0.42.2",
+ "windows_x86_64_gnullvm 0.42.2",
+ "windows_x86_64_msvc 0.42.2",
+]
+
+[[package]]
+name = "windows-targets"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
[[package]]
name = "windows_aarch64_gnullvm"
+version = "0.42.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8"
+
+[[package]]
+name = "windows_aarch64_gnullvm"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
[[package]]
name = "windows_aarch64_msvc"
+version = "0.42.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43"
+
+[[package]]
+name = "windows_aarch64_msvc"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
[[package]]
name = "windows_i686_gnu"
+version = "0.42.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f"
+
+[[package]]
+name = "windows_i686_gnu"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
[[package]]
name = "windows_i686_msvc"
+version = "0.42.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060"
+
+[[package]]
+name = "windows_i686_msvc"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
[[package]]
name = "windows_x86_64_gnu"
+version = "0.42.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36"
+
+[[package]]
+name = "windows_x86_64_gnu"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
[[package]]
name = "windows_x86_64_gnullvm"
+version = "0.42.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3"
+
+[[package]]
+name = "windows_x86_64_gnullvm"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
[[package]]
name = "windows_x86_64_msvc"
+version = "0.42.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0"
+
+[[package]]
+name = "windows_x86_64_msvc"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
blob - 9e54c2456c150d9dfe7a305a792fe99c4975219b
blob + f62f88dfbbf876b7f19291bc78d6c856a115d1f8
--- Cargo.toml
+++ Cargo.toml
all = { level = "warn", priority = -1 }
[workspace.dependencies]
+kops_aws_sso = { version = "=0.1.0", path = "crates/kops_aws_sso" }
kops_log = { version = "=0.1.0", path = "crates/kops_log" }
kops_protocol = { version = "=0.1.0", path = "crates/kops_protocol" }
aws-credential-types = "=1.2.10"
aws-sdk-sso = "=1.90.0"
aws-sdk-ssooidc = "=1.92.0"
+aws-types = "=1.3.10"
bincode = "=2.0.1"
chrono = { version = "0.4", features = ["clock", "serde"] }
clap = { version = "=4.5.53", features = ["derive", "env"] }
blob - 2c19e0b681afb8959610e668a41f2be2e5f590bb
blob + f56d5d4bcc487b5ef9a0ab4f3df36a1fd084876b
--- crates/kops_aws_sso/src/lib.rs
+++ crates/kops_aws_sso/src/lib.rs
.await
.context("failed to start device authorization")?;
+ let verification_uri = device_auth
+ .verification_uri_complete()
+ .ok_or(anyhow!("missing verification URI"))?;
+
let device_code = must(device_auth.device_code(), "device_code")?;
let verification_uri = device_auth
.verification_uri_complete()
blob - 67012d53d2e0050150e27f10dbbbb755ee53f201
blob + e366e724d0780028563ba609e69247912d6eb450
--- crates/kops_protocol/src/lib.rs
+++ crates/kops_protocol/src/lib.rs
/// Health-check: the daemon must reply with `Response::Pong`.
Ping,
- Login,
+ Login(LoginRequest),
Pods(PodsRequest),
Env(EnvRequest),
/// Response for `Request::Ping`,
Pong,
+ /// Login successfully registered in daemon
LoginOk,
Version(VersionInfo),
(reason, message, ready, restarts)
}
+
+#[derive(Debug, Encode, Decode)]
+pub struct LoginRequest {
+ /// Logical profile name, e.g. "dev" or "prod".
+ pub name: String,
+
+ /// Optional region associated with this profile.
+ pub region: Option<String>,
+
+ /// AWS account ID where this role is valid.
+ pub account_id: String,
+
+ /// IAM role name assumed via SSO.
+ pub role_name: String,
+
+ /// AWS access key ID from SSO.
+ pub access_key_id: String,
+
+ /// AWS secret access key from SSO.
+ pub secret_access_key: String,
+
+ /// Temporary session token from SSO.
+ pub session_token: String,
+
+ /// Expiration of this session as Unix epoch milliseconds (UTC).
+ pub expires_at_epoch_ms: i64,
+}
blob - f681f50610a0ae1ffb26827e7357f7f1914c68c2
blob + c04aedf8fc4b9e16e60484aa925f646a89eafda1
--- kopsctl/Cargo.toml
+++ kopsctl/Cargo.toml
[dependencies]
anyhow.workspace = true
+aws-config.workspace = true
+aws-types.workspace = true
clap.workspace = true
dialoguer.workspace = true
+kops_aws_sso.workspace = true
kops_log.workspace = true
kops_protocol.workspace = true
tokio.workspace = true
tracing.workspace = true
+webbrowser.workspace = true
[lints]
workspace = true
blob - 1d33f4409dbe65886df7591f74bef53c64dbaa1c
blob + 1fdf4a4d1689ac189eb9d0cfca5ad5f7ae3f6817
--- kopsctl/src/cmd/login.rs
+++ kopsctl/src/cmd/login.rs
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
//
-use anyhow::{Result, bail};
+use anyhow::{Result, anyhow, bail};
+use aws_config::BehaviorVersion;
+use aws_types::region::Region;
+use kops_aws_sso::{SsoLoginConfig, login_device_flow};
+use kops_protocol::{LoginRequest, Request, Response};
-use kops_protocol::{Request, Response};
-
use crate::helper::send_request;
-pub async fn execute() -> Result<()> {
- let resp = send_request(Request::Login).await?;
+pub async fn execute(name: String, region: Option<String>) -> Result<()> {
+ let region = region
+ .or_else(|| std::env::var("AWS_REGION").ok())
+ .unwrap_or_else(|| "us-east-1".to_string());
+ let start_url = std::env::var("KOPS_SSO_START_URL")
+ .map_err(|_| anyhow!("KOPS_SSO_START_URL not set"))?;
+ let account_id = std::env::var("KOPS_SSO_ACCOUNT_ID")
+ .map_err(|_| anyhow!("KOPS_SSO_ACCOUNT_ID not set"))?;
+ let role_name = std::env::var("KOPS_SSO_ROLE_NAME")
+ .map_err(|_| anyhow!("KOPS_SSO_ROLE_NAME not set"))?;
+
+ let client_name = format!("kops");
+
+ let sso_cfg = SsoLoginConfig {
+ region: region.clone(),
+ start_url,
+ account_id: account_id.clone(),
+ role_name: role_name.clone(),
+ client_name,
+ };
+
+ let sdk_config = aws_config::from_env()
+ .region(Region::new(region.clone()))
+ .load()
+ .await;
+
+ println!("Starting AWS SSO device flow for profile '{name}'...");
+ println!("Region : {region}");
+ println!("Account ID : {account_id}");
+ println!("Role name : {role_name}");
+ println!();
+
+ let session = login_device_flow(&sdk_config, &sso_cfg, |info| {
+ println!("SSO user code : {}", info.user_code);
+ println!("Verification URL : {}", info.verification_uri);
+
+ if let Some(full) = &info.verification_uri_complete {
+ println!("Verification (full) : {full}");
+
+ if let Err(err) = webbrowser::open(full) {
+ eprintln!("Failed to open browser automatically: {err}");
+ eprintln!("Please open the URL manually.");
+ } else {
+ println!(
+ "Browser opened automatically, please finish authentication."
+ );
+ }
+ } else if let Err(err) = webbrowser::open(&info.verification_uri) {
+ eprintln!("Failed to open browser automatically: {err}");
+ eprintln!("Please open the URL manually.");
+ } else {
+ println!(
+ "Browser opened automatically, please finish authentication."
+ );
+ }
+
+ println!();
+ println!("Waiting for AWS SSO authorization...");
+ })
+ .await?;
+
+ println!(
+ "Successfully obtained AWS credentials for account {} role {}",
+ session.account_id, session.role_name
+ );
+
+ let expires_at_epoch_ms = session.expires_at.timestamp_millis();
+
+ let creds = session.credentials;
+ let access_key_id = creds.access_key_id().to_string();
+ let secret_access_key = creds.secret_access_key().to_string();
+ let session_token = creds
+ .session_token()
+ .ok_or_else(|| anyhow!("missing session token in AWS credentials"))?
+ .to_string();
+
+ let req = Request::Login(LoginRequest {
+ name: name.clone(),
+ region: Some(region),
+ account_id,
+ role_name,
+ access_key_id,
+ secret_access_key,
+ session_token,
+ expires_at_epoch_ms,
+ });
+
+ let resp = send_request(req).await?;
+
match resp {
- Response::LoginOk => print_login_info(),
- Response::Error { message } => bail!("reponse error {message}"),
- _ => bail!("unexpected response to version"),
+ Response::LoginOk => {
+ println!(
+ "kopsd registered AWS session for profile '{name}' successfully."
+ );
+ }
+ Response::Error { message } => {
+ bail!("daemon returned error on login: {message}");
+ }
+ _ => bail!("unexpected response to login"),
}
Ok(())
}
-
-fn print_login_info() {
- println!("login ok");
-}
blob - 8afcb435a3252d9616c2cdd15312e411aea7d5e4
blob + 165fa0600e9635c0a977f44d3806fcf0f044f431
--- kopsctl/src/main.rs
+++ kopsctl/src/main.rs
/// Ping the daemon and expect a Pong response.
Ping,
- /// Login to the aws
- Login,
+ /// Login via AWS SSO and register credentials in kopsd
+ Login {
+ /// Logical name for this credential set (e.g. dev, prod)
+ #[arg(long)]
+ name: String,
+ /// AWS region for SSO (optional, defaults to config or us-east-1)
+ #[arg(long)]
+ region: Option<String>,
+ },
+
/// Show daemon and protocol version
Version,
match args.command {
Command::Ping => cmd::ping::execute().await?,
- Command::Login => cmd::login::execute().await?,
+ Command::Login { name, region } => {
+ cmd::login::execute(name, region).await?
+ }
Command::Version => cmd::version::execute().await?,
Command::Pods { cluster, namespace, failed_only } => {
cmd::pods::execute(cluster, namespace, failed_only).await?
blob - b974932c59871600a915c99522dfb7e2eb3b2380
blob + d4f8871404773124280108e5f09e2bc43cb1e1e2
--- kopsd/Cargo.toml
+++ kopsd/Cargo.toml
[dependencies]
anyhow.workspace = true
+chrono.workspace = true
clap.workspace = true
config.workspace = true
daemonize.workspace = true
blob - 804f99b9964ceb3f4a37a5da2acd641deab88d4d
blob + 27a3846d04bd7f1ecbc20b96792e43336afde4c2
--- kopsd/src/handler.rs
+++ kopsd/src/handler.rs
use std::sync::Arc;
+use chrono::{TimeZone, Utc};
use k8s_openapi::api::core::v1::Pod;
use kops_protocol::{
- EnvEntry, EnvRequest, PodSummary, PodsRequest, Request, Response,
+ EnvEntry, EnvRequest, LoginRequest, PodSummary, PodsRequest, Request,
+ Response,
};
use kube::ResourceExt;
+use tracing::info;
-use crate::state::DaemonState;
+use crate::state::{AwsSession, DaemonState};
pub struct Handler {
state: Arc<DaemonState>,
pub async fn handle(&self, req: Request) -> Response {
match req {
Request::Ping => Response::Pong,
- Request::Login => Response::LoginOk,
+ Request::Login(login_req) => self.handle_login(login_req).await,
Request::Version => self.handle_version().await,
Request::Pods(p) => self.handle_pods(p).await,
Request::Env(r) => self.handle_env(r).await,
}
}
+ async fn handle_login(&self, req: LoginRequest) -> Response {
+ info!(
+ "received AWS login for profile '{}' (account {} role {})",
+ req.name, req.account_id, req.role_name
+ );
+
+ let expires_at = Utc
+ .timestamp_millis_opt(req.expires_at_epoch_ms)
+ .single()
+ .unwrap_or_else(|| Utc::now());
+
+ let session = AwsSession {
+ account_id: req.account_id,
+ role_name: req.role_name,
+ region: req.region.clone(),
+ access_key_id: req.access_key_id,
+ secret_access_key: req.secret_access_key,
+ session_token: req.session_token,
+ expires_at,
+ };
+
+ match self.state.aws_sessions.lock() {
+ Ok(mut map) => {
+ map.insert(req.name.clone(), session);
+ info!("stored AWS session for profile '{}'", req.name);
+ Response::LoginOk
+ }
+ Err(_) => Response::Error {
+ message: "failed to lock aws_sessions map".into(),
+ },
+ }
+ }
+
async fn handle_env(&self, req: EnvRequest) -> Response {
let cluster = req
.cluster
blob - 537caf4d8e725986ab270adea8b30f905bab7f49
blob + da25e6bbcbb16dbed6de3816f4e9803a375b845a
--- kopsd/src/server.rs
+++ kopsd/src/server.rs
.context("failed to build tokio runtime")?;
rt.block_on(async move {
- let mut clusters_map = std::collections::HashMap::new();
- for c in &config.cluster {
- let cs = init_cluster_state(c.clone()).await.unwrap();
- clusters_map.insert(c.name.clone(), cs);
- }
+ let clusters_map = std::collections::HashMap::new();
+ // for c in &config.cluster {
+ // let cs = init_cluster_state(c.clone()).await.unwrap();
+ // // clusters_map.insert(c.name.clone(), cs);
+ // }
let default_cluster = config
.kops
.clone()
.unwrap_or_else(|| config.cluster[0].name.clone());
- let state =
- Arc::new(DaemonState { clusters: clusters_map, default_cluster });
+ // let state =
+ // Arc::new(DaemonState { clusters: clusters_map, default_cluster });
+ let state = Arc::new(DaemonState {
+ clusters: clusters_map,
+ default_cluster,
+ aws_sessions: std::sync::Mutex::new(
+ std::collections::HashMap::new(),
+ ),
+ });
// for c in config.cluster.clone() {
// let cluster_name = c.name.clone();
blob - e1fa0e1dd4458edfb8fd27f4644d3fe4367863b9
blob + 2bfcf0a77e38dfd27b14ab30f08961d9250275e7
--- kopsd/src/state.rs
+++ kopsd/src/state.rs
//
use std::collections::HashMap;
-use std::sync::Arc;
+use std::sync::{Arc, Mutex};
+use chrono::{DateTime, Utc};
use k8s_openapi::api::core::v1::Pod;
use kube::runtime::reflector::Store;
+/// AWS session stored in daemon memory.
+#[derive(Clone)]
+pub struct AwsSession {
+ pub account_id: String,
+ pub role_name: String,
+ pub region: Option<String>,
+ pub access_key_id: String,
+ pub secret_access_key: String,
+ pub session_token: String,
+ pub expires_at: DateTime<Utc>,
+}
+
/// Logical name of the cluster (from config).
pub type ClusterName = String;
pub struct DaemonState {
pub clusters: HashMap<ClusterName, Arc<ClusterState>>,
pub default_cluster: ClusterName,
+
+ /// AWS sessions keyed by logical profile name ("dev", "prod", ...).
+ pub aws_sessions: Mutex<HashMap<String, AwsSession>>,
}
impl DaemonState {
pub fn default_cluster(&self) -> &str {
&self.default_cluster
}
+
+ #[allow(dead_code)]
+ pub fn get_session(&self, name: &str) -> Option<AwsSession> {
+ let sessions = self.aws_sessions.lock().ok()?;
+ sessions.get(name).cloned()
+ }
}
/// Per-cluster in-memory state backed by a reflector Store.