diff --git a/core/gateway/apisix/apisix/plugins/auth-bios.lua b/core/gateway/apisix/apisix/plugins/auth-bios.lua index c923c35ed..569cb9870 100644 --- a/core/gateway/apisix/apisix/plugins/auth-bios.lua +++ b/core/gateway/apisix/apisix/plugins/auth-bios.lua @@ -2,6 +2,7 @@ local core = require("apisix.core") local m_redis = require("apisix.plugins.auth-bios.redis") local m_init = require("apisix.plugins.auth-bios.init") local m_ident = require("apisix.plugins.auth-bios.ident") +local m_aksk = require("apisix.plugins.auth-bios.aksk") local m_auth = require("apisix.plugins.auth-bios.auth") local json = require("cjson") local ngx = ngx @@ -19,13 +20,17 @@ local schema = { redis_database = { type = "integer", default = 0 }, head_key_token = { type = "string", default = "Bios-Token" }, + head_key_ak={ type="string", default="Bios-Ak" }, + head_key_sk={ type="string", default="Bios-Sk" }, head_key_app = { type = "string", default = "Bios-App" }, head_key_protocol = { type = "string", default = "Bios-Proto" }, head_key_context = { type = "string", default = "Tardis-Context" }, cache_key_token_info = { type = "string", default = "iam:cache:token:info:" }, + cache_key_aksk_info = { type = "string", default="iam:cache:aksk:info:"}, cache_key_account_info = { type = "string", default = "iam:cache:account:info:" }, cache_key_token_local_expire_sec = { type = "integer", default = 0 }, + cache_key_aksk_local_expire_sec = { type = "integer", default = 0 }, cache_key_res_info = { type = "string", default = "iam:res:info" }, cache_key_res_changed_info = { type = "string", default = "iam:res:changed:info:" }, @@ -95,6 +100,11 @@ function _M.rewrite(conf, ctx) cors(conf) return ident_code, { code = ident_code .. '-gateway-cert-error', message = ident_message } end + local aksk_code,aksk_message = m_aksk.aksk(conf,ctx) + if aksk_code ~= 200 then + cors(conf) + return aksk_code, { code = ident_code .. '-gateway-cert-error', message = aksk_message } + end local auth_code, auth_message = m_auth.auth(ctx.ident_info) if auth_code ~= 200 then cors(conf) diff --git a/core/gateway/apisix/apisix/plugins/auth-bios/aksk.lua b/core/gateway/apisix/apisix/plugins/auth-bios/aksk.lua new file mode 100644 index 000000000..9e506c9d0 --- /dev/null +++ b/core/gateway/apisix/apisix/plugins/auth-bios/aksk.lua @@ -0,0 +1,105 @@ +local ngx = ngx +local core = require("apisix.core") +local m_utils = require("apisix.plugins.auth-bios.utils") +local m_redis = require("apisix.plugins.auth-bios.redis") + +local _M = {} + +function _M.aksk(conf, ctx) + -- Fetch args + local head_key_ak = conf.head_key_ak + local head_key_sk = conf.head_key_sk + local app_flag = conf.head_key_app + local protocol_flag = conf.head_key_protocol + + local cache_key_aksk= conf.cache_key_aksk_info + local cache_aksk_exp_sec = conf.cache_key_aksk_local_expire_sec + + local resource_uri = ngx.var.request_uri + local req_method = ngx.var.request_method + + -- package rbum info + local domain_end_idx = string.find(string.sub(resource_uri, 2), "/") + if domain_end_idx == nil then + return 400, "Request is not legal, missing [domain] in path" + end + local rbum_kind = core.request.header(ctx, protocol_flag) + if rbum_kind == nil or rbum_kind == "" then + rbum_kind = "iam-res" + end + local rbum_domain = string.sub(resource_uri, 2, domain_end_idx) + local rbum_item = string.sub(resource_uri, domain_end_idx + 1) + local rbum_uri = rbum_kind .. "://" .. rbum_domain .. rbum_item + local rbum_action = string.lower(req_method) + + -- from header + local ak = core.request.header(ctx, head_key_ak) + local sk = core.request.header(ctx, head_key_sk) + + local app_id = core.request.header(ctx, app_flag) + if app_id == nil or app_id == "" then + app_id = "" + end + + -- public + if ak == nil then + ctx.ident_info = { + rbum_uri = rbum_uri, + rbum_action = rbum_action, + iam_app_id = '', + iam_tenant_id = '', + iam_account_id = '', + iam_roles = {}, + iam_groups = {}, + own_paths = '', + ak = '', + } + return 200 + end + + -- ak + if ak ~= nil then + -- cache_sk = (sk,tenant_id,[appid]), see IamConfig:cache_key_aksk_info_ + local cache_sk_info, redis_err = m_redis.get(cache_key_aksk .. ak, cache_aksk_exp_sec) + if redis_err then + error("Redis get error: " .. redis_err) + end + local cache_sk = m_utils.split(cache_sk_info, ',')[1] + if cache_sk_info == nil or cache_sk_info == "" or cache_sk ~= sk then + return 401, "Ak [" .. ak .. "] is not legal" + end + + local tenant_id = m_utils.split(cache_sk_info, ',')[2] + local appid = m_utils.split(cache_sk_info, ',')[3] + + if redis_err then + error("Redis get error: " .. redis_err) + end + + local own_paths = tenant_id + + if app_id ~= "" then + if app_id~=appid then + return 401, "Ak [" .. ak .. "] with App [" .. app_id .. "] is not legal" + end + own_paths=tenant_id.."/"..app_id + end + + ctx.ident_info = { + rbum_uri = rbum_uri, + rbum_action = rbum_action, + iam_app_id = appid or '', + iam_tenant_id = tenant_id or '', + iam_account_id = '', + iam_roles = {}, + iam_groups = {}, + own_paths = own_paths, + ak = ak, + } + return 200 + end + + return 200 +end + +return _M \ No newline at end of file diff --git a/core/iam/src/basic/dto/iam_cert_conf_dto.rs b/core/iam/src/basic/dto/iam_cert_conf_dto.rs index 2222e2f06..eb0c3d33d 100644 --- a/core/iam/src/basic/dto/iam_cert_conf_dto.rs +++ b/core/iam/src/basic/dto/iam_cert_conf_dto.rs @@ -99,7 +99,12 @@ pub struct IamCertConfOAuth2Resp { pub sk: String, } #[derive(poem_openapi::Object, Serialize, Deserialize, Debug)] -pub struct IamCertConfAkSkAddOrModifyReq {} +pub struct IamCertConfAkSkAddOrModifyReq { + #[oai(validator(min_length = "2", max_length = "255"))] + pub name: TrimString, + #[oai(validator(minimum(value = "1", exclusive = "false")))] + pub expire_sec: Option, +} #[derive(poem_openapi::Object, Serialize, Deserialize, Debug)] pub struct IamCertConfLdapAddOrModifyReq { /// Assign a code to the LdapCertConf,Used to distinguish different sources diff --git a/core/iam/src/basic/serv/iam_cert_aksk_serv.rs b/core/iam/src/basic/serv/iam_cert_aksk_serv.rs index 185ee140e..e0e38e7ac 100644 --- a/core/iam/src/basic/serv/iam_cert_aksk_serv.rs +++ b/core/iam/src/basic/serv/iam_cert_aksk_serv.rs @@ -1,6 +1,6 @@ use bios_basic::rbum::dto::rbum_cert_conf_dto::{RbumCertConfAddReq, RbumCertConfModifyReq}; use bios_basic::rbum::dto::rbum_cert_dto::RbumCertAddReq; -use bios_basic::rbum::dto::rbum_filer_dto::RbumCertFilterReq; +use bios_basic::rbum::dto::rbum_filer_dto::{RbumBasicFilterReq, RbumCertConfFilterReq, RbumCertFilterReq}; use bios_basic::rbum::rbum_enumeration::{RbumCertConfStatusKind, RbumCertRelKind, RbumCertStatusKind}; use bios_basic::rbum::serv::rbum_cert_serv::{RbumCertConfServ, RbumCertServ}; use bios_basic::rbum::serv::rbum_crud_serv::RbumCrudOperation; @@ -26,7 +26,7 @@ impl IamCertAkSkServ { &mut RbumCertConfAddReq { kind: TrimString(IamCertKernelKind::AkSk.to_string()), supplier: None, - name: TrimString(IamCertKernelKind::AkSk.to_string()), + name: add_req.name.clone(), note: None, ak_note: None, ak_rule: None, @@ -40,7 +40,7 @@ impl IamCertAkSkServ { is_basic: Some(false), is_ak_repeatable: None, rest_by_kinds: None, - expire_sec: None, + expire_sec: add_req.expire_sec.clone(), sk_lock_cycle_sec: None, sk_lock_err_times: None, sk_lock_duration_sec: None, @@ -62,7 +62,7 @@ impl IamCertAkSkServ { RbumCertConfServ::modify_rbum( id, &mut RbumCertConfModifyReq { - name: None, + name: Some(modify_req.name.clone()), note: None, ak_note: None, ak_rule: None, @@ -74,7 +74,7 @@ impl IamCertAkSkServ { repeatable: None, is_basic: None, rest_by_kinds: None, - expire_sec: None, + expire_sec: modify_req.expire_sec.clone(), sk_lock_cycle_sec: None, sk_lock_err_times: None, sk_lock_duration_sec: None, @@ -89,6 +89,19 @@ impl IamCertAkSkServ { } pub async fn add_cert(add_req: &IamCertAkSkAddReq, ak: &str, sk: &str, rel_rbum_cert_conf_id: &str, funs: &TardisFunsInst, ctx: &TardisContext) -> TardisResult { + let cert_conf = RbumCertConfServ::peek_rbum( + rel_rbum_cert_conf_id, + &RbumCertConfFilterReq { + basic: RbumBasicFilterReq { + with_sub_own_paths: true, + ..Default::default() + }, + ..Default::default() + }, + funs, + ctx, + ) + .await?; let new_ctx = TardisContext { owner: RBUM_SYSTEM_OWNER.to_string(), own_paths: if add_req.app_id.is_some() { @@ -124,7 +137,7 @@ impl IamCertAkSkServ { &new_ctx, ) .await?; - IamIdentCacheServ::add_aksk(ak, sk, rel_rbum_id, funs).await?; + IamIdentCacheServ::add_aksk(ak, sk, rel_rbum_id, cert_conf.expire_sec, funs).await?; Ok(id) } pub async fn delete_cert(id: &str, funs: &TardisFunsInst, ctx: &TardisContext) -> TardisResult<()> { diff --git a/core/iam/src/basic/serv/iam_key_cache_serv.rs b/core/iam/src/basic/serv/iam_key_cache_serv.rs index b34ff465b..386a03e1d 100644 --- a/core/iam/src/basic/serv/iam_key_cache_serv.rs +++ b/core/iam/src/basic/serv/iam_key_cache_serv.rs @@ -227,16 +227,24 @@ impl IamIdentCacheServ { Err(funs.err().not_found("iam_cache_context", "get", "not found context", "404-iam-cache-context-not-exist")) } - pub async fn add_aksk(ak: &str, sk: &str, rel_iam_item_id: &str, funs: &TardisFunsInst) -> TardisResult<()> { + pub async fn add_aksk(ak: &str, sk: &str, rel_iam_item_id: &str, expire_sec: i64, funs: &TardisFunsInst) -> TardisResult<()> { log::trace!("add aksk: ak={},sk={}", ak, sk); - - funs.cache() - .set( - format!("{}{}", funs.conf::().cache_key_aksk_info_, ak).as_str(), - format!("{},{}", sk, rel_iam_item_id,).as_str(), - ) - .await?; - + if expire_sec > 0 { + funs.cache() + .set_ex( + format!("{}{}", funs.conf::().cache_key_aksk_info_, ak).as_str(), + format!("{},{}", sk, rel_iam_item_id,).as_str(), + expire_sec as usize, + ) + .await?; + } else { + funs.cache() + .set( + format!("{}{}", funs.conf::().cache_key_aksk_info_, ak).as_str(), + format!("{},{}", sk, rel_iam_item_id,).as_str(), + ) + .await?; + } Ok(()) }