mirror of
https://github.com/rustfs/rustfs.git
synced 2026-08-11 23:56:53 +00:00
AssumeRoleHandle done
This commit is contained in:
@@ -67,6 +67,7 @@ atoi = "2.0.0"
|
||||
serde_urlencoded = "0.7.1"
|
||||
crypto = { path = "../crypto" }
|
||||
iam = { path = "../iam" }
|
||||
jsonwebtoken = "9.3.0"
|
||||
|
||||
[build-dependencies]
|
||||
prost-build.workspace = true
|
||||
|
||||
@@ -20,6 +20,7 @@ use ecstore::GLOBAL_Endpoints;
|
||||
use futures::{Stream, StreamExt};
|
||||
use http::Uri;
|
||||
use hyper::StatusCode;
|
||||
use iam::get_global_action_cred;
|
||||
use madmin::metrics::RealtimeMetrics;
|
||||
use madmin::utils::parse_duration;
|
||||
use matchit::Params;
|
||||
@@ -47,6 +48,9 @@ use tracing::{error, info, warn};
|
||||
pub mod service_account;
|
||||
pub mod trace;
|
||||
|
||||
const ASSUME_ROLE_ACTION: &str = "AssumeRole";
|
||||
const ASSUME_ROLE_VERSION: &str = "2011-06-15";
|
||||
|
||||
#[derive(Deserialize, Debug, Default)]
|
||||
#[serde(rename_all = "PascalCase", default)]
|
||||
pub struct AssumeRoleRequest {
|
||||
@@ -85,13 +89,30 @@ pub struct AssumeRoleRequest {
|
||||
// pub parent_user: String,
|
||||
// }
|
||||
|
||||
#[derive(Debug, Serialize, Default)]
|
||||
pub struct STSClaims {
|
||||
parent: String,
|
||||
exp: usize,
|
||||
access_key: String,
|
||||
}
|
||||
|
||||
fn get_token_signing_key() -> Option<String> {
|
||||
if let Some(s) = get_global_action_cred() {
|
||||
Some(s.secret_key.clone())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub struct AssumeRoleHandle {}
|
||||
#[async_trait::async_trait]
|
||||
impl Operation for AssumeRoleHandle {
|
||||
async fn call(&self, req: S3Request<Body>, _params: Params<'_, '_>) -> S3Result<S3Response<(StatusCode, Body)>> {
|
||||
warn!("handle AssumeRoleHandle");
|
||||
|
||||
let Some(cred) = req.credentials else { return Err(s3_error!(InvalidRequest, "get cred failed")) };
|
||||
let Some(user) = req.credentials else { return Err(s3_error!(InvalidRequest, "get cred failed")) };
|
||||
|
||||
// TODO: 判断权限, 不允许sts访问
|
||||
|
||||
let mut input = req.input;
|
||||
|
||||
@@ -100,17 +121,67 @@ impl Operation for AssumeRoleHandle {
|
||||
};
|
||||
let body: AssumeRoleRequest = from_bytes(&bytes).map_err(|_e| s3_error!(InvalidRequest, "get body failed"))?;
|
||||
|
||||
warn!("AssumeRole get body {:?}", body);
|
||||
if body.action.as_str() != ASSUME_ROLE_ACTION {
|
||||
return Err(s3_error!(InvalidArgument, "not suport action"));
|
||||
}
|
||||
|
||||
let exp = OffsetDateTime::now_utc().saturating_add(Duration::days(1));
|
||||
if body.version.as_str() != ASSUME_ROLE_VERSION {
|
||||
return Err(s3_error!(InvalidArgument, "not suport version"));
|
||||
}
|
||||
|
||||
warn!("AssumeRole get cred {:?}", &user);
|
||||
warn!("AssumeRole get body {:?}", &body);
|
||||
|
||||
let Ok(iam_store) = iam::get() else { return Err(s3_error!(InvalidRequest, "iam not init")) };
|
||||
|
||||
if let Err(_err) = iam_store.policy_db_get(&user.access_key, None).await {
|
||||
return Err(s3_error!(InvalidArgument, "invalid policy arg"));
|
||||
}
|
||||
|
||||
let Some(secret) = get_token_signing_key() else {
|
||||
return Err(s3_error!(InvalidArgument, "sk not init"));
|
||||
};
|
||||
|
||||
let exp = {
|
||||
if body.duration_seconds > 0 {
|
||||
body.duration_seconds
|
||||
} else {
|
||||
3600
|
||||
}
|
||||
};
|
||||
|
||||
let mut claims = STSClaims {
|
||||
parent: user.access_key.clone(),
|
||||
exp,
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
let ak = iam::utils::gen_access_key(20).unwrap_or_default();
|
||||
let sk = iam::utils::gen_secret_key(32).unwrap_or_default();
|
||||
|
||||
claims.access_key = ak.clone();
|
||||
|
||||
let mut cred = match iam::auth::Credentials::create_new_credentials_with_metadata(&ak, &sk, &claims, &secret, Some(exp)) {
|
||||
Ok(res) => res,
|
||||
Err(_er) => return Err(s3_error!(InvalidRequest, "")),
|
||||
};
|
||||
|
||||
cred.parent_user = user.access_key.clone();
|
||||
|
||||
if let Err(err) = iam_store.set_temp_user(&cred.access_key, &cred, "").await {
|
||||
error!("set_temp_user err {:?}", err);
|
||||
return Err(s3_error!(InternalError, "set_temp_user failed"));
|
||||
}
|
||||
|
||||
// TODO: create tmp access_key
|
||||
let resp = AssumeRoleOutput {
|
||||
credentials: Some(Credentials {
|
||||
access_key_id: cred.access_key,
|
||||
expiration: Timestamp::from(exp),
|
||||
secret_access_key: cred.secret_key.expose().to_string(),
|
||||
session_token: "sdfsdf".to_owned(),
|
||||
expiration: Timestamp::from(
|
||||
cred.expiration
|
||||
.unwrap_or(OffsetDateTime::now_utc().saturating_add(Duration::seconds(3600))),
|
||||
),
|
||||
secret_access_key: cred.secret_key,
|
||||
session_token: cred.session_token,
|
||||
}),
|
||||
..Default::default()
|
||||
};
|
||||
@@ -119,8 +190,6 @@ impl Operation for AssumeRoleHandle {
|
||||
let output = xml::serialize::<AssumeRoleOutput>(&resp).unwrap();
|
||||
|
||||
Ok(S3Response::new((StatusCode::OK, Body::from(output))))
|
||||
|
||||
// return Err(s3_error!(NotImplemented));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
use iam::cache::CacheInner;
|
||||
use s3s::auth::S3Auth;
|
||||
use s3s::auth::SecretKey;
|
||||
use s3s::auth::SimpleAuth;
|
||||
use s3s::s3_error;
|
||||
use s3s::S3Result;
|
||||
|
||||
pub struct IAMAuth {
|
||||
simple_auth: SimpleAuth,
|
||||
}
|
||||
|
||||
impl IAMAuth {
|
||||
pub fn new(ak: impl Into<String>, sk: impl Into<SecretKey>) -> Self {
|
||||
let simple_auth = SimpleAuth::from_single(ak, sk);
|
||||
Self { simple_auth }
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl S3Auth for IAMAuth {
|
||||
async fn get_secret_key(&self, access_key: &str) -> S3Result<SecretKey> {
|
||||
if access_key.is_empty() {
|
||||
return Err(s3_error!(NotSignedUp, "Your account is not signed up"));
|
||||
}
|
||||
|
||||
if let Ok(key) = self.simple_auth.get_secret_key(access_key).await {
|
||||
return Ok(key);
|
||||
}
|
||||
|
||||
if let Ok(iam_store) = iam::get() {
|
||||
let c = CacheInner::from(&iam_store.cache);
|
||||
if let Some(id) = c.get_user(access_key) {
|
||||
return Ok(SecretKey::from(id.credentials.secret_key.clone()));
|
||||
}
|
||||
}
|
||||
|
||||
Err(s3_error!(NotSignedUp, "Your account is not signed up2"))
|
||||
}
|
||||
}
|
||||
+7
-3
@@ -1,8 +1,10 @@
|
||||
mod admin;
|
||||
mod auth;
|
||||
mod config;
|
||||
mod grpc;
|
||||
mod service;
|
||||
mod storage;
|
||||
use crate::auth::IAMAuth;
|
||||
use clap::Parser;
|
||||
use common::{
|
||||
error::{Error, Result},
|
||||
@@ -26,7 +28,7 @@ use hyper_util::{
|
||||
};
|
||||
use iam::init_iam_sys;
|
||||
use protos::proto_gen::node_service::node_service_server::NodeServiceServer;
|
||||
use s3s::{auth::SimpleAuth, service::S3ServiceBuilder};
|
||||
use s3s::service::S3ServiceBuilder;
|
||||
use service::hybrid;
|
||||
use std::{io::IsTerminal, net::SocketAddr, str::FromStr};
|
||||
use tokio::net::TcpListener;
|
||||
@@ -87,6 +89,7 @@ async fn run(opt: config::Opt) -> Result<()> {
|
||||
|
||||
debug!("server_address {}", &server_address);
|
||||
|
||||
iam::init_global_action_cred(None, None).unwrap();
|
||||
set_global_rustfs_port(server_port);
|
||||
|
||||
//监听地址,端口从参数中获取
|
||||
@@ -133,7 +136,7 @@ async fn run(opt: config::Opt) -> Result<()> {
|
||||
}
|
||||
//显示info信息
|
||||
info!("authentication is enabled {}, {}", &access_key, &secret_key);
|
||||
b.set_auth(SimpleAuth::from_single(access_key, secret_key));
|
||||
b.set_auth(IAMAuth::new(access_key, secret_key));
|
||||
|
||||
b.set_access(store.clone());
|
||||
|
||||
@@ -212,6 +215,8 @@ async fn run(opt: config::Opt) -> Result<()> {
|
||||
})?;
|
||||
warn!(" init store success!");
|
||||
|
||||
init_iam_sys(store.clone()).await.unwrap();
|
||||
|
||||
new_global_notification_sys(endpoint_pools.clone()).await.map_err(|err| {
|
||||
error!("new_global_notification_sys faild {:?}", &err);
|
||||
Error::from_string(err.to_string())
|
||||
@@ -221,7 +226,6 @@ async fn run(opt: config::Opt) -> Result<()> {
|
||||
init_data_scanner().await;
|
||||
// init auto heal
|
||||
init_auto_heal().await;
|
||||
init_iam_sys(store.clone()).await.unwrap();
|
||||
|
||||
info!("server was started");
|
||||
|
||||
|
||||
Reference in New Issue
Block a user