iam add_user

This commit is contained in:
weisd
2025-01-12 03:04:14 +08:00
parent 1c44e2d099
commit 0aaef2d9a8
4 changed files with 102 additions and 30 deletions
+1 -1
View File
@@ -100,7 +100,7 @@ pub struct Credentials {
pub status: String, pub status: String,
pub parent_user: String, pub parent_user: String,
pub groups: Option<Vec<String>>, pub groups: Option<Vec<String>>,
pub claims: Option<HashMap<String, Vec<String>>>, pub claims: Option<HashMap<String, String>>,
pub name: Option<String>, pub name: Option<String>,
pub description: Option<String>, pub description: Option<String>,
} }
+13 -1
View File
@@ -20,7 +20,7 @@ use tokio::{
use crate::{ use crate::{
arn::ARN, arn::ARN,
auth::{Credentials, UserIdentity}, auth::{self, Credentials, UserIdentity},
cache::Cache, cache::Cache,
format::Format, format::Format,
handler::Handler, handler::Handler,
@@ -309,4 +309,16 @@ where
Ok(m) 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!()
}
} }
+72 -27
View File
@@ -20,9 +20,9 @@ use ecstore::utils::path::path_join;
use ecstore::utils::xml; use ecstore::utils::xml;
use ecstore::GLOBAL_Endpoints; use ecstore::GLOBAL_Endpoints;
use futures::{Stream, StreamExt}; use futures::{Stream, StreamExt};
use http::Uri; use http::{HeaderMap, Uri};
use hyper::StatusCode; 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 iam::{auth, get_global_action_cred};
use madmin::metrics::RealtimeMetrics; use madmin::metrics::RealtimeMetrics;
use madmin::utils::parse_duration; use madmin::utils::parse_duration;
@@ -93,11 +93,21 @@ pub struct AssumeRoleRequest {
// pub parent_user: String, // pub parent_user: String,
// } // }
#[derive(Debug, Serialize, Default)] #[derive(Debug, Serialize, Deserialize, Default)]
pub struct STSClaims { pub struct STSClaims {
parent: String, pub parent: String,
exp: usize, pub exp: usize,
access_key: String, 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> { 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 { let Some(mut cred) = get_global_action_cred() else {
return Err(s3_error!(InternalError, "action cred not init")); return Err(s3_error!(InternalError, "action cred not init"));
}; };
let sys_cred = cred.clone();
if cred.access_key != ak { if cred.access_key != ak {
let Ok(iam_store) = iam::get() else { return Err(s3_error!(InternalError, "iam not init")) }; 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 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>>> { pub fn check_claims_from_token(token: &str, cred: &auth::Credentials) -> S3Result<STSClaims> {
// if !token.is_empty() && cred.access_key.is_empty() { if !token.is_empty() && cred.access_key.is_empty() {
// return Err(Error::NoAccessKey); return Err(s3_error!(InvalidRequest, "no access key"));
// } }
// if token.is_empty() && cred.is_temp() && !cred.is_service_account() { if token.is_empty() && cred.is_temp() && !cred.is_service_account() {
// return Err(Error::InvalidToken); return Err(s3_error!(InvalidRequest, "invalid token"));
// } }
// if !token.is_empty() && !cred.is_temp() { if !token.is_empty() && !cred.is_temp() {
// return Err(Error::InvalidToken); return Err(s3_error!(InvalidRequest, "invalid token"));
// } }
// if !cred.is_service_account() && cred.is_temp() && token != cred.session_token { if !cred.is_service_account() && cred.is_temp() && token != cred.session_token {
// return Err(Error::InvalidToken); return Err(s3_error!(InvalidRequest, "invalid token"));
// } }
// if cred.is_temp() || cred.is_expired() { if cred.is_temp() || cred.is_expired() {
// return Err(Error::InvalidAccessKey); 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 {} pub struct AssumeRoleHandle {}
+16 -1
View File
@@ -7,7 +7,10 @@ use serde::Deserialize;
use serde_urlencoded::from_bytes; use serde_urlencoded::from_bytes;
use tracing::warn; use tracing::warn;
use crate::admin::router::Operation; use crate::admin::{
handlers::{check_key_valid, get_session_token},
router::Operation,
};
#[derive(Debug, Deserialize, Default)] #[derive(Debug, Deserialize, Default)]
pub struct AddUserQuery { 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(); let ak = query.access_key.as_deref().unwrap_or_default();
if let Some(sys_cred) = get_global_action_cred() { 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"); warn!("handle AddUser");
return Err(s3_error!(NotImplemented)); return Err(s3_error!(NotImplemented));
} }