mirror of
https://github.com/rustfs/rustfs.git
synced 2026-08-08 22:33:22 +00:00
rewrite service_account handler
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
use crate::error::Error as IamError;
|
||||
use crate::policy::Policy;
|
||||
use crate::sys::Validator;
|
||||
use crate::sys::{iam_policy_claim_name_sa, Validator, INHERITED_POLICY_TYPE};
|
||||
use crate::utils;
|
||||
use crate::utils::extract_claims;
|
||||
use ecstore::error::{Error, Result};
|
||||
@@ -158,6 +158,21 @@ impl Credentials {
|
||||
.unwrap_or_default()
|
||||
}
|
||||
|
||||
pub fn is_implied_policy(&self) -> bool {
|
||||
if self.is_service_account() {
|
||||
return self
|
||||
.claims
|
||||
.as_ref()
|
||||
.map(|x| {
|
||||
x.get(&iam_policy_claim_name_sa())
|
||||
.map_or(false, |v| v == INHERITED_POLICY_TYPE)
|
||||
})
|
||||
.unwrap_or_default();
|
||||
}
|
||||
|
||||
false
|
||||
}
|
||||
|
||||
pub fn is_valid(&self) -> bool {
|
||||
if self.status == "off" {
|
||||
return false;
|
||||
@@ -200,7 +215,7 @@ pub fn create_new_credentials_with_metadata(
|
||||
let expiration = {
|
||||
if let Some(v) = claims.get("exp") {
|
||||
if let Some(expiry) = v.as_i64() {
|
||||
Some(OffsetDateTime::from_unix_timestamp(expiry)?.to_offset(OffsetDateTime::now_local()?.offset()))
|
||||
Some(OffsetDateTime::from_unix_timestamp(expiry)?.to_offset(OffsetDateTime::now_utc().offset()))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
|
||||
@@ -132,3 +132,11 @@ pub fn is_err_no_such_group(err: &ecstore::error::Error) -> bool {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_err_no_such_service_account(err: &ecstore::error::Error) -> bool {
|
||||
if let Some(e) = err.downcast_ref::<Error>() {
|
||||
matches!(e, Error::NoSuchServiceAccount(_))
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
+16
-15
@@ -17,7 +17,7 @@ use ecstore::{
|
||||
error::{Error, Result},
|
||||
};
|
||||
use log::{debug, warn};
|
||||
use madmin::{AccountStatus, GroupDesc};
|
||||
use madmin::{AccountStatus, AddOrUpdateUserReq, GroupDesc};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde_json::Value;
|
||||
use std::{
|
||||
@@ -483,12 +483,12 @@ where
|
||||
let mut cr = ui.credentials.clone();
|
||||
let current_secret_key = cr.secret_key.clone();
|
||||
|
||||
if !opts.secret_key.is_empty() {
|
||||
if !is_secret_key_valid(&opts.secret_key) {
|
||||
if let Some(secret) = opts.secret_key {
|
||||
if !is_secret_key_valid(&secret) {
|
||||
return Err(IamError::InvalidSecretKeyLength.into());
|
||||
}
|
||||
|
||||
cr.secret_key = opts.secret_key;
|
||||
cr.secret_key = secret;
|
||||
}
|
||||
|
||||
if opts.name.is_some() {
|
||||
@@ -554,7 +554,7 @@ where
|
||||
Ok(OffsetDateTime::now_utc())
|
||||
}
|
||||
|
||||
pub async fn policy_db_get(&self, name: &str, groups: &[String]) -> Result<Vec<String>> {
|
||||
pub async fn policy_db_get(&self, name: &str, groups: &Option<Vec<String>>) -> Result<Vec<String>> {
|
||||
if name.is_empty() {
|
||||
return Err(Error::new(IamError::InvalidArgument));
|
||||
}
|
||||
@@ -562,11 +562,13 @@ where
|
||||
let (mut policies, _) = self.policy_db_get_internal(name, false, false).await?;
|
||||
let present = !policies.is_empty();
|
||||
|
||||
for group in groups.iter() {
|
||||
let (gp, _) = self.policy_db_get_internal(group, true, present).await?;
|
||||
gp.iter().for_each(|v| {
|
||||
policies.push(v.clone());
|
||||
});
|
||||
if let Some(groups) = groups {
|
||||
for group in groups.iter() {
|
||||
let (gp, _) = self.policy_db_get_internal(group, true, present).await?;
|
||||
gp.iter().for_each(|v| {
|
||||
policies.push(v.clone());
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Ok(policies)
|
||||
@@ -946,7 +948,7 @@ where
|
||||
m
|
||||
}
|
||||
|
||||
pub async fn add_user(&self, access_key: &str, secret_key: &str, status: &str) -> Result<OffsetDateTime> {
|
||||
pub async fn add_user(&self, access_key: &str, args: &AddOrUpdateUserReq) -> Result<OffsetDateTime> {
|
||||
let users = self.cache.users.load();
|
||||
if let Some(x) = users.get(access_key) {
|
||||
warn!("user already exists: {:?}", x);
|
||||
@@ -956,15 +958,14 @@ where
|
||||
}
|
||||
|
||||
let status = {
|
||||
match status {
|
||||
val if val == AccountStatus::Enabled.as_ref() => auth::ACCOUNT_ON,
|
||||
auth::ACCOUNT_ON => auth::ACCOUNT_ON,
|
||||
match &args.status {
|
||||
AccountStatus::Enabled => auth::ACCOUNT_ON,
|
||||
_ => auth::ACCOUNT_OFF,
|
||||
}
|
||||
};
|
||||
let user_entiry = UserIdentity::from(Credentials {
|
||||
access_key: access_key.to_string(),
|
||||
secret_key: secret_key.to_string(),
|
||||
secret_key: args.secret_key.to_string(),
|
||||
status: status.to_owned(),
|
||||
..Default::default()
|
||||
});
|
||||
|
||||
+13
-11
@@ -27,6 +27,7 @@ use crate::store::UserType;
|
||||
use ecstore::error::{Error, Result};
|
||||
use ecstore::utils::crypto::base64_decode;
|
||||
use ecstore::utils::crypto::base64_encode;
|
||||
use madmin::AddOrUpdateUserReq;
|
||||
use madmin::GroupDesc;
|
||||
use serde_json::json;
|
||||
use serde_json::Value;
|
||||
@@ -178,9 +179,9 @@ impl<T: Store> IamSys<T> {
|
||||
pub async fn new_service_account(
|
||||
&self,
|
||||
parent_user: &str,
|
||||
groups: Vec<String>,
|
||||
groups: Option<Vec<String>>,
|
||||
opts: NewServiceAccountOpts,
|
||||
) -> Result<OffsetDateTime> {
|
||||
) -> Result<(Credentials, OffsetDateTime)> {
|
||||
if parent_user.is_empty() {
|
||||
return Err(IamError::InvalidArgument.into());
|
||||
}
|
||||
@@ -236,14 +237,15 @@ impl<T: Store> IamSys<T> {
|
||||
|
||||
let mut cred = create_new_credentials_with_metadata(&access_key, &secret_key, &m, &secret_key)?;
|
||||
cred.parent_user = parent_user.to_owned();
|
||||
cred.groups = Some(groups);
|
||||
cred.groups = groups;
|
||||
cred.status = ACCOUNT_ON.to_owned();
|
||||
cred.name = opts.name;
|
||||
cred.description = opts.description;
|
||||
cred.expiration = opts.expiration;
|
||||
|
||||
self.store.add_service_account(cred).await
|
||||
let create_at = self.store.add_service_account(cred.clone()).await?;
|
||||
|
||||
Ok((cred, create_at))
|
||||
// TODO: notification
|
||||
}
|
||||
|
||||
@@ -387,7 +389,7 @@ impl<T: Store> IamSys<T> {
|
||||
// TODO: notification
|
||||
}
|
||||
|
||||
pub async fn create_user(&self, access_key: &str, secret_key: &str, status: &str) -> Result<OffsetDateTime> {
|
||||
pub async fn create_user(&self, access_key: &str, args: &AddOrUpdateUserReq) -> Result<OffsetDateTime> {
|
||||
if !is_access_key_valid(access_key) {
|
||||
return Err(IamError::InvalidAccessKeyLength.into());
|
||||
}
|
||||
@@ -396,11 +398,11 @@ impl<T: Store> IamSys<T> {
|
||||
return Err(IamError::ContainsReservedChars.into());
|
||||
}
|
||||
|
||||
if !is_secret_key_valid(secret_key) {
|
||||
if !is_secret_key_valid(&args.secret_key) {
|
||||
return Err(IamError::InvalidSecretKeyLength.into());
|
||||
}
|
||||
|
||||
self.store.add_user(access_key, secret_key, status).await
|
||||
self.store.add_user(access_key, args).await
|
||||
// TODO: notification
|
||||
}
|
||||
|
||||
@@ -470,7 +472,7 @@ impl<T: Store> IamSys<T> {
|
||||
// TODO: notification
|
||||
}
|
||||
|
||||
pub async fn policy_db_get(&self, name: &str, groups: &[String]) -> Result<Vec<String>> {
|
||||
pub async fn policy_db_get(&self, name: &str, groups: &Option<Vec<String>>) -> Result<Vec<String>> {
|
||||
self.store.policy_db_get(name, groups).await
|
||||
}
|
||||
|
||||
@@ -580,7 +582,7 @@ impl<T: Store> IamSys<T> {
|
||||
is_owner || combined_policy.is_allowed(&parent_args)
|
||||
}
|
||||
|
||||
async fn get_combined_policy(&self, policies: &[String]) -> Policy {
|
||||
pub async fn get_combined_policy(&self, policies: &[String]) -> Policy {
|
||||
self.store.merge_policies(&policies.join(",")).await.1
|
||||
}
|
||||
|
||||
@@ -676,7 +678,7 @@ pub struct NewServiceAccountOpts {
|
||||
|
||||
pub struct UpdateServiceAccountOpts {
|
||||
pub session_policy: Option<Policy>,
|
||||
pub secret_key: String,
|
||||
pub secret_key: Option<String>,
|
||||
pub name: Option<String>,
|
||||
pub description: Option<String>,
|
||||
pub expiration: Option<OffsetDateTime>,
|
||||
@@ -702,7 +704,7 @@ pub trait Validator {
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct Args<'a> {
|
||||
pub account: &'a str,
|
||||
pub groups: &'a [String],
|
||||
pub groups: &'a Option<Vec<String>>,
|
||||
pub action: Action,
|
||||
pub bucket: &'a str,
|
||||
pub conditions: &'a HashMap<String, Vec<String>>,
|
||||
|
||||
Reference in New Issue
Block a user