commit c71cc900bed6be4372957b42316a516c75575bb1 from: murilo ijanc date: Fri Nov 28 18:07:15 2025 UTC Generating aws eks token commit - 58786c5f343a9270afe5ce81fb158379ccf27849 commit + c71cc900bed6be4372957b42316a516c75575bb1 blob - /dev/null blob + e4e220b13c5171d236cbb61100ac24acf7d1438e (mode 644) --- /dev/null +++ crates/kops_eks/Cargo.toml @@ -0,0 +1,24 @@ +[package] +name = "kops_eks" +version = "0.1.0" +edition = "2024" + +[dependencies] +anyhow = "1" +aws-config = { version = "1", features = ["behavior-version-latest"] } +aws-sdk-eks = "1" +aws-credential-types = "1" +aws-sigv4 = "1" +http = "1" +base64 = "0.22" +kube = { version = "0.91", features = ["client", "rustls-tls"] } +k8s-openapi = { version = "0.22", features = ["v1_30"] } +tokio = { version = "1", features = ["macros", "rt-multi-thread"] } +aws-smithy-runtime-api = "1.9.2" +rustls = { version = "0.23", default-features = false, features = ["ring"] } +rustls-pemfile = "2" +aws-sdk-sts = "1.94.0" +urlencoding = "2.1" +percent-encoding = "2.3" +url = "2.5.7" +pem = "3.0.6" blob - /dev/null blob + cc56ce3257a24b2db2485fb4ab0d4875dea69737 (mode 644) --- /dev/null +++ crates/kops_eks/src/main.rs @@ -0,0 +1,138 @@ +#![allow(unused_imports, unused_variables, unused_mut)] +use anyhow::{Context, Result, anyhow}; +use aws_config::BehaviorVersion; +use aws_credential_types::provider::ProvideCredentials; +use aws_sdk_eks as eks; +use aws_sigv4::http_request::SignatureLocation; +use aws_sigv4::http_request::{ + SignableBody, SignableRequest, SigningParams, SigningSettings, sign, +}; +use aws_sigv4::sign::v4; +use aws_smithy_runtime_api::client::identity::Identity; +use base64::Engine; +use base64::engine::general_purpose::{STANDARD, URL_SAFE_NO_PAD}; +use http::Uri; +use http::header; +use k8s_openapi::api::core::v1::Pod; +use kube::Api; +use kube::config::{AuthInfo, Config as KubeConfig}; +use percent_encoding::{NON_ALPHANUMERIC, utf8_percent_encode}; +use rustls::crypto::aws_lc_rs; +use rustls_pemfile::Item; +use std::io::Cursor; +use std::time::{Duration, SystemTime}; + +#[tokio::main] +async fn main() -> Result<()> { + aws_lc_rs::default_provider() + .install_default() + .expect("failed to install aws-lc provider"); + + let region = "us-east-1"; + let cluster_name = "my-cluster"; + + let token = main2(cluster_name, region).await?; + + let (eks_cluster_url, eks_cluster_cert) = eks_k8s_cluster_info(cluster_name).await?; + + let kubeconfig = kube::Config { + cluster_url: eks_cluster_url, + default_namespace: "observability".to_string(), + auth_info: kube::config::AuthInfo { + token: Some(token.clone().into()), + ..Default::default() + }, + root_cert: Some(eks_cluster_cert), + accept_invalid_certs: false, + connect_timeout: Some(Duration::from_secs(30)), + read_timeout: Some(Duration::from_secs(295)), + write_timeout: None, + proxy_url: None, + tls_server_name: None, + }; + + let client = kube::Client::try_from(kubeconfig)?; + let pods: Api = Api::namespaced(client, "observability"); + for p in pods.list(&Default::default()).await?.items { + println!("{}", p.metadata.name.unwrap_or_default()); + } + + Ok(()) +} + +pub async fn eks_k8s_cluster_info(cluster_name: &str) -> Result<(http::Uri, Vec>)> { + let sdk_config = aws_config::load_defaults(BehaviorVersion::latest()).await; + let client = eks::Client::new(&sdk_config); + + let resp = client.describe_cluster().name(cluster_name).send().await?; + + let cluster = resp.cluster().context("Unable to find cluster")?.to_owned(); + let b64_cert = cluster + .certificate_authority() + .context("Unable to find certificate authority")? + .data() + .context("Unable to find certificate data")?; + let cert = pem::parse(STANDARD.decode(b64_cert)?)?.into_contents(); + let endpoint = cluster + .endpoint() + .context("Unable to find endpoint")? + .parse::()?; + + Ok((endpoint, [cert].to_vec())) +} + +pub async fn main2(cluster_name: &str, region: &str) -> Result { + let sdk_config = aws_config::load_defaults(BehaviorVersion::latest()).await; + let credentials = sdk_config + .credentials_provider() + .ok_or_else(|| anyhow!("no credentials provider in sdk_config"))? + .provide_credentials() + .await + .context("failed to provide AWS credentials")?; + + let mut signing_settings = SigningSettings::default(); + signing_settings.expires_in = Some(Duration::from_secs(60)); + signing_settings.signature_location = SignatureLocation::QueryParams; + + let identity = Identity::from(credentials.clone()); + + let signing_params = match aws_sigv4::sign::v4::SigningParams::builder() + .identity(&identity) + .region(region) + .name("sts") + .time(SystemTime::now()) + .settings(signing_settings) + .build() + { + Ok(params) => params, + Err(e) => { + return Err(anyhow!("Unable to create signing params: {:?}", e)); + } + }; + + let url = + format!("https://sts.{region}.amazonaws.com/?Action=GetCallerIdentity&Version=2011-06-15"); + let headers = vec![("x-k8s-aws-id", cluster_name)]; + let signable_request = SignableRequest::new( + "GET", + url.clone(), + headers.into_iter(), + SignableBody::Bytes(&[]), + )?; + + let (signing_instructions, _signature) = aws_sigv4::http_request::sign( + signable_request, + &aws_sigv4::http_request::SigningParams::V4(signing_params), + )? + .into_parts(); + + let mut fake_req = http::Request::builder() + .uri(url) + .body(()) + .expect("empty body request should not fail"); + + signing_instructions.apply_to_request_http1x(&mut fake_req); + let uri = fake_req.uri().to_string(); + + Ok(format!("k8s-aws-v1.{}", &URL_SAFE_NO_PAD.encode(uri))) +}