mirror of
https://github.com/rustfs/rustfs.git
synced 2026-07-28 17:18:58 +00:00
iam add_user
This commit is contained in:
@@ -100,7 +100,7 @@ pub struct Credentials {
|
||||
pub status: String,
|
||||
pub parent_user: String,
|
||||
pub groups: Option<Vec<String>>,
|
||||
pub claims: Option<HashMap<String, Vec<String>>>,
|
||||
pub claims: Option<HashMap<String, String>>,
|
||||
pub name: Option<String>,
|
||||
pub description: Option<String>,
|
||||
}
|
||||
|
||||
+13
-1
@@ -20,7 +20,7 @@ use tokio::{
|
||||
|
||||
use crate::{
|
||||
arn::ARN,
|
||||
auth::{Credentials, UserIdentity},
|
||||
auth::{self, Credentials, UserIdentity},
|
||||
cache::Cache,
|
||||
format::Format,
|
||||
handler::Handler,
|
||||
@@ -309,4 +309,16 @@ where
|
||||
|
||||
Ok(m)
|
||||
}
|
||||
|
||||
pub async fn add_user(&self, access_key: &str, secret_key: &str, status: &str) -> crate::Result<()> {
|
||||
let status = {
|
||||
match status {
|
||||
"disabled" => auth::ACCOUNT_ON,
|
||||
auth::ACCOUNT_ON => auth::ACCOUNT_ON,
|
||||
_ => auth::ACCOUNT_OFF,
|
||||
}
|
||||
};
|
||||
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,9 +20,9 @@ use ecstore::utils::path::path_join;
|
||||
use ecstore::utils::xml;
|
||||
use ecstore::GLOBAL_Endpoints;
|
||||
use futures::{Stream, StreamExt};
|
||||
use http::Uri;
|
||||
use http::{HeaderMap, Uri};
|
||||
use hyper::StatusCode;
|
||||
use iam::auth::create_new_credentials_with_metadata;
|
||||
use iam::auth::{create_new_credentials_with_metadata, get_claims_from_token_with_secret};
|
||||
use iam::{auth, get_global_action_cred};
|
||||
use madmin::metrics::RealtimeMetrics;
|
||||
use madmin::utils::parse_duration;
|
||||
@@ -93,11 +93,21 @@ pub struct AssumeRoleRequest {
|
||||
// pub parent_user: String,
|
||||
// }
|
||||
|
||||
#[derive(Debug, Serialize, Default)]
|
||||
#[derive(Debug, Serialize, Deserialize, Default)]
|
||||
pub struct STSClaims {
|
||||
parent: String,
|
||||
exp: usize,
|
||||
access_key: String,
|
||||
pub parent: String,
|
||||
pub exp: usize,
|
||||
pub access_key: String,
|
||||
}
|
||||
|
||||
impl STSClaims {
|
||||
pub fn to_map(&self) -> HashMap<String, String> {
|
||||
let mut m = HashMap::new();
|
||||
m.insert("parent".to_string(), self.parent.clone());
|
||||
m.insert("exp".to_string(), self.exp.to_string());
|
||||
m.insert("access_key".to_string(), self.access_key.clone());
|
||||
m
|
||||
}
|
||||
}
|
||||
|
||||
fn get_token_signing_key() -> Option<String> {
|
||||
@@ -108,11 +118,13 @@ fn get_token_signing_key() -> Option<String> {
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn check_key_valid(st: &str, ak: &str) -> S3Result<(auth::Credentials, bool)> {
|
||||
pub async fn check_key_valid(token: Option<String>, ak: &str) -> S3Result<(auth::Credentials, bool)> {
|
||||
let Some(mut cred) = get_global_action_cred() else {
|
||||
return Err(s3_error!(InternalError, "action cred not init"));
|
||||
};
|
||||
|
||||
let sys_cred = cred.clone();
|
||||
|
||||
if cred.access_key != ak {
|
||||
let Ok(iam_store) = iam::get() else { return Err(s3_error!(InternalError, "iam not init")) };
|
||||
|
||||
@@ -135,34 +147,67 @@ pub async fn check_key_valid(st: &str, ak: &str) -> S3Result<(auth::Credentials,
|
||||
return Err(s3_error!(InvalidRequest, "check key failed"));
|
||||
}
|
||||
}
|
||||
|
||||
return Ok((cred, true));
|
||||
}
|
||||
unimplemented!()
|
||||
|
||||
if let Some(st) = token {
|
||||
let claims = check_claims_from_token(&st, &cred)
|
||||
.map_err(|e| S3Error::with_message(S3ErrorCode::InternalError, format!("check claims failed {}", e)))?;
|
||||
cred.claims = Some(claims.to_map());
|
||||
}
|
||||
|
||||
let owner = sys_cred.access_key == cred.access_key || cred.parent_user == sys_cred.access_key;
|
||||
|
||||
// permitRootAccess
|
||||
// SessionPolicyName
|
||||
Ok((cred, owner))
|
||||
}
|
||||
|
||||
pub fn check_claims_from_token(token: &str, cred: &auth::Credentials) -> crate::Result<HashMap<String, Vec<String>>> {
|
||||
// if !token.is_empty() && cred.access_key.is_empty() {
|
||||
// return Err(Error::NoAccessKey);
|
||||
// }
|
||||
pub fn check_claims_from_token(token: &str, cred: &auth::Credentials) -> S3Result<STSClaims> {
|
||||
if !token.is_empty() && cred.access_key.is_empty() {
|
||||
return Err(s3_error!(InvalidRequest, "no access key"));
|
||||
}
|
||||
|
||||
// if token.is_empty() && cred.is_temp() && !cred.is_service_account() {
|
||||
// return Err(Error::InvalidToken);
|
||||
// }
|
||||
if token.is_empty() && cred.is_temp() && !cred.is_service_account() {
|
||||
return Err(s3_error!(InvalidRequest, "invalid token"));
|
||||
}
|
||||
|
||||
// if !token.is_empty() && !cred.is_temp() {
|
||||
// return Err(Error::InvalidToken);
|
||||
// }
|
||||
if !token.is_empty() && !cred.is_temp() {
|
||||
return Err(s3_error!(InvalidRequest, "invalid token"));
|
||||
}
|
||||
|
||||
// if !cred.is_service_account() && cred.is_temp() && token != cred.session_token {
|
||||
// return Err(Error::InvalidToken);
|
||||
// }
|
||||
if !cred.is_service_account() && cred.is_temp() && token != cred.session_token {
|
||||
return Err(s3_error!(InvalidRequest, "invalid token"));
|
||||
}
|
||||
|
||||
// if cred.is_temp() || cred.is_expired() {
|
||||
// return Err(Error::InvalidAccessKey);
|
||||
// }
|
||||
if cred.is_temp() || cred.is_expired() {
|
||||
return Err(s3_error!(InvalidRequest, "invalid access key"));
|
||||
}
|
||||
|
||||
unimplemented!()
|
||||
let Some(sys_cred) = get_global_action_cred() else {
|
||||
return Err(s3_error!(InternalError, "action cred not init"));
|
||||
};
|
||||
|
||||
let mut secret = sys_cred.secret_key;
|
||||
|
||||
let mut token = token;
|
||||
|
||||
if cred.is_service_account() {
|
||||
token = cred.session_token.as_str();
|
||||
secret = cred.secret_key.clone();
|
||||
}
|
||||
|
||||
if !token.is_empty() {
|
||||
let claims: STSClaims =
|
||||
get_claims_from_token_with_secret(token, &secret).map_err(|_e| s3_error!(InvalidRequest, "invalid token"))?;
|
||||
return Ok(claims);
|
||||
}
|
||||
|
||||
Ok(STSClaims::default())
|
||||
}
|
||||
|
||||
pub fn get_session_token(hds: &HeaderMap) -> Option<String> {
|
||||
hds.get("x-amz-security-token")
|
||||
.map(|v| v.to_str().unwrap_or_default().to_string())
|
||||
}
|
||||
|
||||
pub struct AssumeRoleHandle {}
|
||||
|
||||
@@ -7,7 +7,10 @@ use serde::Deserialize;
|
||||
use serde_urlencoded::from_bytes;
|
||||
use tracing::warn;
|
||||
|
||||
use crate::admin::router::Operation;
|
||||
use crate::admin::{
|
||||
handlers::{check_key_valid, get_session_token},
|
||||
router::Operation,
|
||||
};
|
||||
|
||||
#[derive(Debug, Deserialize, Default)]
|
||||
pub struct AddUserQuery {
|
||||
@@ -29,6 +32,10 @@ impl Operation for AddUser {
|
||||
}
|
||||
};
|
||||
|
||||
let Some(input_cred) = req.credentials else {
|
||||
return Err(s3_error!(InvalidRequest, "get cred failed"));
|
||||
};
|
||||
|
||||
let ak = query.access_key.as_deref().unwrap_or_default();
|
||||
|
||||
if let Some(sys_cred) = get_global_action_cred() {
|
||||
@@ -46,6 +53,14 @@ impl Operation for AddUser {
|
||||
}
|
||||
}
|
||||
|
||||
let token = get_session_token(&req.headers);
|
||||
|
||||
let (cred, _) = check_key_valid(token, &input_cred.access_key).await?;
|
||||
|
||||
if (cred.is_temp() || cred.is_service_account()) && cred.parent_user == input_cred.access_key {
|
||||
return Err(s3_error!(InvalidArgument, "can't create user with service account access key"));
|
||||
}
|
||||
|
||||
warn!("handle AddUser");
|
||||
return Err(s3_error!(NotImplemented));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user