diff --git a/ecstore/src/store.rs b/ecstore/src/store.rs index 1aae9ab3..8a95edef 100644 --- a/ecstore/src/store.rs +++ b/ecstore/src/store.rs @@ -58,7 +58,7 @@ use tokio::select; use tokio::sync::mpsc::Sender; use tokio::sync::{broadcast, mpsc, RwLock}; use tokio::time::{interval, sleep}; -use tracing::{debug, info, warn}; +use tracing::{debug, info}; use uuid::Uuid; const MAX_UPLOADS_LIST: usize = 10000; @@ -1235,10 +1235,8 @@ impl StorageAPI for ECStore { let mut buckets = self.peer_sys.list_bucket(opts).await?; if !opts.no_metadata { - warn!("list_bucket meta"); for bucket in buckets.iter_mut() { if let Ok(created) = metadata_sys::created_at(&bucket.name).await { - warn!("list_bucket created {:?}", &created); bucket.created = Some(created); } } diff --git a/iam/src/auth/credentials.rs b/iam/src/auth/credentials.rs index bb543779..457df7d9 100644 --- a/iam/src/auth/credentials.rs +++ b/iam/src/auth/credentials.rs @@ -224,7 +224,7 @@ pub fn create_new_credentials_with_metadata( } }; - let token = utils::generate_jwt(claims, token_secret)?; + let token = utils::generate_jwt(&claims, token_secret)?; Ok(Credentials { access_key: ak.to_owned(), diff --git a/iam/src/store/object.rs b/iam/src/store/object.rs index e9c20064..99bf40db 100644 --- a/iam/src/store/object.rs +++ b/iam/src/store/object.rs @@ -4,7 +4,7 @@ use crate::{ cache::{Cache, CacheEntity}, error::{is_err_no_such_policy, is_err_no_such_user}, get_global_action_cred, - manager::get_default_policyes, + manager::{extract_jwt_claims, get_default_policyes}, policy::PolicyDoc, }; use ecstore::{ @@ -420,8 +420,20 @@ impl Store for ObjectStore { u.credentials.access_key = name.to_owned(); } - if u.credentials.session_token.is_empty() { - // TODO: 解析sts + if !u.credentials.session_token.is_empty() { + match extract_jwt_claims(&u) { + Ok(claims) => { + u.credentials.claims = Some(claims); + } + Err(err) => { + if u.credentials.is_temp() { + let _ = self.delete_iam_config(get_user_identity_path(name, user_type)).await; + let _ = self.delete_iam_config(get_mapped_policy_path(name, user_type, false)).await; + } + warn!("extract_jwt_claims failed: {}", err); + return Err(Error::new(crate::error::Error::NoSuchUser(name.to_owned()))); + } + } } Ok(u) @@ -807,7 +819,7 @@ impl Store for ObjectStore { } // group policy - if let Some(item_name_list) = listed_config_items.get(SVC_ACC_LIST_KEY) { + if let Some(item_name_list) = listed_config_items.get(POLICY_DB_GROUPS_LIST_KEY) { let mut items_cache = CacheEntity::default(); for item in item_name_list.iter() { @@ -815,7 +827,9 @@ impl Store for ObjectStore { info!("load group policy: {}", name); if let Err(err) = self.load_mapped_policy(name, UserType::Reg, true, &mut items_cache).await { - return Err(Error::msg(std::format!("load group failed: {}", err))); + if !is_err_no_such_policy(&err) { + return Err(Error::msg(std::format!("load group policy failed: {}", err))); + } }; } @@ -825,7 +839,7 @@ impl Store for ObjectStore { let mut sts_policies_cache = CacheEntity::default(); // svc users - if let Some(item_name_list) = listed_config_items.get(POLICY_DB_GROUPS_LIST_KEY) { + if let Some(item_name_list) = listed_config_items.get(SVC_ACC_LIST_KEY) { let mut items_cache = HashMap::default(); for item in item_name_list.iter() { diff --git a/iam/src/sys.rs b/iam/src/sys.rs index 5188bab8..6a016708 100644 --- a/iam/src/sys.rs +++ b/iam/src/sys.rs @@ -229,6 +229,11 @@ impl IamSys { } } + m.insert( + "exp".to_string(), + serde_json::Value::Number(serde_json::Number::from(opts.expiration.map_or(0, |t| t.unix_timestamp()))), + ); + let (access_key, secret_key) = if !opts.access_key.is_empty() || !opts.secret_key.is_empty() { (opts.access_key, opts.secret_key) } else { diff --git a/madmin/src/user.rs b/madmin/src/user.rs index ffe402d1..7de50f5b 100644 --- a/madmin/src/user.rs +++ b/madmin/src/user.rs @@ -104,7 +104,7 @@ pub struct ServiceAccountInfo { #[serde(rename = "description", skip_serializing_if = "Option::is_none")] pub description: Option, - #[serde(rename = "expiration", skip_serializing_if = "Option::is_none")] + #[serde(rename = "expiration", with = "time::serde::rfc3339::option")] pub expiration: Option, } @@ -134,7 +134,7 @@ pub struct AddServiceAccountReq { #[serde(rename = "description", skip_serializing_if = "Option::is_none")] pub description: Option, - #[serde(rename = "expiration", skip_serializing_if = "Option::is_none")] + #[serde(rename = "expiration", with = "time::serde::rfc3339::option")] pub expiration: Option, } diff --git a/rustfs/src/admin/handlers/service_account.rs b/rustfs/src/admin/handlers/service_account.rs index be1588cc..7357d9b2 100644 --- a/rustfs/src/admin/handlers/service_account.rs +++ b/rustfs/src/admin/handlers/service_account.rs @@ -42,6 +42,7 @@ impl Operation for AddServiceAccount { let mut create_req: AddServiceAccountReq = serde_json::from_slice(&body[..]).map_err(|e| s3_error!(InvalidRequest, "unmarshal body failed, e: {:?}", e))?; + create_req.expiration = create_req.expiration.and_then(|expire| expire.replace_millisecond(0).ok()); if has_space_be(&create_req.access_key) { @@ -128,7 +129,7 @@ impl Operation for AddServiceAccount { .await .map_err(|e| { debug!("create service account failed, e: {:?}", e); - s3_error!(InternalError, "create service account failed") + s3_error!(InternalError, "create service account failed, e: {:?}", e) })?; let resp = AddServiceAccountResp { diff --git a/rustfs/src/config/mod.rs b/rustfs/src/config/mod.rs index 406b211f..477998a8 100644 --- a/rustfs/src/config/mod.rs +++ b/rustfs/src/config/mod.rs @@ -35,7 +35,7 @@ const LONG_VERSION: &str = concat!( #[command(version = SHORT_VERSION, long_version = LONG_VERSION)] pub struct Opt { /// DIR points to a directory on a filesystem. - #[arg(required = true)] + #[arg(required = true, env = "RUSTFS_VOLUMES")] pub volumes: Vec, /// bind to a specific ADDRESS:PORT, ADDRESS can be an IP or hostname diff --git a/rustfs/src/console.rs b/rustfs/src/console.rs index 07aa8119..704a575e 100644 --- a/rustfs/src/console.rs +++ b/rustfs/src/console.rs @@ -7,6 +7,7 @@ use axum::{ }; use include_dir::{include_dir, Dir}; +use serde::Serialize; static STATIC_DIR: Dir = include_dir!("$CARGO_MANIFEST_DIR/static"); @@ -25,9 +26,26 @@ async fn static_handler(uri: axum::http::Uri) -> impl IntoResponse { } } -pub async fn start_static_file_server(addrs: &str) { +#[derive(Debug, Clone, Serialize)] +struct Config { + fs_addr: String, +} + +async fn config_handler(axum::extract::Extension(fs_addr): axum::extract::Extension) -> impl IntoResponse { + let cfg = serde_json::to_string(&Config { fs_addr }).unwrap_or_default(); + + Response::builder() + .header("content-type", "application/json") + .status(StatusCode::OK) + .body(Body::from(cfg)) + .unwrap() +} + +pub async fn start_static_file_server(addrs: &str, fs_addr: &str) { // 创建路由 - let app = Router::new().route("/*file", get(static_handler)); + let app = Router::new() + .route("/config.json", get(config_handler).layer(axum::extract::Extension(fs_addr.to_string()))) + .route("/*file", get(static_handler)); let listener = tokio::net::TcpListener::bind(addrs).await.unwrap(); diff --git a/rustfs/src/main.rs b/rustfs/src/main.rs index a2ed4790..fd5d4079 100644 --- a/rustfs/src/main.rs +++ b/rustfs/src/main.rs @@ -234,7 +234,7 @@ async fn run(opt: config::Opt) -> Result<()> { if opt.console_enable { info!("console is enabled"); tokio::spawn(async move { - console::start_static_file_server(&opt.console_address).await; + console::start_static_file_server(&opt.console_address, &opt.address).await; }); } diff --git a/scripts/run.sh b/scripts/run.sh index b2436ac1..4aa012d7 100755 --- a/scripts/run.sh +++ b/scripts/run.sh @@ -11,6 +11,7 @@ mkdir -p ./target/volume/test{0..4} if [ -z "$RUST_LOG" ]; then +export RUST_BACKTRACE=1 export RUST_LOG="rustfs=debug,ecstore=debug,s3s=debug,iam=debug" fi @@ -18,21 +19,15 @@ fi # export RUSTFS_STORAGE_CLASS_INLINE_BLOCK="512 KB" - -# DATA_DIR_ARG="./target/volume/test{0...4}" -DATA_DIR_ARG="./target/volume/test" +# RUSTFS_VOLUMES="./target/volume/test{0...4}" +export RUSTFS_VOLUMES="./target/volume/test" +export RUSTFS_ADDRESS="0.0.0.0:9000" +export RUSTFS_CONSOLE_ENABLE=true +export RUSTFS_CONSOLE_ADDRESS="0.0.0.0:9002" if [ -n "$1" ]; then - DATA_DIR_ARG="$1" + export RUSTFS_VOLUMES="$1" fi -# cargo run "$DATA_DIR_ARG" - # -- --access-key AKEXAMPLERUSTFS \ - # --secret-key SKEXAMPLERUSTFS \ - # --address 0.0.0.0:9010 \ - # --domain-name 127.0.0.1:9010 \ - # "$DATA_DIR_ARG" - -./target/debug/rustfs "$DATA_DIR_ARG" -# cargo run ./target/volume/test \ No newline at end of file +./target/debug/rustfs