mirror of
https://github.com/rustfs/rustfs.git
synced 2026-08-06 13:27:43 +00:00
Merge branch 'main' of github.com:rustfs/s3-rustfs into feature/observability-metrics
# Conflicts: # .github/workflows/build.yml # .github/workflows/ci.yml # Cargo.lock # Cargo.toml # appauth/src/token.rs # crates/config/src/config.rs # crates/event-notifier/examples/simple.rs # crates/event-notifier/src/global.rs # crates/event-notifier/src/lib.rs # crates/event-notifier/src/notifier.rs # crates/event-notifier/src/store.rs # crates/filemeta/src/filemeta.rs # crates/notify/examples/webhook.rs # crates/utils/Cargo.toml # ecstore/Cargo.toml # ecstore/src/cmd/bucket_replication.rs # ecstore/src/config/com.rs # ecstore/src/disk/error.rs # ecstore/src/disk/mod.rs # ecstore/src/set_disk.rs # ecstore/src/store_api.rs # ecstore/src/store_list_objects.rs # iam/Cargo.toml # iam/src/manager.rs # policy/Cargo.toml # rustfs/src/admin/rpc.rs # rustfs/src/main.rs # rustfs/src/storage/mod.rs
This commit is contained in:
+9
-9
@@ -1,4 +1,4 @@
|
||||
use common::error::{Error, Result};
|
||||
use crate::error::{Error, Result};
|
||||
use regex::Regex;
|
||||
|
||||
const ARN_PREFIX_ARN: &str = "arn";
|
||||
@@ -19,7 +19,7 @@ impl ARN {
|
||||
pub fn new_iam_role_arn(resource_id: &str, server_region: &str) -> Result<Self> {
|
||||
let valid_resource_id_regex = Regex::new(r"^[A-Za-z0-9_/\.-]+$")?;
|
||||
if !valid_resource_id_regex.is_match(resource_id) {
|
||||
return Err(Error::msg("ARN resource ID invalid"));
|
||||
return Err(Error::other("ARN resource ID invalid"));
|
||||
}
|
||||
Ok(ARN {
|
||||
partition: ARN_PARTITION_RUSTFS.to_string(),
|
||||
@@ -33,33 +33,33 @@ impl ARN {
|
||||
pub fn parse(arn_str: &str) -> Result<Self> {
|
||||
let ps: Vec<&str> = arn_str.split(':').collect();
|
||||
if ps.len() != 6 || ps[0] != ARN_PREFIX_ARN {
|
||||
return Err(Error::msg("ARN format invalid"));
|
||||
return Err(Error::other("ARN format invalid"));
|
||||
}
|
||||
|
||||
if ps[1] != ARN_PARTITION_RUSTFS {
|
||||
return Err(Error::msg("ARN partition invalid"));
|
||||
return Err(Error::other("ARN partition invalid"));
|
||||
}
|
||||
|
||||
if ps[2] != ARN_SERVICE_IAM {
|
||||
return Err(Error::msg("ARN service invalid"));
|
||||
return Err(Error::other("ARN service invalid"));
|
||||
}
|
||||
|
||||
if !ps[4].is_empty() {
|
||||
return Err(Error::msg("ARN account-id invalid"));
|
||||
return Err(Error::other("ARN account-id invalid"));
|
||||
}
|
||||
|
||||
let res: Vec<&str> = ps[5].splitn(2, '/').collect();
|
||||
if res.len() != 2 {
|
||||
return Err(Error::msg("ARN resource invalid"));
|
||||
return Err(Error::other("ARN resource invalid"));
|
||||
}
|
||||
|
||||
if res[0] != ARN_RESOURCE_TYPE_ROLE {
|
||||
return Err(Error::msg("ARN resource type invalid"));
|
||||
return Err(Error::other("ARN resource type invalid"));
|
||||
}
|
||||
|
||||
let valid_resource_id_regex = Regex::new(r"^[A-Za-z0-9_/\.-]+$")?;
|
||||
if !valid_resource_id_regex.is_match(res[1]) {
|
||||
return Err(Error::msg("ARN resource ID invalid"));
|
||||
return Err(Error::other("ARN resource ID invalid"));
|
||||
}
|
||||
|
||||
Ok(ARN {
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
use crate::error::Error as IamError;
|
||||
use crate::policy::{iam_policy_claim_name_sa, Policy, Validator, INHERITED_POLICY_TYPE};
|
||||
use crate::error::{Error, Result};
|
||||
use crate::policy::{INHERITED_POLICY_TYPE, Policy, Validator, iam_policy_claim_name_sa};
|
||||
use crate::utils;
|
||||
use crate::utils::extract_claims;
|
||||
use common::error::{Error, Result};
|
||||
use serde::de::DeserializeOwned;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde_json::{json, Value};
|
||||
use serde_json::{Value, json};
|
||||
use std::collections::HashMap;
|
||||
use time::macros::offset;
|
||||
use time::OffsetDateTime;
|
||||
use time::macros::offset;
|
||||
|
||||
const ACCESS_KEY_MIN_LEN: usize = 3;
|
||||
const ACCESS_KEY_MAX_LEN: usize = 20;
|
||||
@@ -54,41 +54,41 @@ pub fn is_secret_key_valid(secret_key: &str) -> bool {
|
||||
// fn try_from(value: &str) -> Result<Self, Self::Error> {
|
||||
// let mut elem = value.trim().splitn(2, '=');
|
||||
// let (Some(h), Some(cred_elems)) = (elem.next(), elem.next()) else {
|
||||
// return Err(Error::new(IamError::ErrCredMalformed));
|
||||
// return Err(IamError::ErrCredMalformed));
|
||||
// };
|
||||
|
||||
// if h != "Credential" {
|
||||
// return Err(Error::new(IamError::ErrCredMalformed));
|
||||
// return Err(IamError::ErrCredMalformed));
|
||||
// }
|
||||
|
||||
// let mut cred_elems = cred_elems.trim().rsplitn(5, '/');
|
||||
|
||||
// let Some(request) = cred_elems.next() else {
|
||||
// return Err(Error::new(IamError::ErrCredMalformed));
|
||||
// return Err(IamError::ErrCredMalformed));
|
||||
// };
|
||||
|
||||
// let Some(service) = cred_elems.next() else {
|
||||
// return Err(Error::new(IamError::ErrCredMalformed));
|
||||
// return Err(IamError::ErrCredMalformed));
|
||||
// };
|
||||
|
||||
// let Some(region) = cred_elems.next() else {
|
||||
// return Err(Error::new(IamError::ErrCredMalformed));
|
||||
// return Err(IamError::ErrCredMalformed));
|
||||
// };
|
||||
|
||||
// let Some(date) = cred_elems.next() else {
|
||||
// return Err(Error::new(IamError::ErrCredMalformed));
|
||||
// return Err(IamError::ErrCredMalformed));
|
||||
// };
|
||||
|
||||
// let Some(ak) = cred_elems.next() else {
|
||||
// return Err(Error::new(IamError::ErrCredMalformed));
|
||||
// return Err(IamError::ErrCredMalformed));
|
||||
// };
|
||||
|
||||
// if ak.len() < 3 {
|
||||
// return Err(Error::new(IamError::ErrCredMalformed));
|
||||
// return Err(IamError::ErrCredMalformed));
|
||||
// }
|
||||
|
||||
// if request != "aws4_request" {
|
||||
// return Err(Error::new(IamError::ErrCredMalformed));
|
||||
// return Err(IamError::ErrCredMalformed));
|
||||
// }
|
||||
|
||||
// Ok(CredentialHeader {
|
||||
@@ -98,7 +98,7 @@ pub fn is_secret_key_valid(secret_key: &str) -> bool {
|
||||
// const FORMATTER: LazyCell<Vec<BorrowedFormatItem<'static>>> =
|
||||
// LazyCell::new(|| time::format_description::parse("[year][month][day]").unwrap());
|
||||
|
||||
// Date::parse(date, &FORMATTER).map_err(|_| Error::new(IamError::ErrCredMalformed))?
|
||||
// Date::parse(date, &FORMATTER).map_err(|_| IamError::ErrCredMalformed))?
|
||||
// },
|
||||
// region: region.to_owned(),
|
||||
// service: service.try_into()?,
|
||||
@@ -199,11 +199,11 @@ pub fn create_new_credentials_with_metadata(
|
||||
token_secret: &str,
|
||||
) -> Result<Credentials> {
|
||||
if ak.len() < ACCESS_KEY_MIN_LEN || ak.len() > ACCESS_KEY_MAX_LEN {
|
||||
return Err(Error::new(IamError::InvalidAccessKeyLength));
|
||||
return Err(IamError::InvalidAccessKeyLength);
|
||||
}
|
||||
|
||||
if sk.len() < SECRET_KEY_MIN_LEN || sk.len() > SECRET_KEY_MAX_LEN {
|
||||
return Err(Error::new(IamError::InvalidAccessKeyLength));
|
||||
return Err(IamError::InvalidAccessKeyLength);
|
||||
}
|
||||
|
||||
if token_secret.is_empty() {
|
||||
@@ -326,23 +326,23 @@ impl CredentialsBuilder {
|
||||
|
||||
impl TryFrom<CredentialsBuilder> for Credentials {
|
||||
type Error = Error;
|
||||
fn try_from(mut value: CredentialsBuilder) -> Result<Self, Self::Error> {
|
||||
fn try_from(mut value: CredentialsBuilder) -> std::result::Result<Self, Self::Error> {
|
||||
if value.parent_user.is_empty() {
|
||||
return Err(Error::new(IamError::InvalidArgument));
|
||||
return Err(IamError::InvalidArgument);
|
||||
}
|
||||
|
||||
if (value.access_key.is_empty() && !value.secret_key.is_empty())
|
||||
|| (!value.access_key.is_empty() && value.secret_key.is_empty())
|
||||
{
|
||||
return Err(Error::msg("Either ak or sk is empty"));
|
||||
return Err(Error::other("Either ak or sk is empty"));
|
||||
}
|
||||
|
||||
if value.parent_user == value.access_key.as_str() {
|
||||
return Err(Error::new(IamError::InvalidArgument));
|
||||
return Err(IamError::InvalidArgument);
|
||||
}
|
||||
|
||||
if value.access_key == "site-replicator-0" && !value.allow_site_replicator_account {
|
||||
return Err(Error::new(IamError::InvalidArgument));
|
||||
return Err(IamError::InvalidArgument);
|
||||
}
|
||||
|
||||
let mut claim = serde_json::json!({
|
||||
@@ -351,9 +351,9 @@ impl TryFrom<CredentialsBuilder> for Credentials {
|
||||
|
||||
if let Some(p) = value.session_policy {
|
||||
p.is_valid()?;
|
||||
let policy_buf = serde_json::to_vec(&p).map_err(|_| Error::new(IamError::InvalidArgument))?;
|
||||
let policy_buf = serde_json::to_vec(&p).map_err(|_| IamError::InvalidArgument)?;
|
||||
if policy_buf.len() > 4096 {
|
||||
return Err(Error::msg("session policy is too large"));
|
||||
return Err(Error::other("session policy is too large"));
|
||||
}
|
||||
claim["sessionPolicy"] = serde_json::json!(base64_simd::STANDARD.encode_to_string(&policy_buf));
|
||||
claim["sa-policy"] = serde_json::json!("embedded-policy");
|
||||
@@ -390,8 +390,8 @@ impl TryFrom<CredentialsBuilder> for Credentials {
|
||||
};
|
||||
|
||||
if !value.secret_key.is_empty() {
|
||||
let session_token =
|
||||
crypto::jwt_encode(value.access_key.as_bytes(), &claim).map_err(|_| Error::msg("session policy is too large"))?;
|
||||
let session_token = crypto::jwt_encode(value.access_key.as_bytes(), &claim)
|
||||
.map_err(|_| Error::other("session policy is too large"))?;
|
||||
cred.session_token = session_token;
|
||||
// cred.expiration = Some(
|
||||
// OffsetDateTime::from_unix_timestamp(
|
||||
|
||||
+257
-39
@@ -1,13 +1,12 @@
|
||||
use crate::policy;
|
||||
|
||||
pub type Result<T> = core::result::Result<T, Error>;
|
||||
|
||||
#[derive(thiserror::Error, Debug)]
|
||||
pub enum Error {
|
||||
#[error(transparent)]
|
||||
PolicyError(#[from] policy::Error),
|
||||
|
||||
#[error("ecsotre error: {0}")]
|
||||
EcstoreError(common::error::Error),
|
||||
|
||||
#[error("{0}")]
|
||||
StringError(String),
|
||||
|
||||
@@ -66,7 +65,7 @@ pub enum Error {
|
||||
GroupNameContainsReservedChars,
|
||||
|
||||
#[error("jwt err {0}")]
|
||||
JWTError(jsonwebtoken::errors::Error),
|
||||
JWTError(#[from] jsonwebtoken::errors::Error),
|
||||
|
||||
#[error("no access key")]
|
||||
NoAccessKey,
|
||||
@@ -90,56 +89,275 @@ pub enum Error {
|
||||
|
||||
#[error("policy too large")]
|
||||
PolicyTooLarge,
|
||||
|
||||
#[error("io error: {0}")]
|
||||
Io(std::io::Error),
|
||||
}
|
||||
|
||||
impl Error {
|
||||
pub fn other<E>(error: E) -> Self
|
||||
where
|
||||
E: Into<Box<dyn std::error::Error + Send + Sync>>,
|
||||
{
|
||||
Error::Io(std::io::Error::other(error))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<std::io::Error> for Error {
|
||||
fn from(e: std::io::Error) -> Self {
|
||||
Error::Io(e)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<time::error::ComponentRange> for Error {
|
||||
fn from(e: time::error::ComponentRange) -> Self {
|
||||
Error::other(e)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<serde_json::Error> for Error {
|
||||
fn from(e: serde_json::Error) -> Self {
|
||||
Error::other(e)
|
||||
}
|
||||
}
|
||||
|
||||
// impl From<jsonwebtoken::errors::Error> for Error {
|
||||
// fn from(e: jsonwebtoken::errors::Error) -> Self {
|
||||
// Error::JWTError(e)
|
||||
// }
|
||||
// }
|
||||
|
||||
impl From<regex::Error> for Error {
|
||||
fn from(e: regex::Error) -> Self {
|
||||
Error::other(e)
|
||||
}
|
||||
}
|
||||
|
||||
// pub fn is_err_no_such_user(e: &Error) -> bool {
|
||||
// matches!(e, Error::NoSuchUser(_))
|
||||
// }
|
||||
|
||||
pub fn is_err_no_such_policy(err: &common::error::Error) -> bool {
|
||||
if let Some(e) = err.downcast_ref::<Error>() {
|
||||
matches!(e, Error::NoSuchPolicy)
|
||||
} else {
|
||||
false
|
||||
}
|
||||
pub fn is_err_no_such_policy(err: &Error) -> bool {
|
||||
matches!(err, Error::NoSuchPolicy)
|
||||
}
|
||||
|
||||
pub fn is_err_no_such_user(err: &common::error::Error) -> bool {
|
||||
if let Some(e) = err.downcast_ref::<Error>() {
|
||||
matches!(e, Error::NoSuchUser(_))
|
||||
} else {
|
||||
false
|
||||
}
|
||||
pub fn is_err_no_such_user(err: &Error) -> bool {
|
||||
matches!(err, Error::NoSuchUser(_))
|
||||
}
|
||||
|
||||
pub fn is_err_no_such_account(err: &common::error::Error) -> bool {
|
||||
if let Some(e) = err.downcast_ref::<Error>() {
|
||||
matches!(e, Error::NoSuchAccount(_))
|
||||
} else {
|
||||
false
|
||||
}
|
||||
pub fn is_err_no_such_account(err: &Error) -> bool {
|
||||
matches!(err, Error::NoSuchAccount(_))
|
||||
}
|
||||
|
||||
pub fn is_err_no_such_temp_account(err: &common::error::Error) -> bool {
|
||||
if let Some(e) = err.downcast_ref::<Error>() {
|
||||
matches!(e, Error::NoSuchTempAccount(_))
|
||||
} else {
|
||||
false
|
||||
}
|
||||
pub fn is_err_no_such_temp_account(err: &Error) -> bool {
|
||||
matches!(err, Error::NoSuchTempAccount(_))
|
||||
}
|
||||
|
||||
pub fn is_err_no_such_group(err: &common::error::Error) -> bool {
|
||||
if let Some(e) = err.downcast_ref::<Error>() {
|
||||
matches!(e, Error::NoSuchGroup(_))
|
||||
} else {
|
||||
false
|
||||
}
|
||||
pub fn is_err_no_such_group(err: &Error) -> bool {
|
||||
matches!(err, Error::NoSuchGroup(_))
|
||||
}
|
||||
|
||||
pub fn is_err_no_such_service_account(err: &common::error::Error) -> bool {
|
||||
if let Some(e) = err.downcast_ref::<Error>() {
|
||||
matches!(e, Error::NoSuchServiceAccount(_))
|
||||
} else {
|
||||
false
|
||||
pub fn is_err_no_such_service_account(err: &Error) -> bool {
|
||||
matches!(err, Error::NoSuchServiceAccount(_))
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use std::io::{Error as IoError, ErrorKind};
|
||||
|
||||
#[test]
|
||||
fn test_policy_error_from_io_error() {
|
||||
let io_error = IoError::new(ErrorKind::PermissionDenied, "permission denied");
|
||||
let policy_error: Error = io_error.into();
|
||||
|
||||
match policy_error {
|
||||
Error::Io(inner_io) => {
|
||||
assert_eq!(inner_io.kind(), ErrorKind::PermissionDenied);
|
||||
assert!(inner_io.to_string().contains("permission denied"));
|
||||
}
|
||||
_ => panic!("Expected Io variant"),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_policy_error_other_function() {
|
||||
let custom_error = "Custom policy error";
|
||||
let policy_error = Error::other(custom_error);
|
||||
|
||||
match policy_error {
|
||||
Error::Io(io_error) => {
|
||||
assert!(io_error.to_string().contains(custom_error));
|
||||
assert_eq!(io_error.kind(), ErrorKind::Other);
|
||||
}
|
||||
_ => panic!("Expected Io variant"),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_policy_error_from_crypto_error() {
|
||||
// Test conversion from crypto::Error - use an actual variant
|
||||
let crypto_error = crypto::Error::ErrUnexpectedHeader;
|
||||
let policy_error: Error = crypto_error.into();
|
||||
|
||||
match policy_error {
|
||||
Error::CryptoError(_) => {
|
||||
// Verify the conversion worked
|
||||
assert!(policy_error.to_string().contains("crypto"));
|
||||
}
|
||||
_ => panic!("Expected CryptoError variant"),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_policy_error_from_jwt_error() {
|
||||
use jsonwebtoken::{Algorithm, DecodingKey, Validation, decode};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
struct Claims {
|
||||
sub: String,
|
||||
exp: usize,
|
||||
}
|
||||
|
||||
// Create an invalid JWT to generate a JWT error
|
||||
let invalid_token = "invalid.jwt.token";
|
||||
let key = DecodingKey::from_secret(b"secret");
|
||||
let validation = Validation::new(Algorithm::HS256);
|
||||
|
||||
let jwt_result = decode::<Claims>(invalid_token, &key, &validation);
|
||||
assert!(jwt_result.is_err());
|
||||
|
||||
let jwt_error = jwt_result.unwrap_err();
|
||||
let policy_error: Error = jwt_error.into();
|
||||
|
||||
match policy_error {
|
||||
Error::JWTError(_) => {
|
||||
// Verify the conversion worked
|
||||
assert!(policy_error.to_string().contains("jwt err"));
|
||||
}
|
||||
_ => panic!("Expected JWTError variant"),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_policy_error_from_serde_json() {
|
||||
// Test conversion from serde_json::Error
|
||||
let invalid_json = r#"{"invalid": json}"#;
|
||||
let json_error = serde_json::from_str::<serde_json::Value>(invalid_json).unwrap_err();
|
||||
let policy_error: Error = json_error.into();
|
||||
|
||||
match policy_error {
|
||||
Error::Io(io_error) => {
|
||||
assert_eq!(io_error.kind(), ErrorKind::Other);
|
||||
}
|
||||
_ => panic!("Expected Io variant"),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_policy_error_from_time_component_range() {
|
||||
use time::{Date, Month};
|
||||
|
||||
// Create an invalid date to generate a ComponentRange error
|
||||
let time_result = Date::from_calendar_date(2023, Month::January, 32); // Invalid day
|
||||
assert!(time_result.is_err());
|
||||
|
||||
let time_error = time_result.unwrap_err();
|
||||
let policy_error: Error = time_error.into();
|
||||
|
||||
match policy_error {
|
||||
Error::Io(io_error) => {
|
||||
assert_eq!(io_error.kind(), ErrorKind::Other);
|
||||
}
|
||||
_ => panic!("Expected Io variant"),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[allow(clippy::invalid_regex)]
|
||||
fn test_policy_error_from_regex_error() {
|
||||
use regex::Regex;
|
||||
|
||||
// Create an invalid regex to generate a regex error (unclosed bracket)
|
||||
let regex_result = Regex::new("[");
|
||||
assert!(regex_result.is_err());
|
||||
|
||||
let regex_error = regex_result.unwrap_err();
|
||||
let policy_error: Error = regex_error.into();
|
||||
|
||||
match policy_error {
|
||||
Error::Io(io_error) => {
|
||||
assert_eq!(io_error.kind(), ErrorKind::Other);
|
||||
}
|
||||
_ => panic!("Expected Io variant"),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_helper_functions() {
|
||||
// Test helper functions for error type checking
|
||||
assert!(is_err_no_such_policy(&Error::NoSuchPolicy));
|
||||
assert!(!is_err_no_such_policy(&Error::NoSuchUser("test".to_string())));
|
||||
|
||||
assert!(is_err_no_such_user(&Error::NoSuchUser("test".to_string())));
|
||||
assert!(!is_err_no_such_user(&Error::NoSuchAccount("test".to_string())));
|
||||
|
||||
assert!(is_err_no_such_account(&Error::NoSuchAccount("test".to_string())));
|
||||
assert!(!is_err_no_such_account(&Error::NoSuchUser("test".to_string())));
|
||||
|
||||
assert!(is_err_no_such_temp_account(&Error::NoSuchTempAccount("test".to_string())));
|
||||
assert!(!is_err_no_such_temp_account(&Error::NoSuchAccount("test".to_string())));
|
||||
|
||||
assert!(is_err_no_such_group(&Error::NoSuchGroup("test".to_string())));
|
||||
assert!(!is_err_no_such_group(&Error::NoSuchUser("test".to_string())));
|
||||
|
||||
assert!(is_err_no_such_service_account(&Error::NoSuchServiceAccount("test".to_string())));
|
||||
assert!(!is_err_no_such_service_account(&Error::NoSuchAccount("test".to_string())));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_error_display_format() {
|
||||
let test_cases = vec![
|
||||
(Error::NoSuchUser("testuser".to_string()), "user 'testuser' does not exist"),
|
||||
(Error::NoSuchAccount("testaccount".to_string()), "account 'testaccount' does not exist"),
|
||||
(
|
||||
Error::NoSuchServiceAccount("service1".to_string()),
|
||||
"service account 'service1' does not exist",
|
||||
),
|
||||
(Error::NoSuchTempAccount("temp1".to_string()), "temp account 'temp1' does not exist"),
|
||||
(Error::NoSuchGroup("group1".to_string()), "group 'group1' does not exist"),
|
||||
(Error::NoSuchPolicy, "policy does not exist"),
|
||||
(Error::PolicyInUse, "policy in use"),
|
||||
(Error::GroupNotEmpty, "group not empty"),
|
||||
(Error::InvalidArgument, "invalid arguments specified"),
|
||||
(Error::IamSysNotInitialized, "not initialized"),
|
||||
(Error::InvalidServiceType("invalid".to_string()), "invalid service type: invalid"),
|
||||
(Error::ErrCredMalformed, "malformed credential"),
|
||||
(Error::CredNotInitialized, "CredNotInitialized"),
|
||||
(Error::InvalidAccessKeyLength, "invalid access key length"),
|
||||
(Error::InvalidSecretKeyLength, "invalid secret key length"),
|
||||
(Error::ContainsReservedChars, "access key contains reserved characters =,"),
|
||||
(Error::GroupNameContainsReservedChars, "group name contains reserved characters =,"),
|
||||
(Error::NoAccessKey, "no access key"),
|
||||
(Error::InvalidToken, "invalid token"),
|
||||
(Error::InvalidAccessKey, "invalid access_key"),
|
||||
(Error::IAMActionNotAllowed, "action not allowed"),
|
||||
(Error::InvalidExpiration, "invalid expiration"),
|
||||
(Error::NoSecretKeyWithAccessKey, "no secret key with access key"),
|
||||
(Error::NoAccessKeyWithSecretKey, "no access key with secret key"),
|
||||
(Error::PolicyTooLarge, "policy too large"),
|
||||
];
|
||||
|
||||
for (error, expected_message) in test_cases {
|
||||
assert_eq!(error.to_string(), expected_message);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_string_error_variant() {
|
||||
let custom_message = "Custom error message";
|
||||
let error = Error::StringError(custom_message.to_string());
|
||||
assert_eq!(error.to_string(), custom_message);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
use common::error::{Error, Result};
|
||||
use crate::error::{Error, Result};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::{collections::HashSet, ops::Deref};
|
||||
use strum::{EnumString, IntoStaticStr};
|
||||
|
||||
use super::{utils::wildcard, Error as IamError, Validator};
|
||||
use super::{Error as IamError, Validator, utils::wildcard};
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Default, Debug)]
|
||||
pub struct ActionSet(pub HashSet<Action>);
|
||||
@@ -84,7 +84,7 @@ impl Action {
|
||||
|
||||
impl TryFrom<&str> for Action {
|
||||
type Error = Error;
|
||||
fn try_from(value: &str) -> Result<Self, Self::Error> {
|
||||
fn try_from(value: &str) -> std::result::Result<Self, Self::Error> {
|
||||
if value.starts_with(Self::S3_PREFIX) {
|
||||
Ok(Self::S3Action(
|
||||
S3Action::try_from(value).map_err(|_| IamError::InvalidAction(value.into()))?,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use common::error::{Error, Result};
|
||||
use crate::error::{Error, Result};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use strum::{EnumString, IntoStaticStr};
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use crate::policy::function::condition::Condition;
|
||||
use serde::ser::SerializeMap;
|
||||
use serde::{de, Deserialize, Serialize, Serializer};
|
||||
use serde::{Deserialize, Serialize, Serializer, de};
|
||||
use std::collections::HashMap;
|
||||
use std::collections::HashSet;
|
||||
|
||||
@@ -163,12 +163,12 @@ pub struct Value;
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::policy::Functions;
|
||||
use crate::policy::function::condition::Condition::*;
|
||||
use crate::policy::function::func::FuncKeyValue;
|
||||
use crate::policy::function::key::Key;
|
||||
use crate::policy::function::string::StringFunc;
|
||||
use crate::policy::function::string::StringFuncValue;
|
||||
use crate::policy::Functions;
|
||||
use test_case::test_case;
|
||||
|
||||
#[test_case(
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use super::func::InnerFunc;
|
||||
use ipnetwork::IpNetwork;
|
||||
use serde::{de::Visitor, Deserialize, Serialize};
|
||||
use serde::{Deserialize, Serialize, de::Visitor};
|
||||
use std::{borrow::Cow, collections::HashMap, net::IpAddr};
|
||||
|
||||
pub type AddrFunc = InnerFunc<AddrFuncValue>;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use super::func::InnerFunc;
|
||||
use serde::de::{Error, IgnoredAny, SeqAccess};
|
||||
use serde::{de, Deserialize, Deserializer, Serialize};
|
||||
use serde::{Deserialize, Deserializer, Serialize, de};
|
||||
use std::{collections::HashMap, fmt};
|
||||
|
||||
pub type BoolFunc = InnerFunc<BoolFuncValue>;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use serde::Deserialize;
|
||||
use serde::de::{Error, MapAccess};
|
||||
use serde::ser::SerializeMap;
|
||||
use serde::Deserialize;
|
||||
use std::collections::HashMap;
|
||||
use time::OffsetDateTime;
|
||||
|
||||
@@ -122,11 +122,7 @@ impl Condition {
|
||||
DateGreaterThanEquals(s) => s.evaluate(OffsetDateTime::ge, values),
|
||||
};
|
||||
|
||||
if self.is_negate() {
|
||||
!r
|
||||
} else {
|
||||
r
|
||||
}
|
||||
if self.is_negate() { !r } else { r }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use super::func::InnerFunc;
|
||||
use serde::{de, Deserialize, Deserializer, Serialize};
|
||||
use serde::{Deserialize, Deserializer, Serialize, de};
|
||||
use std::{collections::HashMap, fmt};
|
||||
use time::{format_description::well_known::Rfc3339, OffsetDateTime};
|
||||
use time::{OffsetDateTime, format_description::well_known::Rfc3339};
|
||||
|
||||
pub type DateFunc = InnerFunc<DateFuncValue>;
|
||||
|
||||
@@ -82,7 +82,7 @@ mod tests {
|
||||
key_name::S3KeyName::*,
|
||||
};
|
||||
use test_case::test_case;
|
||||
use time::{format_description::well_known::Rfc3339, OffsetDateTime};
|
||||
use time::{OffsetDateTime, format_description::well_known::Rfc3339};
|
||||
|
||||
fn new_func(name: KeyName, variable: Option<String>, value: &str) -> DateFunc {
|
||||
DateFunc {
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
use std::marker::PhantomData;
|
||||
|
||||
use serde::{
|
||||
de::{self, Visitor},
|
||||
Deserialize, Deserializer, Serialize,
|
||||
de::{self, Visitor},
|
||||
};
|
||||
|
||||
use super::key::Key;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use super::key_name::KeyName;
|
||||
use crate::error::Error;
|
||||
use crate::policy::{Error as PolicyError, Validator};
|
||||
use common::error::Error;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
|
||||
|
||||
@@ -2,8 +2,8 @@ use std::collections::HashMap;
|
||||
|
||||
use super::func::InnerFunc;
|
||||
use serde::{
|
||||
de::{Error, Visitor},
|
||||
Deserialize, Deserializer, Serialize,
|
||||
de::{Error, Visitor},
|
||||
};
|
||||
|
||||
pub type NumberFunc = InnerFunc<NumberFuncValue>;
|
||||
|
||||
@@ -7,7 +7,7 @@ use std::{borrow::Cow, collections::HashMap};
|
||||
|
||||
use crate::policy::function::func::FuncKeyValue;
|
||||
use crate::policy::utils::wildcard;
|
||||
use serde::{de, ser::SerializeSeq, Deserialize, Deserializer, Serialize};
|
||||
use serde::{Deserialize, Deserializer, Serialize, de, ser::SerializeSeq};
|
||||
|
||||
use super::{func::InnerFunc, key_name::KeyName};
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use common::error::{Error, Result};
|
||||
use crate::error::{Error, Result};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::ops::Deref;
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use super::{action::Action, statement::BPStatement, Effect, Error as IamError, Statement, ID};
|
||||
use common::error::{Error, Result};
|
||||
use super::{Effect, Error as IamError, ID, Statement, action::Action, statement::BPStatement};
|
||||
use crate::error::{Error, Result};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde_json::Value;
|
||||
use std::collections::{HashMap, HashSet};
|
||||
@@ -252,9 +252,9 @@ pub mod default {
|
||||
use std::{collections::HashSet, sync::LazyLock};
|
||||
|
||||
use crate::policy::{
|
||||
ActionSet, DEFAULT_VERSION, Effect, Functions, ResourceSet, Statement,
|
||||
action::{Action, AdminAction, KmsAction, S3Action},
|
||||
resource::Resource,
|
||||
ActionSet, Effect, Functions, ResourceSet, Statement, DEFAULT_VERSION,
|
||||
};
|
||||
|
||||
use super::Policy;
|
||||
@@ -449,7 +449,7 @@ pub mod default {
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
use common::error::Result;
|
||||
use crate::error::Result;
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_parse_policy() -> Result<()> {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use super::{utils::wildcard, Validator};
|
||||
use common::error::{Error, Result};
|
||||
use super::{Validator, utils::wildcard};
|
||||
use crate::error::{Error, Result};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::collections::HashSet;
|
||||
|
||||
@@ -25,7 +25,7 @@ impl Validator for Principal {
|
||||
type Error = Error;
|
||||
fn is_valid(&self) -> Result<()> {
|
||||
if self.aws.is_empty() {
|
||||
return Err(Error::msg("Principal is empty"));
|
||||
return Err(Error::other("Principal is empty"));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use common::error::{Error, Result};
|
||||
use crate::error::{Error, Result};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::{
|
||||
collections::{HashMap, HashSet},
|
||||
@@ -7,9 +7,9 @@ use std::{
|
||||
};
|
||||
|
||||
use super::{
|
||||
Error as IamError, Validator,
|
||||
function::key_name::KeyName,
|
||||
utils::{path, wildcard},
|
||||
Error as IamError, Validator,
|
||||
};
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Default, Debug)]
|
||||
@@ -101,7 +101,7 @@ impl Resource {
|
||||
|
||||
impl TryFrom<&str> for Resource {
|
||||
type Error = Error;
|
||||
fn try_from(value: &str) -> Result<Self, Self::Error> {
|
||||
fn try_from(value: &str) -> std::result::Result<Self, Self::Error> {
|
||||
let resource = if value.starts_with(Self::S3_PREFIX) {
|
||||
Resource::S3(value.strip_prefix(Self::S3_PREFIX).unwrap().into())
|
||||
} else {
|
||||
@@ -115,7 +115,7 @@ impl TryFrom<&str> for Resource {
|
||||
|
||||
impl Validator for Resource {
|
||||
type Error = Error;
|
||||
fn is_valid(&self) -> Result<(), Error> {
|
||||
fn is_valid(&self) -> std::result::Result<(), Error> {
|
||||
match self {
|
||||
Self::S3(pattern) => {
|
||||
if pattern.is_empty() || pattern.starts_with('/') {
|
||||
@@ -139,7 +139,7 @@ impl Validator for Resource {
|
||||
}
|
||||
|
||||
impl Serialize for Resource {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
|
||||
where
|
||||
S: serde::Serializer,
|
||||
{
|
||||
@@ -151,7 +151,7 @@ impl Serialize for Resource {
|
||||
}
|
||||
|
||||
impl<'de> Deserialize<'de> for Resource {
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
|
||||
where
|
||||
D: serde::Deserializer<'de>,
|
||||
{
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
use super::{
|
||||
action::Action, ActionSet, Args, BucketPolicyArgs, Effect, Error as IamError, Functions, Principal, ResourceSet, Validator,
|
||||
ID,
|
||||
ActionSet, Args, BucketPolicyArgs, Effect, Error as IamError, Functions, ID, Principal, ResourceSet, Validator,
|
||||
action::Action,
|
||||
};
|
||||
use common::error::{Error, Result};
|
||||
use crate::error::{Error, Result};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Default, Debug)]
|
||||
|
||||
@@ -85,11 +85,7 @@ pub fn clean(path: &str) -> String {
|
||||
}
|
||||
}
|
||||
|
||||
if out.w == 0 {
|
||||
".".into()
|
||||
} else {
|
||||
out.string()
|
||||
}
|
||||
if out.w == 0 { ".".into() } else { out.string() }
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
||||
+6
-6
@@ -1,7 +1,7 @@
|
||||
use common::error::{Error, Result};
|
||||
use jsonwebtoken::{Algorithm, DecodingKey, EncodingKey, Header};
|
||||
use rand::{Rng, RngCore};
|
||||
use serde::{de::DeserializeOwned, Serialize};
|
||||
use serde::{Serialize, de::DeserializeOwned};
|
||||
use std::io::{Error, Result};
|
||||
|
||||
pub fn gen_access_key(length: usize) -> Result<String> {
|
||||
const ALPHA_NUMERIC_TABLE: [char; 36] = [
|
||||
@@ -10,7 +10,7 @@ pub fn gen_access_key(length: usize) -> Result<String> {
|
||||
];
|
||||
|
||||
if length < 3 {
|
||||
return Err(Error::msg("access key length is too short"));
|
||||
return Err(Error::other("access key length is too short"));
|
||||
}
|
||||
|
||||
let mut result = String::with_capacity(length);
|
||||
@@ -27,7 +27,7 @@ pub fn gen_secret_key(length: usize) -> Result<String> {
|
||||
use base64_simd::URL_SAFE_NO_PAD;
|
||||
|
||||
if length < 8 {
|
||||
return Err(Error::msg("secret key length is too short"));
|
||||
return Err(Error::other("secret key length is too short"));
|
||||
}
|
||||
let mut rng = rand::rng();
|
||||
|
||||
@@ -40,7 +40,7 @@ pub fn gen_secret_key(length: usize) -> Result<String> {
|
||||
Ok(key_str)
|
||||
}
|
||||
|
||||
pub fn generate_jwt<T: Serialize>(claims: &T, secret: &str) -> Result<String, jsonwebtoken::errors::Error> {
|
||||
pub fn generate_jwt<T: Serialize>(claims: &T, secret: &str) -> std::result::Result<String, jsonwebtoken::errors::Error> {
|
||||
let header = Header::new(Algorithm::HS512);
|
||||
jsonwebtoken::encode(&header, &claims, &EncodingKey::from_secret(secret.as_bytes()))
|
||||
}
|
||||
@@ -48,7 +48,7 @@ pub fn generate_jwt<T: Serialize>(claims: &T, secret: &str) -> Result<String, js
|
||||
pub fn extract_claims<T: DeserializeOwned>(
|
||||
token: &str,
|
||||
secret: &str,
|
||||
) -> Result<jsonwebtoken::TokenData<T>, jsonwebtoken::errors::Error> {
|
||||
) -> std::result::Result<jsonwebtoken::TokenData<T>, jsonwebtoken::errors::Error> {
|
||||
jsonwebtoken::decode::<T>(
|
||||
token,
|
||||
&DecodingKey::from_secret(secret.as_bytes()),
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use policy::policy::action::Action;
|
||||
use policy::policy::action::S3Action::*;
|
||||
use policy::policy::ActionSet;
|
||||
use policy::policy::Effect::*;
|
||||
use policy::policy::action::Action;
|
||||
use policy::policy::action::S3Action::*;
|
||||
use policy::policy::*;
|
||||
use serde_json::Value;
|
||||
use std::collections::HashMap;
|
||||
|
||||
Reference in New Issue
Block a user