diff --git a/Cargo.toml b/Cargo.toml index 7ffecc41a..c32e04620 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -50,12 +50,17 @@ run_script = { version = "0.10" } testcontainers-modules = { version = "0.1"} strum ={ version = "0.25", features = ["derive"] } # tardis -tardis = { version = "=0.1.0-rc.2" } +tardis = { version = "=0.1.0-rc.3" } # tardis = { path = "../tardis/tardis" } # tardis = { git = "https://github.com/ideal-world/tardis.git", rev = "9424e16" } #spacegate -spacegate-kernel = { git = "https://github.com/ideal-world/spacegate.git", rev = "ed34d33",features = [ +spacegate-kernel = { git = "https://github.com/ideal-world/spacegate.git", rev = "a0430a8",features = [ "ws", "cache", "k8s", ] } +#spacegate-kernel = { path = "../spacegate/kernel",features = [ +# "ws", +# "cache", +# "k8s", +#] } \ No newline at end of file diff --git a/basic/src/rbum/dto/rbum_safe_dto.rs b/basic/src/rbum/dto/rbum_safe_dto.rs index ed16eca53..58723a537 100644 --- a/basic/src/rbum/dto/rbum_safe_dto.rs +++ b/basic/src/rbum/dto/rbum_safe_dto.rs @@ -1,4 +1,4 @@ -use serde::{Serialize}; +use serde::Serialize; #[cfg(feature = "default")] use tardis::db::sea_orm; use tardis::{ diff --git a/basic/src/rbum/serv/rbum_kind_serv.rs b/basic/src/rbum/serv/rbum_kind_serv.rs index 88f133287..edf1c40cb 100644 --- a/basic/src/rbum/serv/rbum_kind_serv.rs +++ b/basic/src/rbum/serv/rbum_kind_serv.rs @@ -56,8 +56,7 @@ impl RbumCrudOperation 0 + if funs.db().count(Query::select().column(rbum_kind::Column::Id).from(rbum_kind::Entity).and_where(Expr::col(rbum_kind::Column::Code).eq(add_req.code.as_str()))).await? > 0 { return Err(funs.err().conflict(&Self::get_obj_name(), "add", &format!("code {} already exists", add_req.code), "409-rbum-*-code-exist")); } diff --git a/basic/src/test/init_rbum_test_container.rs b/basic/src/test/init_rbum_test_container.rs index d10eb4590..ee5a9c031 100644 --- a/basic/src/test/init_rbum_test_container.rs +++ b/basic/src/test/init_rbum_test_container.rs @@ -3,10 +3,10 @@ use std::env; use tardis::basic::result::TardisResult; use tardis::test::test_container::TardisTestContainer; use tardis::testcontainers::clients::Cli; -use tardis::testcontainers::GenericImage; -use testcontainers_modules::redis::Redis; use tardis::testcontainers::Container; +use tardis::testcontainers::GenericImage; use tardis::TardisFuns; +use testcontainers_modules::redis::Redis; pub struct LifeHold<'a> { pub reldb: Container<'a, GenericImage>, diff --git a/basic/src/test/test_http_client.rs b/basic/src/test/test_http_client.rs index 8b15a35bd..5dcec5a34 100644 --- a/basic/src/test/test_http_client.rs +++ b/basic/src/test/test_http_client.rs @@ -20,7 +20,11 @@ pub struct TestHttpClient { impl TestHttpClient { pub fn new(base_url: String) -> TestHttpClient { TestHttpClient { - client: TardisWebClient::init(&WebClientModuleConfig { connect_timeout_sec: 600, ..Default::default() }).unwrap(), + client: TardisWebClient::init(&WebClientModuleConfig { + connect_timeout_sec: 600, + ..Default::default() + }) + .unwrap(), context: Default::default(), base_url, } diff --git a/gateway/spacegate-lib/src/lib.rs b/gateway/spacegate-lib/src/lib.rs index 9543a5e90..6f6da66c5 100644 --- a/gateway/spacegate-lib/src/lib.rs +++ b/gateway/spacegate-lib/src/lib.rs @@ -1,6 +1,6 @@ #![warn(clippy::unwrap_used)] -use crate::plugin::{anti_replay, anti_xss, audit_log, auth, ip_time}; +use crate::plugin::{anti_replay, anti_xss, audit_log, auth, ip_time, rewrite_ns_b_ip}; mod plugin; @@ -12,4 +12,5 @@ pub fn register_lib_filter() { spacegate_kernel::register_filter_def(anti_replay::SgFilterAntiReplayDef); spacegate_kernel::register_filter_def(anti_xss::SgFilterAntiXSSDef); spacegate_kernel::register_filter_def(auth::SgFilterAuthDef); + spacegate_kernel::register_filter_def(rewrite_ns_b_ip::SgFilterRewriteNsDef); } diff --git a/gateway/spacegate-lib/src/plugin.rs b/gateway/spacegate-lib/src/plugin.rs index 393ce2a92..bfbd117c6 100644 --- a/gateway/spacegate-lib/src/plugin.rs +++ b/gateway/spacegate-lib/src/plugin.rs @@ -3,6 +3,7 @@ pub mod anti_xss; pub mod audit_log; pub mod auth; pub mod ip_time; +pub mod rewrite_ns_b_ip; mod plugin_constants { pub const BEFORE_ENCRYPT_BODY: &str = "beforeEncryptBody"; } diff --git a/gateway/spacegate-lib/src/plugin/anti_replay.rs b/gateway/spacegate-lib/src/plugin/anti_replay.rs index 3dd2c5a0e..059d22e10 100644 --- a/gateway/spacegate-lib/src/plugin/anti_replay.rs +++ b/gateway/spacegate-lib/src/plugin/anti_replay.rs @@ -3,10 +3,11 @@ use std::time::Duration; use async_trait::async_trait; use serde::{Deserialize, Serialize}; +use spacegate_kernel::def_filter; use spacegate_kernel::plugins::filters::SgPluginFilterInitDto; use spacegate_kernel::plugins::{ context::SgRoutePluginContext, - filters::{BoxSgPluginFilter, SgPluginFilter, SgPluginFilterAccept, SgPluginFilterDef}, + filters::{SgPluginFilter, SgPluginFilterAccept}, }; use tardis::cache::cache_client::TardisCacheClient; @@ -15,22 +16,9 @@ use tardis::{ basic::{error::TardisError, result::TardisResult}, serde_json::{self}, tokio::{self}, - TardisFuns, }; -pub const CODE: &str = "anti_replay"; -pub struct SgFilterAntiReplayDef; - -impl SgPluginFilterDef for SgFilterAntiReplayDef { - fn get_code(&self) -> &str { - CODE - } - - fn inst(&self, spec: serde_json::Value) -> TardisResult { - let filter = TardisFuns::json.json_to_obj::(spec)?; - Ok(filter.boxed()) - } -} +def_filter!("anti_replay", SgFilterAntiReplayDef, SgFilterAntiReplay); #[derive(Serialize, Deserialize)] #[serde(default)] @@ -131,6 +119,7 @@ mod tests { use std::env; + use super::*; use spacegate_kernel::{ http::Uri, hyper::{Body, HeaderMap, Method, Version}, @@ -140,7 +129,6 @@ mod tests { testcontainers::{self, clients::Cli, Container}, }; use testcontainers_modules::redis::Redis; - use super::*; #[tokio::test] async fn test_anti_replay() { diff --git a/gateway/spacegate-lib/src/plugin/anti_xss.rs b/gateway/spacegate-lib/src/plugin/anti_xss.rs index 474fc95f3..68618b71f 100644 --- a/gateway/spacegate-lib/src/plugin/anti_xss.rs +++ b/gateway/spacegate-lib/src/plugin/anti_xss.rs @@ -3,18 +3,17 @@ use std::fmt; use async_trait::async_trait; use serde::{Deserialize, Serialize}; -use spacegate_kernel::http; use spacegate_kernel::plugins::filters::SgPluginFilterInitDto; use spacegate_kernel::plugins::{ context::SgRoutePluginContext, - filters::{BoxSgPluginFilter, SgPluginFilter, SgPluginFilterAccept, SgPluginFilterDef}, + filters::{SgPluginFilter, SgPluginFilterAccept}, }; +use spacegate_kernel::{def_filter, http}; use tardis::{ async_trait, basic::result::TardisResult, serde_json::{self}, - TardisFuns, }; macro_rules! append_value { @@ -24,18 +23,8 @@ macro_rules! append_value { } }; } -pub const CODE: &str = "anti_xss"; -pub struct SgFilterAntiXSSDef; -impl SgPluginFilterDef for SgFilterAntiXSSDef { - fn get_code(&self) -> &str { - CODE - } - fn inst(&self, spec: serde_json::Value) -> TardisResult { - let filter = TardisFuns::json.json_to_obj::(spec)?; - Ok(filter.boxed()) - } -} +def_filter!("anti_xss", SgFilterAntiXSSDef, SgFilterAntiXSS); #[derive(Default, Serialize, Deserialize)] #[serde(default)] diff --git a/gateway/spacegate-lib/src/plugin/audit_log.rs b/gateway/spacegate-lib/src/plugin/audit_log.rs index 2f14e9d57..2d56213a5 100644 --- a/gateway/spacegate-lib/src/plugin/audit_log.rs +++ b/gateway/spacegate-lib/src/plugin/audit_log.rs @@ -11,10 +11,11 @@ use bios_sdk_invoke::invoke_initializer; use jsonpath_rust::JsonPathInst; use serde::{Deserialize, Serialize}; +use spacegate_kernel::def_filter; use spacegate_kernel::plugins::context::SGRoleInfo; use spacegate_kernel::plugins::{ context::SgRoutePluginContext, - filters::{BoxSgPluginFilter, SgPluginFilter, SgPluginFilterAccept, SgPluginFilterDef, SgPluginFilterInitDto}, + filters::{SgPluginFilter, SgPluginFilterAccept, SgPluginFilterInitDto}, }; use tardis::basic::dto::TardisContext; use tardis::serde_json::{json, Value}; @@ -31,18 +32,7 @@ use tardis::{ use super::plugin_constants; -pub const CODE: &str = "audit_log"; -pub struct SgFilterAuditLogDef; - -impl SgPluginFilterDef for SgFilterAuditLogDef { - fn get_code(&self) -> &str { - CODE - } - fn inst(&self, spec: serde_json::Value) -> TardisResult { - let filter = TardisFuns::json.json_to_obj::(spec)?; - Ok(filter.boxed()) - } -} +def_filter!("audit_log", SgFilterAuditLogDef, SgFilterAuditLog); #[derive(Serialize, Deserialize)] #[serde(default)] diff --git a/gateway/spacegate-lib/src/plugin/auth.rs b/gateway/spacegate-lib/src/plugin/auth.rs index 2ea95fb91..9fdc88066 100644 --- a/gateway/spacegate-lib/src/plugin/auth.rs +++ b/gateway/spacegate-lib/src/plugin/auth.rs @@ -11,12 +11,13 @@ use bios_auth::{ use serde::{Deserialize, Serialize}; use spacegate_kernel::{ + def_filter, http::{self, HeaderMap, HeaderName, HeaderValue}, hyper, hyper::{body::Bytes, Body, Method}, plugins::{ context::{SgRouteFilterRequestAction, SgRoutePluginContext}, - filters::{BoxSgPluginFilter, SgPluginFilter, SgPluginFilterAccept, SgPluginFilterDef}, + filters::{SgPluginFilter, SgPluginFilterAccept}, }, }; use spacegate_kernel::{ @@ -45,21 +46,11 @@ use tardis::{ use tardis::{basic::tracing::Directive, tracing, web::poem_openapi::types::Type}; use super::plugin_constants; + #[allow(clippy::type_complexity)] static INSTANCE: OnceLock)>>>> = OnceLock::new(); -pub const CODE: &str = "auth"; -pub struct SgFilterAuthDef; - -impl SgPluginFilterDef for SgFilterAuthDef { - fn get_code(&self) -> &str { - CODE - } - fn inst(&self, spec: serde_json::Value) -> TardisResult { - let filter = TardisFuns::json.json_to_obj::(spec)?; - Ok(filter.boxed()) - } -} +def_filter!("auth", SgFilterAuthDef, SgFilterAuth); #[derive(Serialize, Deserialize)] #[serde(default)] @@ -465,428 +456,4 @@ fn headermap_header_to_hashmap(old_headers: &HeaderMap) -> TardisResult>(), - )) - .unwrap(); - - let pub_key = data["data"]["pub_key"].as_str().unwrap(); - let server_sm2 = TardisCryptoSm2 {}; - let server_public_key = server_sm2.new_public_key_from_public_key(pub_key).unwrap(); - - let front_pri_key = TardisFuns::crypto.sm2.new_private_key().unwrap(); - let front_pub_key = TardisFuns::crypto.sm2.new_public_key(&front_pri_key).unwrap(); - - let test_body_value = r#"test_body_value!@#$%^&*():"中文测试"#; - //dont need to decrypt - let header = HeaderMap::new(); - let ctx = SgRoutePluginContext::new_http( - Method::POST, - Uri::from_static("http://sg.idealworld.group/test1"), - Version::HTTP_11, - header, - Body::from(test_body_value), - "127.0.0.1:8080".parse().unwrap(), - "".to_string(), - None, - ); - let (is_ok, mut before_filter_ctx) = filter_auth.req_filter("", ctx).await.unwrap(); - assert!(is_ok); - let req_body = before_filter_ctx.request.dump_body().await.unwrap(); - assert!(!req_body.is_empty()); - let req_body = req_body.to_vec(); - let req_body = String::from_utf8(req_body).unwrap(); - assert_eq!(req_body, test_body_value.to_string()); - - //=========request GET============ - let mut header = HeaderMap::new(); - let (_crypto_data, bios_crypto_value) = crypto_req("", server_public_key.serialize().unwrap().as_ref(), front_pub_key.serialize().unwrap().as_ref(), true); - header.insert("Bios-Crypto", bios_crypto_value.parse().unwrap()); - let ctx = SgRoutePluginContext::new_http( - Method::GET, - Uri::from_static("http://sg.idealworld.group/test1"), - Version::HTTP_11, - header, - Body::empty(), - "127.0.0.1:8080".parse().unwrap(), - "".to_string(), - None, - ); - let (is_ok, mut before_filter_ctx) = filter_auth.req_filter("", ctx).await.unwrap(); - assert!(is_ok); - let req_body = before_filter_ctx.request.dump_body().await.unwrap(); - assert!(req_body.is_empty()); - - //=========request POST============ - let mut header = HeaderMap::new(); - let (crypto_data, bios_crypto_value) = crypto_req( - test_body_value, - server_public_key.serialize().unwrap().as_ref(), - front_pub_key.serialize().unwrap().as_ref(), - true, - ); - header.insert("Bios-Crypto", bios_crypto_value.parse().unwrap()); - let ctx = SgRoutePluginContext::new_http( - Method::POST, - Uri::from_static("http://sg.idealworld.group/test1"), - Version::HTTP_11, - header, - Body::from(crypto_data), - "127.0.0.1:8080".parse().unwrap(), - "".to_string(), - None, - ); - let (is_ok, mut before_filter_ctx) = filter_auth.req_filter("", ctx).await.unwrap(); - assert!(is_ok); - let req_body = before_filter_ctx.request.dump_body().await.unwrap(); - assert!(!req_body.is_empty()); - let req_body = req_body.to_vec(); - let req_body = String::from_utf8(req_body).unwrap(); - assert_eq!(req_body, test_body_value.to_string()); - - //======response============ - let mock_resp = r#"mock_resp:test_body_value!@#$%^&*():"中文测试"#; - let mut header = HeaderMap::new(); - header.insert("Test_Header", "test_header".parse().unwrap()); - let ctx = before_filter_ctx.resp(StatusCode::OK, header, Body::from(mock_resp)); - - let (is_ok, mut before_filter_ctx) = filter_auth.resp_filter("", ctx).await.unwrap(); - assert!(is_ok); - let resp_body = before_filter_ctx.response.dump_body().await.unwrap(); - assert!(!resp_body.is_empty()); - let resp_body = resp_body.to_vec(); - let resp_body = String::from_utf8(resp_body).unwrap(); - let resp_body = crypto_resp( - &resp_body, - before_filter_ctx.response.get_headers().get("Bios-Crypto").unwrap().to_str().unwrap(), - &front_pri_key, - ); - println!("req_body:{req_body} mock_resp:{mock_resp}"); - assert_eq!(resp_body, mock_resp.to_string()); - - filter_auth.destroy().await.unwrap(); - } - - async fn test_auth_plugin_strict_security_mode_crypto() { - log::info!("======test_auth_plugin_strict_security_mode_crypto===="); - - let mut filter_auth = SgFilterAuth { - cache_url: env::var("TARDIS_FW.CACHE.URL").unwrap(), - ..Default::default() - }; - filter_auth.auth_config.strict_security_mode = true; - - filter_auth - .init(&SgPluginFilterInitDto { - gateway_name: "".to_string(), - gateway_parameters: SgParameters { - redis_url: None, - log_level: None, - lang: None, - ignore_tls_verification: None, - }, - http_route_rules: vec![], - attached_level: spacegate_kernel::plugins::filters::SgAttachedLevel::Gateway, - }) - .await - .unwrap(); - - let ctx = SgRoutePluginContext::new_http( - Method::GET, - Uri::from_str(&format!("http://sg.idealworld.group{}", filter_auth.fetch_server_config_path)).unwrap(), - Version::HTTP_11, - HeaderMap::new(), - Body::empty(), - "127.0.0.1:8080".parse().unwrap(), - "".to_string(), - None, - ); - let (_, mut before_filter_ctx) = filter_auth.req_filter("", ctx).await.unwrap(); - let mut server_config_resp = before_filter_ctx.build_response().await.unwrap(); - let data: Value = serde_json::from_str(&String::from_utf8_lossy( - &hyper::body::to_bytes(server_config_resp.body_mut()).await.unwrap().iter().cloned().collect::>(), - )) - .unwrap(); - - let pub_key = data["data"]["pub_key"].as_str().unwrap(); - let server_sm2 = TardisCryptoSm2 {}; - let server_public_key = server_sm2.new_public_key_from_public_key(pub_key).unwrap(); - - let front_pri_key = TardisFuns::crypto.sm2.new_private_key().unwrap(); - let front_pub_key = TardisFuns::crypto.sm2.new_public_key(&front_pri_key).unwrap(); - - //=========request GET by apis============ - let true_path = "get_path"; - let body = MixRequestBody { - method: "GET".to_string(), - uri: true_path.to_string(), - body: "".to_string(), - headers: Default::default(), - ts: 0.0, - }; - let mix_body = TardisFuns::json.obj_to_string(&body).unwrap(); - let mut header = HeaderMap::new(); - let (crypto_body, bios_crypto_value) = crypto_req( - &mix_body, - server_public_key.serialize().unwrap().as_ref(), - front_pub_key.serialize().unwrap().as_ref(), - true, - ); - header.insert("Bios-Crypto", bios_crypto_value.parse().unwrap()); - header.insert(hyper::header::CONTENT_LENGTH, crypto_body.as_bytes().len().to_string().parse().unwrap()); - let ctx = SgRoutePluginContext::new_http( - Method::POST, - Uri::from_str(&format!("http://sg.idealworld.group/{}", filter_auth.mix_replace_url)).unwrap(), - Version::HTTP_11, - header, - Body::from(crypto_body), - "127.0.0.1:8080".parse().unwrap(), - "".to_string(), - None, - ); - let (is_ok, before_filter_ctx) = filter_auth.req_filter("", ctx).await.unwrap(); - assert!(!is_ok); - assert_eq!(before_filter_ctx.get_action(), &SgRouteFilterRequestAction::Redirect); - assert_eq!(before_filter_ctx.request.get_uri().path(), &format!("/{}", true_path)); - assert_eq!(before_filter_ctx.request.get_method(), &Method::GET); - assert_eq!( - before_filter_ctx.request.get_headers().get(hyper::header::CONTENT_LENGTH), - Some(&HeaderValue::from_static("0")) - ); - let (is_ok, mut before_filter_ctx) = filter_auth.req_filter("", before_filter_ctx).await.unwrap(); - assert!(is_ok); - println!("before_filter_ctx=={:?}", before_filter_ctx); - let req_body = before_filter_ctx.request.dump_body().await.unwrap(); - assert!(req_body.is_empty()); - - filter_auth.destroy().await.unwrap(); - } - - fn decode_context(headers: &HeaderMap) -> TardisContext { - let config = TardisFuns::cs_config::(auth_constants::DOMAIN_CODE); - let ctx = headers.get(&config.head_key_context).unwrap(); - let ctx = TardisFuns::crypto.base64.decode_to_string(ctx.to_str().unwrap()).unwrap(); - TardisFuns::json.str_to_obj(&ctx).unwrap() - } - - fn crypto_req(body: &str, serv_pub_key: &str, front_pub_key: &str, need_crypto_resp: bool) -> (String, String) { - let pub_key = TardisFuns::crypto.sm2.new_public_key_from_public_key(serv_pub_key).unwrap(); - - let sm4_key = TardisFuns::crypto.key.rand_16_bytes(); - let sm4_key_hex = TardisFuns::crypto.hex.encode(&sm4_key); - let sm4_iv = TardisFuns::crypto.key.rand_16_bytes(); - let sm4_iv_hex = TardisFuns::crypto.hex.encode(&sm4_key); - - let data = TardisFuns::crypto.sm4.encrypt_cbc(body, &sm4_key, &sm4_iv).unwrap(); - let sign_data = TardisFuns::crypto.digest.sm3(&data).unwrap(); - - let sm4_encrypt = if need_crypto_resp { - pub_key.encrypt(&format!("{sign_data} {sm4_key_hex} {sm4_iv_hex} {front_pub_key}",)).unwrap() - } else { - pub_key.encrypt(&format!("{sign_data} {sm4_key_hex} {sm4_iv_hex}",)).unwrap() - }; - let base64_encrypt = TardisFuns::crypto.base64.encode(sm4_encrypt); - (data, base64_encrypt) - } - - fn crypto_resp(body: &str, crypto_header: &str, front_pri_key: &TardisCryptoSm2PrivateKey) -> String { - let decode_base64 = TardisFuns::crypto.base64.decode_to_string(crypto_header).unwrap(); - let decrypt_key = front_pri_key.decrypt(&decode_base64).unwrap(); - let splits: Vec<_> = decrypt_key.split(' ').collect(); - if splits.len() != 3 { - panic!("splits:{:?}", splits); - } - - let sign_data = splits[0]; - let sm4_key = splits[1]; - let sm4_iv = splits[2]; - let gen_sign_data = TardisFuns::crypto.digest.sm3(body).unwrap(); - assert_eq!(sign_data, gen_sign_data); - TardisFuns::crypto.sm4.decrypt_cbc(body, sm4_key, sm4_iv).unwrap() - } - - pub struct LifeHold<'a> { - pub redis: Container<'a, Redis>, - } - - async fn docker_init(docker: &Cli) -> TardisResult> { - let redis_container = TardisTestContainer::redis_custom(docker); - let port = redis_container.get_host_port_ipv4(6379); - let url = format!("redis://127.0.0.1:{port}/0",); - env::set_var("TARDIS_FW.CACHE.URL", url); - - Ok(LifeHold { redis: redis_container }) - } -} +mod tests; diff --git a/gateway/spacegate-lib/src/plugin/auth/tests.rs b/gateway/spacegate-lib/src/plugin/auth/tests.rs new file mode 100644 index 000000000..bea82ad1a --- /dev/null +++ b/gateway/spacegate-lib/src/plugin/auth/tests.rs @@ -0,0 +1,423 @@ +use std::env; + +use bios_auth::auth_constants; + +use super::*; +use spacegate_kernel::config::gateway_dto::SgParameters; +use spacegate_kernel::http::{Method, Uri, Version}; +use spacegate_kernel::hyper::{self, Body, StatusCode}; +use tardis::basic::dto::TardisContext; +use tardis::crypto::crypto_sm2_4::{TardisCryptoSm2, TardisCryptoSm2PrivateKey}; +use tardis::{ + test::test_container::TardisTestContainer, + testcontainers::{self, clients::Cli, Container}, + tokio, +}; +use testcontainers_modules::redis::Redis; + +#[tokio::test] +async fn test() { + env::set_var("RUST_LOG", "info,bios_spacegate=trace,bios_auth=trace,tardis=trace"); + tracing_subscriber::fmt::init(); + + let docker = testcontainers::clients::Cli::default(); + let _x = docker_init(&docker).await.unwrap(); + + test_auth_plugin_ctx().await; + test_auth_plugin_crypto().await; + test_auth_plugin_strict_security_mode_crypto().await; +} + +async fn test_auth_plugin_ctx() { + log::info!("========test_auth_plugin_ctx====="); + + let mut filter_auth = SgFilterAuth { + cache_url: env::var("TARDIS_FW.CACHE.URL").unwrap(), + ..Default::default() + }; + + filter_auth + .init(&SgPluginFilterInitDto { + gateway_name: "".to_string(), + gateway_parameters: SgParameters { + redis_url: None, + log_level: None, + lang: None, + ignore_tls_verification: None, + }, + http_route_rules: vec![], + attached_level: spacegate_kernel::plugins::filters::SgAttachedLevel::Gateway, + }) + .await + .unwrap(); + + let cache_client = TardisFuns::cache_by_module_or_default(auth_constants::DOMAIN_CODE); + + let mut header = HeaderMap::new(); + header.insert("Bios-Token", "aaa".parse().unwrap()); + let ctx = SgRoutePluginContext::new_http( + Method::POST, + Uri::from_static("http://sg.idealworld.group/test1"), + Version::HTTP_11, + header, + Body::from("test"), + "127.0.0.1:8080".parse().unwrap(), + "".to_string(), + None, + ); + let (is_ok, mut before_filter_ctx) = filter_auth.req_filter("", ctx).await.unwrap(); + assert!(!is_ok); + let req_body = before_filter_ctx.response.take_body_into_bytes().await.unwrap(); + let req_body = String::from_utf8_lossy(&req_body).to_string(); + assert!(!req_body.is_empty()); + assert_eq!(req_body, "{\"code\":\"401-gateway-cert-error\",\"message\":\"[Auth] Token [aaa] is not legal\"}"); + + cache_client.set(&format!("{}tokenxxx", filter_auth.auth_config.cache_key_token_info), "default,accountxxx").await.unwrap(); + cache_client + .hset( + &format!("{}accountxxx", filter_auth.auth_config.cache_key_account_info), + "", + "{\"own_paths\":\"\",\"owner\":\"account1\",\"roles\":[\"r001\"],\"groups\":[\"g001\"]}", + ) + .await + .unwrap(); + + let mut header = HeaderMap::new(); + header.insert("Bios-Token", "tokenxxx".parse().unwrap()); + let ctx = SgRoutePluginContext::new_http( + Method::POST, + Uri::from_static("http://sg.idealworld.group/test1"), + Version::HTTP_11, + header, + Body::from("test"), + "127.0.0.1:8080".parse().unwrap(), + "".to_string(), + None, + ); + let (is_ok, before_filter_ctx) = filter_auth.req_filter("", ctx).await.unwrap(); + assert!(is_ok); + let ctx = decode_context(before_filter_ctx.request.get_headers()); + + assert_eq!(ctx.own_paths, ""); + assert_eq!(ctx.owner, "account1"); + assert_eq!(ctx.roles, vec!["r001"]); + assert_eq!(ctx.groups, vec!["g001"]); + + cache_client.set(&format!("{}tokenxxx", filter_auth.auth_config.cache_key_token_info), "default,accountxxx").await.unwrap(); + cache_client + .hset( + &format!("{}accountxxx", filter_auth.auth_config.cache_key_account_info), + "", + "{\"own_paths\":\"tenant1\",\"owner\":\"account1\",\"roles\":[\"r001\"],\"groups\":[\"g001\"]}", + ) + .await + .unwrap(); + let mut header = HeaderMap::new(); + header.insert("Bios-Token", "tokenxxx".parse().unwrap()); + let ctx = SgRoutePluginContext::new_http( + Method::POST, + Uri::from_static("http://sg.idealworld.group/test1"), + Version::HTTP_11, + header, + Body::from("test"), + "127.0.0.1:8080".parse().unwrap(), + "".to_string(), + None, + ); + let (is_ok, before_filter_ctx) = filter_auth.req_filter("", ctx).await.unwrap(); + assert!(is_ok); + let ctx = decode_context(before_filter_ctx.request.get_headers()); + + assert_eq!(ctx.own_paths, "tenant1"); + assert_eq!(ctx.owner, "account1"); + assert_eq!(ctx.roles, vec!["r001"]); + assert_eq!(ctx.groups, vec!["g001"]); +} + +async fn test_auth_plugin_crypto() { + log::info!("========test_auth_plugin_crypto====="); + + let mut filter_auth = SgFilterAuth { + cache_url: env::var("TARDIS_FW.CACHE.URL").unwrap(), + ..Default::default() + }; + + filter_auth + .init(&SgPluginFilterInitDto { + gateway_name: "".to_string(), + gateway_parameters: SgParameters { + redis_url: None, + log_level: None, + lang: None, + ignore_tls_verification: None, + }, + http_route_rules: vec![], + attached_level: spacegate_kernel::plugins::filters::SgAttachedLevel::Gateway, + }) + .await + .unwrap(); + + let ctx = SgRoutePluginContext::new_http( + Method::GET, + Uri::from_str(&format!("http://sg.idealworld.group{}", filter_auth.fetch_server_config_path)).unwrap(), + Version::HTTP_11, + HeaderMap::new(), + Body::from(""), + "127.0.0.1:8080".parse().unwrap(), + "".to_string(), + None, + ); + let (_, mut before_filter_ctx) = filter_auth.req_filter("", ctx).await.unwrap(); + let mut server_config_resp = before_filter_ctx.build_response().await.unwrap(); + let data: Value = serde_json::from_str(&String::from_utf8_lossy( + &hyper::body::to_bytes(server_config_resp.body_mut()).await.unwrap().iter().cloned().collect::>(), + )) + .unwrap(); + + let pub_key = data["data"]["pub_key"].as_str().unwrap(); + let server_sm2 = TardisCryptoSm2 {}; + let server_public_key = server_sm2.new_public_key_from_public_key(pub_key).unwrap(); + + let front_pri_key = TardisFuns::crypto.sm2.new_private_key().unwrap(); + let front_pub_key = TardisFuns::crypto.sm2.new_public_key(&front_pri_key).unwrap(); + + let test_body_value = r#"test_body_value!@#$%^&*():"中文测试"#; + //dont need to decrypt + let header = HeaderMap::new(); + let ctx = SgRoutePluginContext::new_http( + Method::POST, + Uri::from_static("http://sg.idealworld.group/test1"), + Version::HTTP_11, + header, + Body::from(test_body_value), + "127.0.0.1:8080".parse().unwrap(), + "".to_string(), + None, + ); + let (is_ok, mut before_filter_ctx) = filter_auth.req_filter("", ctx).await.unwrap(); + assert!(is_ok); + let req_body = before_filter_ctx.request.dump_body().await.unwrap(); + assert!(!req_body.is_empty()); + let req_body = req_body.to_vec(); + let req_body = String::from_utf8(req_body).unwrap(); + assert_eq!(req_body, test_body_value.to_string()); + + //=========request GET============ + let mut header = HeaderMap::new(); + let (_crypto_data, bios_crypto_value) = crypto_req("", server_public_key.serialize().unwrap().as_ref(), front_pub_key.serialize().unwrap().as_ref(), true); + header.insert("Bios-Crypto", bios_crypto_value.parse().unwrap()); + let ctx = SgRoutePluginContext::new_http( + Method::GET, + Uri::from_static("http://sg.idealworld.group/test1"), + Version::HTTP_11, + header, + Body::empty(), + "127.0.0.1:8080".parse().unwrap(), + "".to_string(), + None, + ); + let (is_ok, mut before_filter_ctx) = filter_auth.req_filter("", ctx).await.unwrap(); + assert!(is_ok); + let req_body = before_filter_ctx.request.dump_body().await.unwrap(); + assert!(req_body.is_empty()); + + //=========request POST============ + let mut header = HeaderMap::new(); + let (crypto_data, bios_crypto_value) = crypto_req( + test_body_value, + server_public_key.serialize().unwrap().as_ref(), + front_pub_key.serialize().unwrap().as_ref(), + true, + ); + header.insert("Bios-Crypto", bios_crypto_value.parse().unwrap()); + let ctx = SgRoutePluginContext::new_http( + Method::POST, + Uri::from_static("http://sg.idealworld.group/test1"), + Version::HTTP_11, + header, + Body::from(crypto_data), + "127.0.0.1:8080".parse().unwrap(), + "".to_string(), + None, + ); + let (is_ok, mut before_filter_ctx) = filter_auth.req_filter("", ctx).await.unwrap(); + assert!(is_ok); + let req_body = before_filter_ctx.request.dump_body().await.unwrap(); + assert!(!req_body.is_empty()); + let req_body = req_body.to_vec(); + let req_body = String::from_utf8(req_body).unwrap(); + assert_eq!(req_body, test_body_value.to_string()); + + //======response============ + let mock_resp = r#"mock_resp:test_body_value!@#$%^&*():"中文测试"#; + let mut header = HeaderMap::new(); + header.insert("Test_Header", "test_header".parse().unwrap()); + let ctx = before_filter_ctx.resp(StatusCode::OK, header, Body::from(mock_resp)); + + let (is_ok, mut before_filter_ctx) = filter_auth.resp_filter("", ctx).await.unwrap(); + assert!(is_ok); + let resp_body = before_filter_ctx.response.dump_body().await.unwrap(); + assert!(!resp_body.is_empty()); + let resp_body = resp_body.to_vec(); + let resp_body = String::from_utf8(resp_body).unwrap(); + let resp_body = crypto_resp( + &resp_body, + before_filter_ctx.response.get_headers().get("Bios-Crypto").unwrap().to_str().unwrap(), + &front_pri_key, + ); + println!("req_body:{req_body} mock_resp:{mock_resp}"); + assert_eq!(resp_body, mock_resp.to_string()); + + filter_auth.destroy().await.unwrap(); +} + +async fn test_auth_plugin_strict_security_mode_crypto() { + log::info!("======test_auth_plugin_strict_security_mode_crypto===="); + + let mut filter_auth = SgFilterAuth { + cache_url: env::var("TARDIS_FW.CACHE.URL").unwrap(), + ..Default::default() + }; + filter_auth.auth_config.strict_security_mode = true; + + filter_auth + .init(&SgPluginFilterInitDto { + gateway_name: "".to_string(), + gateway_parameters: SgParameters { + redis_url: None, + log_level: None, + lang: None, + ignore_tls_verification: None, + }, + http_route_rules: vec![], + attached_level: spacegate_kernel::plugins::filters::SgAttachedLevel::Gateway, + }) + .await + .unwrap(); + + let ctx = SgRoutePluginContext::new_http( + Method::GET, + Uri::from_str(&format!("http://sg.idealworld.group{}", filter_auth.fetch_server_config_path)).unwrap(), + Version::HTTP_11, + HeaderMap::new(), + Body::empty(), + "127.0.0.1:8080".parse().unwrap(), + "".to_string(), + None, + ); + let (_, mut before_filter_ctx) = filter_auth.req_filter("", ctx).await.unwrap(); + let mut server_config_resp = before_filter_ctx.build_response().await.unwrap(); + let data: Value = serde_json::from_str(&String::from_utf8_lossy( + &hyper::body::to_bytes(server_config_resp.body_mut()).await.unwrap().iter().cloned().collect::>(), + )) + .unwrap(); + + let pub_key = data["data"]["pub_key"].as_str().unwrap(); + let server_sm2 = TardisCryptoSm2 {}; + let server_public_key = server_sm2.new_public_key_from_public_key(pub_key).unwrap(); + + let front_pri_key = TardisFuns::crypto.sm2.new_private_key().unwrap(); + let front_pub_key = TardisFuns::crypto.sm2.new_public_key(&front_pri_key).unwrap(); + + //=========request GET by apis============ + let true_path = "get_path"; + let body = MixRequestBody { + method: "GET".to_string(), + uri: true_path.to_string(), + body: "".to_string(), + headers: Default::default(), + ts: 0.0, + }; + let mix_body = TardisFuns::json.obj_to_string(&body).unwrap(); + let mut header = HeaderMap::new(); + let (crypto_body, bios_crypto_value) = crypto_req( + &mix_body, + server_public_key.serialize().unwrap().as_ref(), + front_pub_key.serialize().unwrap().as_ref(), + true, + ); + header.insert("Bios-Crypto", bios_crypto_value.parse().unwrap()); + header.insert(hyper::header::CONTENT_LENGTH, crypto_body.as_bytes().len().to_string().parse().unwrap()); + let ctx = SgRoutePluginContext::new_http( + Method::POST, + Uri::from_str(&format!("http://sg.idealworld.group/{}", filter_auth.mix_replace_url)).unwrap(), + Version::HTTP_11, + header, + Body::from(crypto_body), + "127.0.0.1:8080".parse().unwrap(), + "".to_string(), + None, + ); + let (is_ok, before_filter_ctx) = filter_auth.req_filter("", ctx).await.unwrap(); + assert!(!is_ok); + assert_eq!(before_filter_ctx.get_action(), &SgRouteFilterRequestAction::Redirect); + assert_eq!(before_filter_ctx.request.get_uri().path(), &format!("/{}", true_path)); + assert_eq!(before_filter_ctx.request.get_method(), &Method::GET); + assert_eq!( + before_filter_ctx.request.get_headers().get(hyper::header::CONTENT_LENGTH), + Some(&HeaderValue::from_static("0")) + ); + let (is_ok, mut before_filter_ctx) = filter_auth.req_filter("", before_filter_ctx).await.unwrap(); + assert!(is_ok); + println!("before_filter_ctx=={:?}", before_filter_ctx); + let req_body = before_filter_ctx.request.dump_body().await.unwrap(); + assert!(req_body.is_empty()); + + filter_auth.destroy().await.unwrap(); +} + +fn decode_context(headers: &HeaderMap) -> TardisContext { + let config = TardisFuns::cs_config::(auth_constants::DOMAIN_CODE); + let ctx = headers.get(&config.head_key_context).unwrap(); + let ctx = TardisFuns::crypto.base64.decode_to_string(ctx.to_str().unwrap()).unwrap(); + TardisFuns::json.str_to_obj(&ctx).unwrap() +} + +fn crypto_req(body: &str, serv_pub_key: &str, front_pub_key: &str, need_crypto_resp: bool) -> (String, String) { + let pub_key = TardisFuns::crypto.sm2.new_public_key_from_public_key(serv_pub_key).unwrap(); + + let sm4_key = TardisFuns::crypto.key.rand_16_bytes(); + let sm4_key_hex = TardisFuns::crypto.hex.encode(sm4_key); + let sm4_iv = TardisFuns::crypto.key.rand_16_bytes(); + let sm4_iv_hex = TardisFuns::crypto.hex.encode(sm4_key); + + let data = TardisFuns::crypto.sm4.encrypt_cbc(body, sm4_key, sm4_iv).unwrap(); + let sign_data = TardisFuns::crypto.digest.sm3(&data).unwrap(); + + let sm4_encrypt = if need_crypto_resp { + pub_key.encrypt(&format!("{sign_data} {sm4_key_hex} {sm4_iv_hex} {front_pub_key}",)).unwrap() + } else { + pub_key.encrypt(&format!("{sign_data} {sm4_key_hex} {sm4_iv_hex}",)).unwrap() + }; + let base64_encrypt = TardisFuns::crypto.base64.encode(sm4_encrypt); + (data, base64_encrypt) +} + +fn crypto_resp(body: &str, crypto_header: &str, front_pri_key: &TardisCryptoSm2PrivateKey) -> String { + let decode_base64 = TardisFuns::crypto.base64.decode_to_string(crypto_header).unwrap(); + let decrypt_key = front_pri_key.decrypt(&decode_base64).unwrap(); + let splits: Vec<_> = decrypt_key.split(' ').collect(); + if splits.len() != 3 { + panic!("splits:{:?}", splits); + } + + let sign_data = splits[0]; + let sm4_key = splits[1]; + let sm4_iv = splits[2]; + let gen_sign_data = TardisFuns::crypto.digest.sm3(body).unwrap(); + assert_eq!(sign_data, gen_sign_data); + TardisFuns::crypto.sm4.decrypt_cbc(body, sm4_key, sm4_iv).unwrap() +} + +pub struct LifeHold<'a> { + pub redis: Container<'a, Redis>, +} + +async fn docker_init(docker: &Cli) -> TardisResult> { + let redis_container = TardisTestContainer::redis_custom(docker); + let port = redis_container.get_host_port_ipv4(6379); + let url = format!("redis://127.0.0.1:{port}/0",); + env::set_var("TARDIS_FW.CACHE.URL", url); + + Ok(LifeHold { redis: redis_container }) +} diff --git a/gateway/spacegate-lib/src/plugin/rewrite_ns_b_ip.rs b/gateway/spacegate-lib/src/plugin/rewrite_ns_b_ip.rs new file mode 100644 index 000000000..3d014457e --- /dev/null +++ b/gateway/spacegate-lib/src/plugin/rewrite_ns_b_ip.rs @@ -0,0 +1,130 @@ +use ipnet::IpNet; +use serde::{Deserialize, Serialize}; +use spacegate_kernel::config::gateway_dto::SgProtocol; +use spacegate_kernel::def_filter; +use spacegate_kernel::plugins::context::{SgRouteFilterRequestAction, SgRoutePluginContext}; +use spacegate_kernel::plugins::filters::{SgPluginFilter, SgPluginFilterInitDto}; +use std::net::IpAddr; +use tardis::async_trait::async_trait; +use tardis::basic::error::TardisError; +use tardis::basic::result::TardisResult; +use tardis::{log, serde_json}; + +def_filter!("rewrite_ns", SgFilterRewriteNsDef, SgFilterRewriteNs); + +/// Kube available only! +#[derive(Serialize, Deserialize)] +#[serde(default)] +pub struct SgFilterRewriteNs { + pub ip_list: Vec, + pub target_ns: String, + #[serde(skip)] + pub ip_net: Vec, +} + +impl Default for SgFilterRewriteNs { + fn default() -> Self { + SgFilterRewriteNs { + ip_list: vec![], + target_ns: "default".to_string(), + ip_net: vec![], + } + } +} + +#[async_trait] +impl SgPluginFilter for SgFilterRewriteNs { + async fn init(&mut self, _: &SgPluginFilterInitDto) -> TardisResult<()> { + let ip_net = self.ip_list.iter().filter_map(|ip| ip.parse::().or(ip.parse::().map(IpNet::from)).ok()).collect(); + self.ip_net = ip_net; + Ok(()) + } + + async fn destroy(&self) -> TardisResult<()> { + Ok(()) + } + + async fn req_filter(&self, id: &str, mut ctx: SgRoutePluginContext) -> TardisResult<(bool, SgRoutePluginContext)> { + if let Some(backend) = ctx.get_chose_backend() { + if backend.namespace.is_some() { + let ip = ctx.get_remote_addr().ip(); + if self.ip_net.iter().any(|ipnet| ipnet.contains(&IpNet::from(ip))) { + ctx.set_action(SgRouteFilterRequestAction::Redirect); + let scheme = backend.protocol.as_ref().unwrap_or(&SgProtocol::Http); + let host = format!("{}{}", backend.name_or_host, format_args!(".{}", self.target_ns)); + let port = + if (backend.port == 0 || backend.port == 80) && scheme == &SgProtocol::Http || (backend.port == 0 || backend.port == 443) && scheme == &SgProtocol::Https { + "".to_string() + } else { + format!(":{}", backend.port) + }; + let url = format!("{}://{}{}{}", scheme, host, port, ctx.request.get_uri().path_and_query().map(|p| p.as_str()).unwrap_or("")); + ctx.request.set_uri(url.parse().map_err(|e| TardisError::wrap(&format!("[Plugin.Auth.Rewrite_Ns({id})] parse url:{e}"), ""))?); + log::debug!("[Plugin.Auth.Rewrite_Ns({id})] change namespace to {}", self.target_ns); + } + } + } + return Ok((true, ctx)); + } + + async fn resp_filter(&self, _: &str, ctx: SgRoutePluginContext) -> TardisResult<(bool, SgRoutePluginContext)> { + return Ok((true, ctx)); + } +} + +#[cfg(test)] +mod test { + use crate::plugin::rewrite_ns_b_ip::SgFilterRewriteNs; + use spacegate_kernel::config::gateway_dto::SgParameters; + use spacegate_kernel::http::{HeaderMap, Method, Uri, Version}; + use spacegate_kernel::hyper::Body; + use spacegate_kernel::instance::SgBackendInst; + use spacegate_kernel::plugins::context::SgRoutePluginContext; + use spacegate_kernel::plugins::filters::{SgPluginFilter, SgPluginFilterInitDto}; + use tardis::tokio; + + #[tokio::test] + async fn test() { + let mut filter_rens = SgFilterRewriteNs { + ip_list: vec!["198.168.1.0/24".to_string()], + target_ns: "target".to_string(), + ..Default::default() + }; + + filter_rens + .init(&SgPluginFilterInitDto { + gateway_name: "".to_string(), + gateway_parameters: SgParameters { + redis_url: None, + log_level: None, + lang: None, + ignore_tls_verification: None, + }, + http_route_rules: vec![], + attached_level: spacegate_kernel::plugins::filters::SgAttachedLevel::Gateway, + }) + .await + .unwrap(); + + let mut ctx = SgRoutePluginContext::new_http( + Method::POST, + Uri::from_static("http://sg.idealworld.group/test1"), + Version::HTTP_11, + HeaderMap::new(), + Body::from("test"), + "198.168.1.1:8080".parse().unwrap(), + "".to_string(), + None, + ); + let back_inst = SgBackendInst { + name_or_host: "test".to_string(), + namespace: Some("Anamspace".to_string()), + port: 80, + ..Default::default() + }; + ctx.set_chose_backend_inst(&back_inst); + + let (_, ctx) = filter_rens.req_filter("", ctx).await.unwrap(); + assert_eq!(ctx.request.uri.get().host().unwrap(), format!("test.target")) + } +} diff --git a/gateway/test/src/init_apisix.rs b/gateway/test/src/init_apisix.rs index eef9d4d58..a2d933378 100644 --- a/gateway/test/src/init_apisix.rs +++ b/gateway/test/src/init_apisix.rs @@ -2,7 +2,7 @@ use tardis::basic::result::TardisResult; use tardis::serde_json::json; use tardis::testcontainers::clients::Cli; use tardis::testcontainers::core::WaitFor; -use tardis::testcontainers::{GenericImage, Container, RunnableImage}; +use tardis::testcontainers::{Container, GenericImage, RunnableImage}; use tardis::TardisFuns; pub(crate) async fn init(docker: &Cli) -> TardisResult<(String, Container)> { diff --git a/middleware/schedule/src/serv/schedule_job_serv.rs b/middleware/schedule/src/serv/schedule_job_serv.rs index 64bdc68e8..927687641 100644 --- a/middleware/schedule/src/serv/schedule_job_serv.rs +++ b/middleware/schedule/src/serv/schedule_job_serv.rs @@ -42,10 +42,7 @@ pub(crate) async fn add_or_modify(add_or_modify: ScheduleJobAddOrModifyReq, funs owner: funs.conf::().spi_app_id.clone(), ..ctx.clone() }; - let headers = vec![( - "Tardis-Context".to_string(), - TardisFuns::crypto.base64.encode(TardisFuns::json.obj_to_string(&spi_ctx)?), - )]; + let headers = vec![("Tardis-Context".to_string(), TardisFuns::crypto.base64.encode(TardisFuns::json.obj_to_string(&spi_ctx)?))]; // if exist delete it first if service().code_uuid.write().await.get(code).is_some() { delete(code, funs, ctx).await?; @@ -89,10 +86,7 @@ pub(crate) async fn delete(code: &str, funs: &TardisFunsInst, ctx: &TardisContex owner: funs.conf::().spi_app_id.clone(), ..ctx.clone() }; - let headers = vec![( - "Tardis-Context".to_string(), - TardisFuns::crypto.base64.encode(TardisFuns::json.obj_to_string(&spi_ctx)?), - )]; + let headers = vec![("Tardis-Context".to_string(), TardisFuns::crypto.base64.encode(TardisFuns::json.obj_to_string(&spi_ctx)?))]; // 1. log this operation TardisFuns::web_client() .post_obj_to_str( @@ -133,10 +127,7 @@ pub(crate) async fn find_job(code: Option, page_number: u32, page_size: owner: funs.conf::().spi_app_id.clone(), ..ctx.clone() }; - let headers = [( - "Tardis-Context".to_string(), - TardisFuns::crypto.base64.encode(TardisFuns::json.obj_to_string(&spi_ctx)?), - )]; + let headers = [("Tardis-Context".to_string(), TardisFuns::crypto.base64.encode(TardisFuns::json.obj_to_string(&spi_ctx)?))]; let resp = funs .web_client() .get::>>( @@ -196,10 +187,7 @@ pub(crate) async fn find_one_job(code: &str, funs: &TardisFunsInst, ctx: &Tardis owner: funs.conf::().spi_app_id.clone(), ..ctx.clone() }; - let headers = [( - "Tardis-Context".to_string(), - TardisFuns::crypto.base64.encode(TardisFuns::json.obj_to_string(&spi_ctx)?), - )]; + let headers = [("Tardis-Context".to_string(), TardisFuns::crypto.base64.encode(TardisFuns::json.obj_to_string(&spi_ctx)?))]; let resp = funs.web_client().get::>>(&format!("{}/ci/item?key={}", kv_url, format_args!("{}{}", KV_KEY_CODE, code)), headers).await?; let Some(body) = resp.body else { @@ -225,10 +213,7 @@ pub(crate) async fn find_task( owner: funs.conf::().spi_app_id.clone(), ..ctx.clone() }; - let headers = [( - "Tardis-Context".to_string(), - TardisFuns::crypto.base64.encode(&TardisFuns::json.obj_to_string(&spi_ctx)?), - )]; + let headers = [("Tardis-Context".to_string(), TardisFuns::crypto.base64.encode(&TardisFuns::json.obj_to_string(&spi_ctx)?))]; let mut url = format!( "{}/ci/item?tag={}&key={}&page_number={}&page_size={}", log_url, @@ -426,10 +411,7 @@ impl OwnedScheduleTaskServ { groups: vec![], ..Default::default() }; - let headers = [( - "Tardis-Context".to_string(), - TardisFuns::crypto.base64.encode(TardisFuns::json.obj_to_string(&ctx)?), - )]; + let headers = [("Tardis-Context".to_string(), TardisFuns::crypto.base64.encode(TardisFuns::json.obj_to_string(&ctx)?))]; let enable_time = job_config.enable_time; let disable_time = job_config.disable_time; diff --git a/services/spacegate/src/main.rs b/services/spacegate/src/main.rs index 64f4e67f2..becd8cd31 100644 --- a/services/spacegate/src/main.rs +++ b/services/spacegate/src/main.rs @@ -1,7 +1,7 @@ use spacegate_lib::register_lib_filter; use tardis::basic::result::TardisResult; -use tardis::{tokio, TardisFuns}; use tardis::config::config_dto::{FrameworkConfig, LogConfig, TardisConfig}; +use tardis::{tokio, TardisFuns}; #[tokio::main] async fn main() -> TardisResult<()> { diff --git a/spi/spi-cache/src/serv/redis/cache_redis_initializer.rs b/spi/spi-cache/src/serv/redis/cache_redis_initializer.rs index e100b018a..852c5f275 100644 --- a/spi/spi-cache/src/serv/redis/cache_redis_initializer.rs +++ b/spi/spi-cache/src/serv/redis/cache_redis_initializer.rs @@ -3,12 +3,13 @@ use std::collections::HashMap; use bios_basic::spi::{dto::spi_bs_dto::SpiBsCertResp, spi_funs::SpiBsInst, spi_initializer}; use tardis::{ basic::{dto::TardisContext, result::TardisResult}, - cache::cache_client::TardisCacheClient, config::config_dto::CacheModuleConfig, + cache::cache_client::TardisCacheClient, + config::config_dto::CacheModuleConfig, }; pub async fn init(bs_cert: &SpiBsCertResp, ctx: &TardisContext, _: bool) -> TardisResult { let config = CacheModuleConfig { - url: bs_cert.conn_uri.parse().expect("invalid url") + url: bs_cert.conn_uri.parse().expect("invalid url"), }; let client = TardisCacheClient::init(&config).await?; let mut ext = HashMap::new(); diff --git a/spi/spi-conf/tests/spi_conf_nacos_compatible_test.rs b/spi/spi-conf/tests/spi_conf_nacos_compatible_test.rs index 0138acece..a25f017ae 100644 --- a/spi/spi-conf/tests/spi_conf_nacos_compatible_test.rs +++ b/spi/spi-conf/tests/spi_conf_nacos_compatible_test.rs @@ -83,7 +83,7 @@ async fn test_tardis_compatibility(_test_client: &TestHttpClient) -> TardisResul let mut headers = reqwest::header::HeaderMap::new(); let web_server_config = config.web_server(); let context_header_name = web_server_config.context_conf.context_header_name.clone(); - headers.append(HeaderName::from_bytes(context_header_name.as_bytes()).expect("should be ok") , ctx_base64.parse().unwrap()); + headers.append(HeaderName::from_bytes(context_header_name.as_bytes()).expect("should be ok"), ctx_base64.parse().unwrap()); let client = reqwest::ClientBuilder::default().danger_accept_invalid_certs(true).default_headers(headers).build().unwrap(); let mut nacos_client = NacosClient::new_with_client(format!("{SCHEMA}://localhost:8080/spi-conf-nacos/nacos"), client); // register diff --git a/spi/spi-search/src/api/ci/search_ci_item_api.rs b/spi/spi-search/src/api/ci/search_ci_item_api.rs index 91e6bad62..3ed9719f7 100644 --- a/spi/spi-search/src/api/ci/search_ci_item_api.rs +++ b/spi/spi-search/src/api/ci/search_ci_item_api.rs @@ -50,7 +50,6 @@ impl SearchCiItemApi { TardisResp::ok(Void {}) } - /// Search Items #[oai(path = "/search", method = "put")] async fn search(&self, mut search_req: Json, ctx: TardisContextExtractor) -> TardisApiResult> { diff --git a/spi/spi-search/src/serv/es/search_es_initializer.rs b/spi/spi-search/src/serv/es/search_es_initializer.rs index 7af54b915..c994cde0a 100644 --- a/spi/spi-search/src/serv/es/search_es_initializer.rs +++ b/spi/spi-search/src/serv/es/search_es_initializer.rs @@ -3,11 +3,15 @@ use std::collections::HashMap; use bios_basic::spi::{dto::spi_bs_dto::SpiBsCertResp, spi_funs::SpiBsInst, spi_initializer}; use tardis::{ basic::{dto::TardisContext, result::TardisResult}, - search::search_client::TardisSearchClient, config::config_dto::SearchModuleConfig, + config::config_dto::SearchModuleConfig, + search::search_client::TardisSearchClient, }; pub async fn init(bs_cert: &SpiBsCertResp, ctx: &TardisContext, _mgr: bool) -> TardisResult { - let config = SearchModuleConfig { url: bs_cert.conn_uri.parse().expect("invalid url"), timeout_sec: 60 }; + let config = SearchModuleConfig { + url: bs_cert.conn_uri.parse().expect("invalid url"), + timeout_sec: 60, + }; let client = TardisSearchClient::init(&config)?; let mut ext = HashMap::new(); if !bs_cert.private { diff --git a/spi/spi-search/src/serv/es/search_es_item_serv.rs b/spi/spi-search/src/serv/es/search_es_item_serv.rs index 29b011ce9..3d644502b 100644 --- a/spi/spi-search/src/serv/es/search_es_item_serv.rs +++ b/spi/spi-search/src/serv/es/search_es_item_serv.rs @@ -4,8 +4,8 @@ use tardis::{ basic::{dto::TardisContext, result::TardisResult}, search::search_client::TardisSearchClient, serde_json::{self, json, Value}, - TardisFuns, - TardisFunsInst, web::web_resp::TardisPage, + web::web_resp::TardisPage, + TardisFuns, TardisFunsInst, }; use bios_basic::{ @@ -265,7 +265,7 @@ pub async fn delete_by_ownership(tag: &str, onw_paths: &str, funs: &TardisFunsIn cond_by_or: None, }, query: SearchItemQueryReq { - own_paths:Some(vec![onw_paths.to_string().into()]), + own_paths: Some(vec![onw_paths.to_string().into()]), ..Default::default() }, sort: None, diff --git a/spi/spi-search/src/serv/pg/search_pg_item_serv.rs b/spi/spi-search/src/serv/pg/search_pg_item_serv.rs index 122c66ee9..42c2af348 100644 --- a/spi/spi-search/src/serv/pg/search_pg_item_serv.rs +++ b/spi/spi-search/src/serv/pg/search_pg_item_serv.rs @@ -9,8 +9,8 @@ use tardis::{ sea_orm::{FromQueryResult, Value}, }, serde_json::{self, json, Map}, - TardisFuns, - TardisFunsInst, web::web_resp::TardisPage, + web::web_resp::TardisPage, + TardisFuns, TardisFunsInst, }; use bios_basic::{basic_enumeration::BasicQueryOpKind, dto::BasicQueryCondInfo, helper::db_helper, spi::spi_funs::SpiBsInst}; @@ -1154,7 +1154,7 @@ pub async fn query_metrics(query_req: &SearchQueryMetricsReq, funs: &TardisFunsI // (column name with fun, alias name, show_name, is dimension) let mut sql_part_outer_select_infos = vec![]; for (column_name_with_fun, alias_name, show_name) in sql_part_group_infos { - sql_part_outer_select_infos.push((format!("COALESCE({},'\"empty\"')",column_name_with_fun), alias_name, show_name, true)); + sql_part_outer_select_infos.push((format!("COALESCE({},'\"empty\"')", column_name_with_fun), alias_name, show_name, true)); } for select in &query_req.select { let select_column = if select.in_ext.unwrap_or(true) { diff --git a/spi/spi-search/tests/init_search_container.rs b/spi/spi-search/tests/init_search_container.rs index 4afab0cfc..d505c0ef1 100644 --- a/spi/spi-search/tests/init_search_container.rs +++ b/spi/spi-search/tests/init_search_container.rs @@ -4,9 +4,9 @@ use tardis::basic::result::TardisResult; use tardis::test::test_container::TardisTestContainer; use tardis::testcontainers::clients::Cli; use tardis::testcontainers::core::WaitFor; -use tardis::testcontainers::{GenericImage, Container}; -use testcontainers_modules::redis::Redis; +use tardis::testcontainers::{Container, GenericImage}; use tardis::TardisFuns; +use testcontainers_modules::redis::Redis; pub struct LifeHold<'a> { pub search: Container<'a, GenericImage>, diff --git a/spi/spi-stats/src/serv/pg/stats_pg_record_serv.rs b/spi/spi-stats/src/serv/pg/stats_pg_record_serv.rs index 2c1fc3998..b5e7d1676 100644 --- a/spi/spi-stats/src/serv/pg/stats_pg_record_serv.rs +++ b/spi/spi-stats/src/serv/pg/stats_pg_record_serv.rs @@ -427,7 +427,6 @@ pub(crate) async fn fact_records_delete(fact_conf_key: &str, fact_record_delete_ Ok(()) } - pub(crate) async fn fact_records_delete_by_ownership(fact_conf_key: &str, own_paths: &str, funs: &TardisFunsInst, ctx: &TardisContext, inst: &SpiBsInst) -> TardisResult<()> { let bs_inst = inst.inst::(); let (mut conn, _) = common_pg::init_conn(bs_inst).await?; @@ -445,7 +444,7 @@ pub(crate) async fn fact_records_delete_by_ownership(fact_conf_key: &str, own_pa ), vec![Value::from(own_paths)], ) - .await?; + .await?; conn.commit().await?; Ok(()) } diff --git a/support/auth/src/serv/clients/spi_log_client.rs b/support/auth/src/serv/clients/spi_log_client.rs index 7462a88bf..6f1915723 100644 --- a/support/auth/src/serv/clients/spi_log_client.rs +++ b/support/auth/src/serv/clients/spi_log_client.rs @@ -29,10 +29,7 @@ impl SpiLogClient { return Ok(()); } let spi_ctx = TardisContext { owner: spi_owner, ..ctx.clone() }; - let headers = [( - "Tardis-Context".to_string(), - TardisFuns::crypto.base64.encode(TardisFuns::json.obj_to_string(&spi_ctx)?), - )]; + let headers = [("Tardis-Context".to_string(), TardisFuns::crypto.base64.encode(TardisFuns::json.obj_to_string(&spi_ctx)?))]; //add log item let mut body = HashMap::from([ diff --git a/support/auth/tests/init_cache_container.rs b/support/auth/tests/init_cache_container.rs index 688463ae4..f8798624a 100644 --- a/support/auth/tests/init_cache_container.rs +++ b/support/auth/tests/init_cache_container.rs @@ -3,9 +3,9 @@ use std::env; use tardis::basic::result::TardisResult; use tardis::test::test_container::TardisTestContainer; use tardis::testcontainers::clients::Cli; -use testcontainers_modules::redis::Redis; use tardis::testcontainers::Container; use tardis::TardisFuns; +use testcontainers_modules::redis::Redis; pub struct LifeHold<'a> { pub redis: Container<'a, Redis>, diff --git a/support/auth/tests/test_auth_encrypt.rs b/support/auth/tests/test_auth_encrypt.rs index ad391f5ff..55c770714 100644 --- a/support/auth/tests/test_auth_encrypt.rs +++ b/support/auth/tests/test_auth_encrypt.rs @@ -41,7 +41,6 @@ fn crypto_req(body: &str, serv_pub_key: &str, front_pub_key: &str, need_crypto_r (data, base64_encrypt) } - const WEB_CLIENT_CFG: WebClientModuleConfig = WebClientModuleConfig { connect_timeout_sec: 1, request_timeout_sec: 60, diff --git a/support/enhance-wasm/src/lib.rs b/support/enhance-wasm/src/lib.rs index dc9a0041a..d3def76e4 100644 --- a/support/enhance-wasm/src/lib.rs +++ b/support/enhance-wasm/src/lib.rs @@ -1,7 +1,7 @@ use std::collections::HashMap; -use wasm_bindgen::JsValue; use wasm_bindgen::prelude::*; +use wasm_bindgen::JsValue; use constants::{BIOS_TOKEN, STABLE_CONFIG}; use modules::global_api_process::MixRequest; @@ -29,7 +29,7 @@ pub async fn main(service_url: &str, config: JsValue) -> Result<(), JsValue> { #[wasm_bindgen] /// uri: path?query eg. /iam/ct/xxx?q=1 -pub fn on_before_request(method: &str, uri: &str, body: JsValue, headers: JsValue,ignore_token: JsValue) -> Result { +pub fn on_before_request(method: &str, uri: &str, body: JsValue, headers: JsValue, ignore_token: JsValue) -> Result { if modules::double_auth_process::need_auth(method, uri)? { return Err(JsValue::try_from(JsError::new("Need double auth.")).unwrap()); } diff --git a/support/iam/src/basic/serv/clients/sms_client.rs b/support/iam/src/basic/serv/clients/sms_client.rs index 99ade565d..19e3407af 100644 --- a/support/iam/src/basic/serv/clients/sms_client.rs +++ b/support/iam/src/basic/serv/clients/sms_client.rs @@ -30,15 +30,7 @@ impl SmsClient { let fw_config = TardisFuns::fw_config(); let web_server_config = fw_config.web_server(); let header_name = web_server_config.context_conf.context_header_name.to_string(); - match funs - .web_client() - .put_str_to_str( - &format!("{}/{}/{}/{}", conf.sms_base_url, conf.sms_path, phone, vcode), - "", - vec![(header_name, ctx_base64,)], - ) - .await - { + match funs.web_client().put_str_to_str(&format!("{}/{}/{}/{}", conf.sms_base_url, conf.sms_path, phone, vcode), "", vec![(header_name, ctx_base64)]).await { Ok(_) => Ok(()), Err(_) => Err(funs.err().unauthorized("send_code", "activate", "send sms error", "403-iam-cert-valid")), } @@ -72,10 +64,7 @@ impl SmsClient { .put_str_to_str( &format!("{}/{}/{}/{}", conf.sms_base_url, conf.sms_pwd_path, phone, pwd), "", - vec![( - web_server_config.context_conf.context_header_name.clone(), - ctx_base64.to_string(), - )], + vec![(web_server_config.context_conf.context_header_name.clone(), ctx_base64.to_string())], ) .await { diff --git a/support/iam/src/basic/serv/iam_cert_serv.rs b/support/iam/src/basic/serv/iam_cert_serv.rs index eb0820ef5..9d40f745a 100644 --- a/support/iam/src/basic/serv/iam_cert_serv.rs +++ b/support/iam/src/basic/serv/iam_cert_serv.rs @@ -1216,10 +1216,7 @@ impl IamCertServ { } pub async fn add_or_modify_sync_third_integration_config(reqs: Vec, funs: &TardisFunsInst, ctx: &TardisContext) -> TardisResult<()> { - let headers = vec![( - "Tardis-Context".to_string(), - TardisFuns::crypto.base64.encode(TardisFuns::json.obj_to_string(&ctx)?), - )]; + let headers = vec![("Tardis-Context".to_string(), TardisFuns::crypto.base64.encode(TardisFuns::json.obj_to_string(&ctx)?))]; let schedule_url = funs.conf::().spi.schedule_url.clone(); if schedule_url.is_empty() { return Err(funs.err().not_implemented("third_integration_config", "add_or_modify", "schedule is not impl!", "501-iam-schedule_not_impl_error")); diff --git a/support/iam/src/basic/serv/iam_set_serv.rs b/support/iam/src/basic/serv/iam_set_serv.rs index abbdc3325..9ad290846 100644 --- a/support/iam/src/basic/serv/iam_set_serv.rs +++ b/support/iam/src/basic/serv/iam_set_serv.rs @@ -581,7 +581,8 @@ impl IamSetServ { format!("添加部门人员{}", account.name.clone()), Some("AddAccount".to_string()), ctx, - ).await; + ) + .await; } Err(_) => {} } diff --git a/support/iam/tests/test_basic.rs b/support/iam/tests/test_basic.rs index e0b4b477b..b8b5480b6 100644 --- a/support/iam/tests/test_basic.rs +++ b/support/iam/tests/test_basic.rs @@ -6,8 +6,8 @@ use bios_iam::basic::serv::iam_cert_ldap_serv::AccountFieldMap; use tardis::basic::result::TardisResult; use tardis::testcontainers::clients::Cli; use tardis::testcontainers::core::{ExecCommand, WaitFor}; -use tardis::testcontainers::GenericImage; use tardis::testcontainers::Container; +use tardis::testcontainers::GenericImage; use tardis::TardisFuns; const BASE_LDIF: &str = "dn: cn=Barbara,dc=test,dc=com diff --git a/support/reach/src/api/reach_api_ct/reach_api_ct_message.rs b/support/reach/src/api/reach_api_ct/reach_api_ct_message.rs index 9fb62987f..00ed11897 100644 --- a/support/reach/src/api/reach_api_ct/reach_api_ct_message.rs +++ b/support/reach/src/api/reach_api_ct/reach_api_ct_message.rs @@ -56,7 +56,7 @@ impl ReachMessageCtApi { let resp = ReachMessageServ::get_rbum(&id, &filter, &funs, &ctx).await?; TardisResp::ok(resp) } - + /// 重新发送消息(仅仅适用于状态为Fail的消息) #[oai(method = "put", path = "/resend/:id")] pub async fn resend(&self, id: Path, TardisContextExtractor(ctx): TardisContextExtractor) -> TardisApiResult { @@ -64,7 +64,7 @@ impl ReachMessageCtApi { let success = ReachMessageServ::resend(&id, &funs, &ctx).await?; TardisResp::ok(success) } - + /// 添加消息 #[oai(method = "post", path = "/")] pub async fn add_message(&self, mut add_req: Json, TardisContextExtractor(ctx): TardisContextExtractor) -> TardisApiResult { diff --git a/support/reach/src/serv/message_log.rs b/support/reach/src/serv/message_log.rs index 67dcd2529..4d9551812 100644 --- a/support/reach/src/serv/message_log.rs +++ b/support/reach/src/serv/message_log.rs @@ -6,7 +6,7 @@ use tardis::basic::dto::TardisContext; use tardis::basic::result::TardisResult; use tardis::db::reldb_client::TardisActiveModel; -use tardis::db::sea_orm::sea_query::{Query, SelectStatement, Expr, Alias}; +use tardis::db::sea_orm::sea_query::{Alias, Expr, Query, SelectStatement}; use tardis::db::sea_orm::{ColumnTrait, Set}; use tardis::db::sea_orm::{EntityName, Iterable}; use tardis::{TardisFuns, TardisFunsInst}; @@ -42,7 +42,6 @@ impl RbumCrudOperation TardisResult<()> { for req in agg_req.global_config { - Self::add_or_modify_by_single_req(req, funs, ctx).await?; } Ok(()) diff --git a/support/reach/src/task/message_send_listener.rs b/support/reach/src/task/message_send_listener.rs index fa35e2477..6c0998c14 100644 --- a/support/reach/src/task/message_send_listener.rs +++ b/support/reach/src/task/message_send_listener.rs @@ -28,7 +28,13 @@ impl Default for MessageSendListener { } impl MessageSendListener { - async fn execute_send_account(&self, content_replace: ContentReplace, message: message::Model, template: message_template::Model, _signarure: Option) -> TardisResult<()> { + async fn execute_send_account( + &self, + content_replace: ContentReplace, + message: message::Model, + template: message_template::Model, + _signarure: Option, + ) -> TardisResult<()> { let cfg = self.funs.conf::(); let _lock = self.sync.lock().await; let ctx = TardisContext { @@ -60,7 +66,10 @@ impl MessageSendListener { for account_id in message.to_res_ids.split(ACCOUNT_SPLIT) { if let Ok(mut resp) = iam_client.get_account(account_id, &owner_path).await { let Some(res_id) = resp.certs.remove(cert_key) else { - log::warn!("[Reach] Notify {chan} channel send error, missing [{cert_key}] parameters, resp: {resp:?}", chan = message.rel_reach_channel); + log::warn!( + "[Reach] Notify {chan} channel send error, missing [{cert_key}] parameters, resp: {resp:?}", + chan = message.rel_reach_channel + ); continue; }; to.insert(res_id); diff --git a/support/reach/tests/test_reach_common.rs b/support/reach/tests/test_reach_common.rs index 69edfcf33..0216b5ec6 100644 --- a/support/reach/tests/test_reach_common.rs +++ b/support/reach/tests/test_reach_common.rs @@ -13,7 +13,6 @@ use serde::{Deserialize, Serialize}; use std::collections::HashMap; use std::sync::{Arc, OnceLock}; use tardis::testcontainers::GenericImage; -use testcontainers_modules::redis::Redis; use tardis::tokio::sync::RwLock; use tardis::web::poem_openapi::param::Path; use tardis::web::poem_openapi::payload::{Form, Json}; @@ -27,6 +26,7 @@ use tardis::{ TardisFuns, }; use tardis::{log, rand, serde_json}; +use testcontainers_modules::redis::Redis; pub struct Holder<'d> { pub db: Container<'d, GenericImage>, pub cache: Container<'d, Redis>,