mirror of
https://github.com/rustfs/rustfs.git
synced 2026-01-17 01:30:33 +00:00
wip
This commit is contained in:
3
.gitignore
vendored
3
.gitignore
vendored
@@ -3,4 +3,5 @@
|
||||
.idea
|
||||
.vscode
|
||||
/test
|
||||
.devcontainer
|
||||
/logs
|
||||
.devcontainer
|
||||
|
||||
475
ecstore/src/bucket/policy/condition/keyname.rs
Normal file
475
ecstore/src/bucket/policy/condition/keyname.rs
Normal file
@@ -0,0 +1,475 @@
|
||||
use core::fmt;
|
||||
use lazy_static::lazy_static;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::str::FromStr;
|
||||
|
||||
use crate::error::Error;
|
||||
|
||||
use super::key::Key;
|
||||
|
||||
// 定义KeyName枚举类型
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
pub enum KeyName {
|
||||
// S3XAmzCopySource - key representing x-amz-copy-source HTTP header applicable to PutObject API only.
|
||||
S3XAmzCopySource, // KeyName = "s3:x-amz-copy-source"
|
||||
|
||||
// S3XAmzServerSideEncryption - key representing x-amz-server-side-encryption HTTP header applicable
|
||||
// to PutObject API only.
|
||||
S3XAmzServerSideEncryption, // KeyName = "s3:x-amz-server-side-encryption"
|
||||
|
||||
// S3XAmzServerSideEncryptionCustomerAlgorithm - key representing
|
||||
// x-amz-server-side-encryption-customer-algorithm HTTP header applicable to PutObject API only.
|
||||
S3XAmzServerSideEncryptionCustomerAlgorithm, // KeyName = "s3:x-amz-server-side-encryption-customer-algorithm"
|
||||
|
||||
// S3XAmzMetadataDirective - key representing x-amz-metadata-directive HTTP header applicable to
|
||||
// PutObject API only.
|
||||
S3XAmzMetadataDirective, // KeyName = "s3:x-amz-metadata-directive"
|
||||
|
||||
// S3XAmzContentSha256 - set a static content-sha256 for all calls for a given action.
|
||||
S3XAmzContentSha256, // KeyName = "s3:x-amz-content-sha256"
|
||||
|
||||
// S3XAmzStorageClass - key representing x-amz-storage-class HTTP header applicable to PutObject API
|
||||
// only.
|
||||
S3XAmzStorageClass, // KeyName = "s3:x-amz-storage-class"
|
||||
|
||||
// S3XAmzServerSideEncryptionAwsKmsKeyID - key representing x-amz-server-side-encryption-aws-kms-key-id
|
||||
// HTTP header for S3 API calls
|
||||
S3XAmzServerSideEncryptionAwsKmsKeyID, // KeyName = "s3:x-amz-server-side-encryption-aws-kms-key-id"
|
||||
|
||||
// S3LocationConstraint - key representing LocationConstraint XML tag of CreateBucket API only.
|
||||
S3LocationConstraint, // KeyName = "s3:LocationConstraint"
|
||||
|
||||
// S3Prefix - key representing prefix query parameter of ListBucket API only.
|
||||
S3Prefix, // KeyName = "s3:prefix"
|
||||
|
||||
// S3Delimiter - key representing delimiter query parameter of ListBucket API only.
|
||||
S3Delimiter, // KeyName = "s3:delimiter"
|
||||
|
||||
// S3VersionID - Enables you to limit the permission for the
|
||||
// s3:PutObjectVersionTagging action to a specific object version.
|
||||
S3VersionID, // KeyName = "s3:versionid"
|
||||
|
||||
// S3MaxKeys - key representing max-keys query parameter of ListBucket API only.
|
||||
S3MaxKeys, // KeyName = "s3:max-keys"
|
||||
|
||||
// S3ObjectLockRemainingRetentionDays - key representing object-lock-remaining-retention-days
|
||||
// Enables enforcement of an object relative to the remaining retention days, you can set
|
||||
// minimum and maximum allowable retention periods for a bucket using a bucket policy.
|
||||
// This key are specific for s3:PutObjectRetention API.
|
||||
S3ObjectLockRemainingRetentionDays, // KeyName = "s3:object-lock-remaining-retention-days"
|
||||
|
||||
// S3ObjectLockMode - key representing object-lock-mode
|
||||
// Enables enforcement of the specified object retention mode
|
||||
S3ObjectLockMode, // KeyName = "s3:object-lock-mode"
|
||||
|
||||
// S3ObjectLockRetainUntilDate - key representing object-lock-retain-util-date
|
||||
// Enables enforcement of a specific retain-until-date
|
||||
S3ObjectLockRetainUntilDate, // KeyName = "s3:object-lock-retain-until-date"
|
||||
|
||||
// S3ObjectLockLegalHold - key representing object-local-legal-hold
|
||||
// Enables enforcement of the specified object legal hold status
|
||||
S3ObjectLockLegalHold, // KeyName = "s3:object-lock-legal-hold"
|
||||
|
||||
// AWSReferer - key representing Referer header of any API.
|
||||
AWSReferer, // KeyName = "aws:Referer"
|
||||
|
||||
// AWSSourceIP - key representing client's IP address (not intermittent proxies) of any API.
|
||||
AWSSourceIP, // KeyName = "aws:SourceIp"
|
||||
|
||||
// AWSUserAgent - key representing UserAgent header for any API.
|
||||
AWSUserAgent, // KeyName = "aws:UserAgent"
|
||||
|
||||
// AWSSecureTransport - key representing if the clients request is authenticated or not.
|
||||
AWSSecureTransport, // KeyName = "aws:SecureTransport"
|
||||
|
||||
// AWSCurrentTime - key representing the current time.
|
||||
AWSCurrentTime, // KeyName = "aws:CurrentTime"
|
||||
|
||||
// AWSEpochTime - key representing the current epoch time.
|
||||
AWSEpochTime, // KeyName = "aws:EpochTime"
|
||||
|
||||
// AWSPrincipalType - user principal type currently supported values are "User" and "Anonymous".
|
||||
AWSPrincipalType, // KeyName = "aws:principaltype"
|
||||
|
||||
// AWSUserID - user unique ID, in RustFS this value is same as your user Access Key.
|
||||
AWSUserID, // KeyName = "aws:userid"
|
||||
|
||||
// AWSUsername - user friendly name, in RustFS this value is same as your user Access Key.
|
||||
AWSUsername, // KeyName = "aws:username"
|
||||
|
||||
// AWSGroups - groups for any authenticating Access Key.
|
||||
AWSGroups, // KeyName = "ss"
|
||||
|
||||
// S3SignatureVersion - identifies the version of AWS Signature that you want to support for authenticated requests.
|
||||
S3SignatureVersion, // KeyName = "s3:signatureversion"
|
||||
|
||||
// S3SignatureAge - identifies the maximum age of presgiend URL allowed
|
||||
S3SignatureAge, // KeyName = "s3:signatureAge"
|
||||
|
||||
// S3AuthType - optionally use this condition key to restrict incoming requests to use a specific authentication method.
|
||||
S3AuthType, // KeyName = "s3:authType"
|
||||
|
||||
// Refer https://docs.aws.amazon.com/AmazonS3/latest/userguide/tagging-and-policies.html
|
||||
ExistingObjectTag, // KeyName = "s3:ExistingObjectTag"
|
||||
RequestObjectTagKeys, // KeyName = "s3:RequestObjectTagKeys"
|
||||
RequestObjectTag, // KeyName = "s3:RequestObjectTag"
|
||||
|
||||
// JWTSub - JWT subject claim substitution.
|
||||
JWTSub, //KeyName = "jwt:sub"
|
||||
|
||||
// JWTIss issuer claim substitution.
|
||||
JWTIss, //KeyName = "jwt:iss"
|
||||
|
||||
// JWTAud audience claim substitution.
|
||||
JWTAud, //KeyName = "jwt:aud"
|
||||
|
||||
// JWTJti JWT unique identifier claim substitution.
|
||||
JWTJti, //KeyName = "jwt:jti"
|
||||
|
||||
JWTUpn, //KeyName = "jwt:upn"
|
||||
JWTName, //KeyName = "jwt:name"
|
||||
JWTGroups, //KeyName = "jwt:groups"
|
||||
JWTGivenName, //KeyName = "jwt:given_name"
|
||||
JWTFamilyName, //KeyName = "jwt:family_name"
|
||||
JWTMiddleName, //KeyName = "jwt:middle_name"
|
||||
JWTNickName, //KeyName = "jwt:nickname"
|
||||
JWTPrefUsername, //KeyName = "jwt:preferred_username"
|
||||
JWTProfile, //KeyName = "jwt:profile"
|
||||
JWTPicture, //KeyName = "jwt:picture"
|
||||
JWTWebsite, //KeyName = "jwt:website"
|
||||
JWTEmail, //KeyName = "jwt:email"
|
||||
JWTGender, //KeyName = "jwt:gender"
|
||||
JWTBirthdate, //KeyName = "jwt:birthdate"
|
||||
JWTPhoneNumber, //KeyName = "jwt:phone_number"
|
||||
JWTAddress, //KeyName = "jwt:address"
|
||||
JWTScope, //KeyName = "jwt:scope"
|
||||
JWTClientID, //KeyName = "jwt:client_id"
|
||||
|
||||
// LDAPUser - LDAP username, this value is equal to your authenticating LDAP user DN.
|
||||
LDAPUser, // KeyName = "ldap:user"
|
||||
|
||||
// LDAPUsername - LDAP username, is the authenticated simple user.
|
||||
LDAPUsername, // KeyName = "ldap:username"
|
||||
|
||||
// LDAPGroups - LDAP groups, this value is equal LDAP Group DNs for the authenticating user.
|
||||
LDAPGroups, // KeyName = "ldap:groups"
|
||||
|
||||
// STSDurationSeconds - Duration seconds condition for STS policy
|
||||
STSDurationSeconds, // KeyName = "sts:DurationSeconds"
|
||||
// SVCDurationSeconds - Duration seconds condition for Admin policy
|
||||
SVCDurationSeconds, // KeyName = "svc:DurationSeconds"
|
||||
|
||||
Undefined,
|
||||
}
|
||||
|
||||
lazy_static! {
|
||||
pub static ref JWTKEYS: Vec<KeyName> = {
|
||||
vec![
|
||||
KeyName::JWTSub,
|
||||
KeyName::JWTIss,
|
||||
KeyName::JWTAud,
|
||||
KeyName::JWTJti,
|
||||
KeyName::JWTName,
|
||||
KeyName::JWTUpn,
|
||||
KeyName::JWTGroups,
|
||||
KeyName::JWTGivenName,
|
||||
KeyName::JWTFamilyName,
|
||||
KeyName::JWTMiddleName,
|
||||
KeyName::JWTNickName,
|
||||
KeyName::JWTPrefUsername,
|
||||
KeyName::JWTProfile,
|
||||
KeyName::JWTPicture,
|
||||
KeyName::JWTWebsite,
|
||||
KeyName::JWTEmail,
|
||||
KeyName::JWTGender,
|
||||
KeyName::JWTBirthdate,
|
||||
KeyName::JWTPhoneNumber,
|
||||
KeyName::JWTAddress,
|
||||
KeyName::JWTScope,
|
||||
KeyName::JWTClientID,
|
||||
]
|
||||
};
|
||||
pub static ref ALL_SUPPORT_KEYS: Vec<KeyName> = {
|
||||
vec![
|
||||
KeyName::S3SignatureVersion,
|
||||
KeyName::S3AuthType,
|
||||
KeyName::S3SignatureAge,
|
||||
KeyName::S3XAmzCopySource,
|
||||
KeyName::S3XAmzServerSideEncryption,
|
||||
KeyName::S3XAmzServerSideEncryptionCustomerAlgorithm,
|
||||
KeyName::S3XAmzMetadataDirective,
|
||||
KeyName::S3XAmzStorageClass,
|
||||
KeyName::S3XAmzServerSideEncryptionAwsKmsKeyID,
|
||||
KeyName::S3XAmzContentSha256,
|
||||
KeyName::S3LocationConstraint,
|
||||
KeyName::S3Prefix,
|
||||
KeyName::S3Delimiter,
|
||||
KeyName::S3MaxKeys,
|
||||
KeyName::S3VersionID,
|
||||
KeyName::S3ObjectLockRemainingRetentionDays,
|
||||
KeyName::S3ObjectLockMode,
|
||||
KeyName::S3ObjectLockLegalHold,
|
||||
KeyName::S3ObjectLockRetainUntilDate,
|
||||
KeyName::AWSReferer,
|
||||
KeyName::AWSSourceIP,
|
||||
KeyName::AWSUserAgent,
|
||||
KeyName::AWSSecureTransport,
|
||||
KeyName::AWSCurrentTime,
|
||||
KeyName::AWSEpochTime,
|
||||
KeyName::AWSPrincipalType,
|
||||
KeyName::AWSUserID,
|
||||
KeyName::AWSUsername,
|
||||
KeyName::AWSGroups,
|
||||
KeyName::LDAPUser,
|
||||
KeyName::LDAPUsername,
|
||||
KeyName::LDAPGroups,
|
||||
KeyName::RequestObjectTag,
|
||||
KeyName::ExistingObjectTag,
|
||||
KeyName::RequestObjectTagKeys,
|
||||
KeyName::JWTSub,
|
||||
KeyName::JWTIss,
|
||||
KeyName::JWTAud,
|
||||
KeyName::JWTJti,
|
||||
KeyName::JWTName,
|
||||
KeyName::JWTUpn,
|
||||
KeyName::JWTGroups,
|
||||
KeyName::JWTGivenName,
|
||||
KeyName::JWTFamilyName,
|
||||
KeyName::JWTMiddleName,
|
||||
KeyName::JWTNickName,
|
||||
KeyName::JWTPrefUsername,
|
||||
KeyName::JWTProfile,
|
||||
KeyName::JWTPicture,
|
||||
KeyName::JWTWebsite,
|
||||
KeyName::JWTEmail,
|
||||
KeyName::JWTGender,
|
||||
KeyName::JWTBirthdate,
|
||||
KeyName::JWTPhoneNumber,
|
||||
KeyName::JWTAddress,
|
||||
KeyName::JWTScope,
|
||||
KeyName::JWTClientID,
|
||||
KeyName::STSDurationSeconds,
|
||||
KeyName::SVCDurationSeconds,
|
||||
]
|
||||
};
|
||||
pub static ref COMMOM_KEYS: Vec<KeyName> = {
|
||||
let mut keys = vec![
|
||||
KeyName::S3SignatureVersion,
|
||||
KeyName::S3AuthType,
|
||||
KeyName::S3SignatureAge,
|
||||
KeyName::S3XAmzContentSha256,
|
||||
KeyName::S3LocationConstraint,
|
||||
KeyName::AWSReferer,
|
||||
KeyName::AWSSourceIP,
|
||||
KeyName::AWSUserAgent,
|
||||
KeyName::AWSSecureTransport,
|
||||
KeyName::AWSCurrentTime,
|
||||
KeyName::AWSEpochTime,
|
||||
KeyName::AWSPrincipalType,
|
||||
KeyName::AWSUserID,
|
||||
KeyName::AWSUsername,
|
||||
KeyName::AWSGroups,
|
||||
KeyName::LDAPUser,
|
||||
KeyName::LDAPUsername,
|
||||
KeyName::LDAPGroups,
|
||||
];
|
||||
|
||||
keys.extend(JWTKEYS.iter().cloned());
|
||||
|
||||
keys
|
||||
};
|
||||
pub static ref ALL_SUPPORT_ADMIN_KEYS: Vec<KeyName> = {
|
||||
let mut keys = vec![
|
||||
KeyName::AWSReferer,
|
||||
KeyName::AWSSourceIP,
|
||||
KeyName::AWSUserAgent,
|
||||
KeyName::AWSSecureTransport,
|
||||
KeyName::AWSCurrentTime,
|
||||
KeyName::AWSEpochTime,
|
||||
KeyName::AWSPrincipalType,
|
||||
KeyName::AWSUserID,
|
||||
KeyName::AWSUsername,
|
||||
KeyName::AWSGroups,
|
||||
KeyName::LDAPUser,
|
||||
KeyName::LDAPUsername,
|
||||
KeyName::LDAPGroups,
|
||||
KeyName::SVCDurationSeconds,
|
||||
];
|
||||
|
||||
keys.extend(JWTKEYS.iter().cloned());
|
||||
|
||||
keys
|
||||
};
|
||||
pub static ref ALL_SUPPORT_STS_KEYS: Vec<KeyName> = vec![KeyName::STSDurationSeconds];
|
||||
}
|
||||
|
||||
// 实现KeyName枚举的方法
|
||||
impl KeyName {
|
||||
pub fn name(&self) -> &str {
|
||||
let name = self.as_str();
|
||||
if name.starts_with("aws:") {
|
||||
name.trim_start_matches("aws:")
|
||||
} else if name.starts_with("jwt:") {
|
||||
name.trim_start_matches("jwt:")
|
||||
} else if name.starts_with("ldap:") {
|
||||
name.trim_start_matches("ldap:")
|
||||
} else if name.starts_with("sts:") {
|
||||
name.trim_start_matches("sts:")
|
||||
} else if name.starts_with("svc:") {
|
||||
name.trim_start_matches("svc:")
|
||||
} else {
|
||||
name.trim_start_matches("s3:")
|
||||
}
|
||||
}
|
||||
|
||||
// Name方法,返回键名的名称
|
||||
pub fn as_str(&self) -> &str {
|
||||
match self {
|
||||
KeyName::S3XAmzCopySource => "s3:x-amz-copy-source",
|
||||
KeyName::S3XAmzServerSideEncryption => "s3:x-amz-server-side-encryption",
|
||||
KeyName::S3XAmzServerSideEncryptionCustomerAlgorithm => "s3:x-amz-server-side-encryption-customer-algorithm",
|
||||
KeyName::S3XAmzMetadataDirective => "s3:x-amz-metadata-directive",
|
||||
KeyName::S3XAmzContentSha256 => "s3:x-amz-content-sha256",
|
||||
KeyName::S3XAmzStorageClass => "s3:x-amz-storage-class",
|
||||
KeyName::S3XAmzServerSideEncryptionAwsKmsKeyID => "s3:x-amz-server-side-encryption-aws-kms-key-id",
|
||||
KeyName::S3LocationConstraint => "s3:LocationConstraint",
|
||||
KeyName::S3Prefix => "s3:prefix",
|
||||
KeyName::S3Delimiter => "s3:delimiter",
|
||||
KeyName::S3VersionID => "s3:versionid",
|
||||
KeyName::S3MaxKeys => "s3:max-keys",
|
||||
KeyName::S3ObjectLockRemainingRetentionDays => "s3:object-lock-remaining-retention-days",
|
||||
KeyName::S3ObjectLockMode => "s3:object-lock-mode",
|
||||
KeyName::S3ObjectLockRetainUntilDate => "s3:object-lock-retain-until-date",
|
||||
KeyName::S3ObjectLockLegalHold => "s3:object-lock-legal-hold",
|
||||
KeyName::AWSReferer => "aws:Referer",
|
||||
KeyName::AWSSourceIP => "aws:SourceIp",
|
||||
KeyName::AWSUserAgent => "aws:UserAgent",
|
||||
KeyName::AWSSecureTransport => "aws:SecureTransport",
|
||||
KeyName::AWSCurrentTime => "aws:CurrentTime",
|
||||
KeyName::AWSEpochTime => "aws:EpochTime",
|
||||
KeyName::AWSPrincipalType => "aws:principaltype",
|
||||
KeyName::AWSUserID => "aws:userid",
|
||||
KeyName::AWSUsername => "aws:username",
|
||||
KeyName::AWSGroups => "ss",
|
||||
KeyName::S3SignatureVersion => "s3:signatureversion",
|
||||
KeyName::S3SignatureAge => "s3:signatureAge",
|
||||
KeyName::S3AuthType => "s3:authType",
|
||||
KeyName::ExistingObjectTag => "s3:ExistingObjectTag",
|
||||
KeyName::RequestObjectTagKeys => "s3:RequestObjectTagKeys",
|
||||
KeyName::RequestObjectTag => "s3:RequestObjectTag",
|
||||
KeyName::JWTSub => "jwt:sub",
|
||||
KeyName::JWTIss => "jwt:iss",
|
||||
KeyName::JWTAud => "jwt:aud",
|
||||
KeyName::JWTJti => "jwt:jti",
|
||||
KeyName::JWTUpn => "jwt:upn",
|
||||
KeyName::JWTName => "jwt:name",
|
||||
KeyName::JWTGroups => "jwt:groups",
|
||||
KeyName::JWTGivenName => "jwt:given_name",
|
||||
KeyName::JWTFamilyName => "jwt:family_name",
|
||||
KeyName::JWTMiddleName => "jwt:middle_name",
|
||||
KeyName::JWTNickName => "jwt:nickname",
|
||||
KeyName::JWTPrefUsername => "jwt:preferred_username",
|
||||
KeyName::JWTProfile => "jwt:profile",
|
||||
KeyName::JWTPicture => "jwt:picture",
|
||||
KeyName::JWTWebsite => "jwt:website",
|
||||
KeyName::JWTEmail => "jwt:email",
|
||||
KeyName::JWTGender => "jwt:gender",
|
||||
KeyName::JWTBirthdate => "jwt:birthdate",
|
||||
KeyName::JWTPhoneNumber => "jwt:phone_number",
|
||||
KeyName::JWTAddress => "jwt:address",
|
||||
KeyName::JWTScope => "jwt:scope",
|
||||
KeyName::JWTClientID => "jwt:client_id",
|
||||
KeyName::LDAPUser => "ldap:user",
|
||||
KeyName::LDAPUsername => "ldap:username",
|
||||
KeyName::LDAPGroups => "ldap:groups",
|
||||
KeyName::STSDurationSeconds => "sts:DurationSeconds",
|
||||
KeyName::SVCDurationSeconds => "svc:DurationSeconds",
|
||||
KeyName::Undefined => "",
|
||||
}
|
||||
}
|
||||
|
||||
// VarName方法,返回变量键名,例如 "${aws:username}"
|
||||
pub fn var_name(&self) -> String {
|
||||
format!("${{{}}}", self.name())
|
||||
}
|
||||
|
||||
// ToKey方法,从名称创建键
|
||||
pub fn to_key(&self) -> Key {
|
||||
Key::new(self.clone(), "".to_string())
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for KeyName {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "{}", self.as_str())
|
||||
}
|
||||
}
|
||||
|
||||
impl FromStr for KeyName {
|
||||
type Err = Error;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
match s {
|
||||
"s3:x-amz-copy-source" => Ok(KeyName::S3XAmzCopySource),
|
||||
"s3:x-amz-server-side-encryption" => Ok(KeyName::S3XAmzServerSideEncryption),
|
||||
"s3:x-amz-server-side-encryption-customer-algorithm" => Ok(KeyName::S3XAmzServerSideEncryptionCustomerAlgorithm),
|
||||
"s3:x-amz-metadata-directive" => Ok(KeyName::S3XAmzMetadataDirective),
|
||||
"s3:x-amz-content-sha256" => Ok(KeyName::S3XAmzContentSha256),
|
||||
"s3:x-amz-storage-class" => Ok(KeyName::S3XAmzStorageClass),
|
||||
"s3:x-amz-server-side-encryption-aws-kms-key-id" => Ok(KeyName::S3XAmzServerSideEncryptionAwsKmsKeyID),
|
||||
"s3:LocationConstraint" => Ok(KeyName::S3LocationConstraint),
|
||||
"s3:prefix" => Ok(KeyName::S3Prefix),
|
||||
"s3:delimiter" => Ok(KeyName::S3Delimiter),
|
||||
"s3:versionid" => Ok(KeyName::S3VersionID),
|
||||
"s3:max-keys" => Ok(KeyName::S3MaxKeys),
|
||||
"s3:object-lock-remaining-retention-days" => Ok(KeyName::S3ObjectLockRemainingRetentionDays),
|
||||
"s3:object-lock-mode" => Ok(KeyName::S3ObjectLockMode),
|
||||
"s3:object-lock-retain-until-date" => Ok(KeyName::S3ObjectLockRetainUntilDate),
|
||||
"s3:object-lock-legal-hold" => Ok(KeyName::S3ObjectLockLegalHold),
|
||||
"aws:Referer" => Ok(KeyName::AWSReferer),
|
||||
"aws:SourceIp" => Ok(KeyName::AWSSourceIP),
|
||||
"aws:UserAgent" => Ok(KeyName::AWSUserAgent),
|
||||
"aws:SecureTransport" => Ok(KeyName::AWSSecureTransport),
|
||||
"aws:CurrentTime" => Ok(KeyName::AWSCurrentTime),
|
||||
"aws:EpochTime" => Ok(KeyName::AWSEpochTime),
|
||||
"aws:principaltype" => Ok(KeyName::AWSPrincipalType),
|
||||
"aws:userid" => Ok(KeyName::AWSUserID),
|
||||
"aws:username" => Ok(KeyName::AWSUsername),
|
||||
"aws:groups" => Ok(KeyName::AWSGroups),
|
||||
"s3:signatureversion" => Ok(KeyName::S3SignatureVersion),
|
||||
"s3:signatureAge" => Ok(KeyName::S3SignatureAge),
|
||||
"s3:authType" => Ok(KeyName::S3AuthType),
|
||||
"s3:ExistingObjectTag" => Ok(KeyName::ExistingObjectTag),
|
||||
"s3:RequestObjectTagKeys" => Ok(KeyName::RequestObjectTagKeys),
|
||||
"s3:RequestObjectTag" => Ok(KeyName::RequestObjectTag),
|
||||
"jwt:sub" => Ok(KeyName::JWTSub),
|
||||
"jwt:iss" => Ok(KeyName::JWTIss),
|
||||
"jwt:aud" => Ok(KeyName::JWTAud),
|
||||
"jwt:jti" => Ok(KeyName::JWTJti),
|
||||
"jwt:upn" => Ok(KeyName::JWTUpn),
|
||||
"jwt:name" => Ok(KeyName::JWTName),
|
||||
"jwt:groups" => Ok(KeyName::JWTGroups),
|
||||
"jwt:given_name" => Ok(KeyName::JWTGivenName),
|
||||
"jwt:family_name" => Ok(KeyName::JWTFamilyName),
|
||||
"jwt:middle_name" => Ok(KeyName::JWTMiddleName),
|
||||
"jwt:nickname" => Ok(KeyName::JWTNickName),
|
||||
"jwt:preferred_username" => Ok(KeyName::JWTPrefUsername),
|
||||
"jwt:profile" => Ok(KeyName::JWTProfile),
|
||||
"jwt:picture" => Ok(KeyName::JWTPicture),
|
||||
"jwt:website" => Ok(KeyName::JWTWebsite),
|
||||
"jwt:email" => Ok(KeyName::JWTEmail),
|
||||
"jwt:gender" => Ok(KeyName::JWTGender),
|
||||
"jwt:birthdate" => Ok(KeyName::JWTBirthdate),
|
||||
"jwt:phone_number" => Ok(KeyName::JWTPhoneNumber),
|
||||
"jwt:address" => Ok(KeyName::JWTAddress),
|
||||
"jwt:scope" => Ok(KeyName::JWTScope),
|
||||
"jwt:client_id" => Ok(KeyName::JWTClientID),
|
||||
"ldap:user" => Ok(KeyName::LDAPUser),
|
||||
"ldap:username" => Ok(KeyName::LDAPUsername),
|
||||
"ldap:groups" => Ok(KeyName::LDAPGroups),
|
||||
"sts:DurationSeconds" => Ok(KeyName::STSDurationSeconds),
|
||||
"svc:DurationSeconds" => Ok(KeyName::SVCDurationSeconds),
|
||||
_ => Err(Error::msg(format!("keyname not found: {}", s))),
|
||||
}
|
||||
}
|
||||
}
|
||||
5044
ecstore/src/set_disk.rs
Normal file
5044
ecstore/src/set_disk.rs
Normal file
File diff suppressed because it is too large
Load Diff
155
iam/src/handler.rs
Normal file
155
iam/src/handler.rs
Normal file
@@ -0,0 +1,155 @@
|
||||
use std::{borrow::Cow, collections::HashMap, f32::NAN};
|
||||
|
||||
use log::{info, warn};
|
||||
use time::OffsetDateTime;
|
||||
|
||||
use crate::{
|
||||
arn::ARN,
|
||||
auth::{Credentials, UserIdentity},
|
||||
cache::{Cache, CacheInner},
|
||||
policy::{utils::get_values_from_claims, Args, MappedPolicy, Policy, UserType},
|
||||
store::Store,
|
||||
Error,
|
||||
};
|
||||
|
||||
pub(crate) struct Handler<'m, T> {
|
||||
cache: CacheInner,
|
||||
api: &'m T,
|
||||
roles: &'m HashMap<ARN, Vec<String>>,
|
||||
}
|
||||
|
||||
impl<'m, T> Handler<'m, T> {
|
||||
pub fn new(cache: CacheInner, api: &'m T, roles: &'m HashMap<ARN, Vec<String>>) -> Self {
|
||||
Self { cache, api, roles }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'m, T> Handler<'m, T>
|
||||
where
|
||||
T: Store,
|
||||
{
|
||||
#[inline]
|
||||
fn get_user<'a>(&self, user_name: &'a str) -> Option<&UserIdentity> {
|
||||
self.cache
|
||||
.users
|
||||
.get(user_name)
|
||||
.or_else(|| self.cache.sts_accounts.get(user_name))
|
||||
}
|
||||
|
||||
async fn get_policy(&self, name: &str, groups: &[String]) -> crate::Result<Vec<String>> {
|
||||
if name.is_empty() {
|
||||
return Err(Error::InvalidArgument);
|
||||
}
|
||||
|
||||
todo!()
|
||||
// self.api.policy_db_get(name, groups)
|
||||
}
|
||||
|
||||
/// 如果是临时用户,返回Ok(Some(partent_name)))
|
||||
/// 如果不是临时用户,返回Ok(None)
|
||||
fn is_temp_user<'a>(&self, user_name: &'a str) -> crate::Result<Option<&str>> {
|
||||
let user = self
|
||||
.get_user(user_name)
|
||||
.ok_or_else(|| Error::NoSuchUser(user_name.to_owned()))?;
|
||||
|
||||
if user.credentials.is_temp() {
|
||||
Ok(Some(&user.credentials.parent_user))
|
||||
} else {
|
||||
Ok(None)
|
||||
}
|
||||
}
|
||||
|
||||
/// 如果是临时用户,返回Ok(Some(partent_name)))
|
||||
/// 如果不是临时用户,返回Ok(None)
|
||||
fn is_service_account<'a>(&self, user_name: &'a str) -> crate::Result<Option<&str>> {
|
||||
let user = self
|
||||
.get_user(user_name)
|
||||
.ok_or_else(|| Error::NoSuchUser(user_name.to_owned()))?;
|
||||
|
||||
if user.credentials.is_service_account() {
|
||||
Ok(Some(&user.credentials.parent_user))
|
||||
} else {
|
||||
Ok(None)
|
||||
}
|
||||
}
|
||||
|
||||
// todo
|
||||
pub fn is_allowed_sts(&self, args: &Args, parent: &str) -> bool {
|
||||
warn!("unimplement is_allowed_sts");
|
||||
false
|
||||
}
|
||||
|
||||
// todo
|
||||
pub async fn is_allowed_service_account<'a>(&self, args: &Args<'a>, parent: &str) -> bool {
|
||||
let Some(p) = args.claims.get(parent) else {
|
||||
return false;
|
||||
};
|
||||
|
||||
if let Some(parent_in_chaim) = p.as_str() {
|
||||
if parent_in_chaim != parent {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
let is_owner_derived = parent == "rustfsadmin"; // todo ,使用全局变量
|
||||
let role_arn = args.get_role_arn();
|
||||
let mut svc_policies = None;
|
||||
|
||||
if is_owner_derived {
|
||||
} else if let Some(x) = role_arn {
|
||||
let Ok(arn) = x.parse::<ARN>() else {
|
||||
info!("error parsing role ARN {x}");
|
||||
return false;
|
||||
};
|
||||
|
||||
svc_policies = self.roles.get(&arn).map(|x| Cow::from(x));
|
||||
} else {
|
||||
let Ok(mut p) = self.get_policy(parent, &args.groups[..]).await else { return false };
|
||||
if p.is_empty() {
|
||||
// todo iamPolicyClaimNameOpenID
|
||||
let (p1, _) = get_values_from_claims(&args.claims, "");
|
||||
p = p1;
|
||||
}
|
||||
svc_policies = Some(Cow::Owned(p));
|
||||
}
|
||||
|
||||
if is_owner_derived && svc_policies.as_ref().map(|x| x.as_ref().len()).unwrap_or_default() == 0 {
|
||||
return false;
|
||||
}
|
||||
|
||||
false
|
||||
}
|
||||
|
||||
pub async fn get_combined_policy(&self, policyes: &[String]) -> Policy {
|
||||
todo!()
|
||||
}
|
||||
|
||||
pub async fn is_allowed<'a>(&self, args: Args<'a>) -> bool {
|
||||
if args.is_owner {
|
||||
return true;
|
||||
}
|
||||
|
||||
match self.is_temp_user(&args.account) {
|
||||
Ok(Some(parent)) => return self.is_allowed_sts(&args, parent),
|
||||
Err(_) => return false,
|
||||
_ => {}
|
||||
}
|
||||
|
||||
match self.is_service_account(&args.account) {
|
||||
Ok(Some(parent)) => return self.is_allowed_service_account(&args, parent).await,
|
||||
Err(_) => return false,
|
||||
_ => {}
|
||||
}
|
||||
|
||||
let Ok(policies) = self.get_policy(&args.account, &args.groups).await else { return false };
|
||||
|
||||
if policies.is_empty() {
|
||||
return false;
|
||||
}
|
||||
|
||||
let policy = self.get_combined_policy(&policies[..]).await;
|
||||
policy.is_allowed(&args)
|
||||
}
|
||||
}
|
||||
129
scripts/test.sh
Normal file
129
scripts/test.sh
Normal file
@@ -0,0 +1,129 @@
|
||||
#!/bin/bash
|
||||
|
||||
mkdir test
|
||||
|
||||
cd test
|
||||
|
||||
# make_bucket
|
||||
mc mb rustfs/mbmb
|
||||
mc ls rustfs
|
||||
mc rb rustfs/mbmb
|
||||
|
||||
mc mb rustfs/rb-force
|
||||
mc ls rustfs
|
||||
echo "123525" >> test.txt
|
||||
mc cp test.txt rustfs/rb-force
|
||||
|
||||
mc rb --force rustfs/rb-force
|
||||
rm test.txt
|
||||
|
||||
|
||||
mc mb rustfs/dada
|
||||
|
||||
echo "123525" >> test.txt
|
||||
mc cp test.txt rustfs/dada
|
||||
|
||||
mc get rustfs/dada/test.txt test2.txt
|
||||
|
||||
diff test.txt test2.txt
|
||||
|
||||
echo "33333" >> test2.txt
|
||||
|
||||
mc cp test2.txt rustfs/dada
|
||||
|
||||
mc get rustfs/dada/test2.txt test3.txt
|
||||
|
||||
diff test2.txt test3.txt
|
||||
|
||||
# list_buckets
|
||||
mc ls rustfs/dada
|
||||
|
||||
mc mb rustfs/dada2
|
||||
|
||||
mc ls rustfs
|
||||
|
||||
mc ls rustfs/dada
|
||||
|
||||
mc rm rustfs/dada/test2.txt
|
||||
|
||||
mc ls rustfs/dada
|
||||
|
||||
dd if=/dev/urandom of=50M.file bs=1M count=50
|
||||
|
||||
mc cp 50M.file rustfs/dada
|
||||
|
||||
mc ls rustfs/dada
|
||||
|
||||
|
||||
mc get rustfs/dada/50M.file 50m.file.d
|
||||
|
||||
diff 50M.file 50m.file.d
|
||||
|
||||
mc rm rustfs/dada/50M.file
|
||||
mc ls rustfs/dada
|
||||
|
||||
rm test.txt test2.txt test3.txt
|
||||
rm 50M.file 50m.file.d
|
||||
|
||||
|
||||
# object_tags
|
||||
echo "33333" >> tags.txt
|
||||
mc cp tags.txt rustfs/dada
|
||||
mc tag list rustfs/dada/tags.txt
|
||||
mc tag set rustfs/dada/tags.txt "key1=value1&key2=value2"
|
||||
mc tag list rustfs/dada/tags.txt
|
||||
mc tag remove rustfs/dada/tags.txt
|
||||
mc tag list rustfs/dada/tags.txt
|
||||
rm tags.txt
|
||||
|
||||
# bucket_tags
|
||||
mc tag list rustfs/dada
|
||||
mc tag set rustfs/dada "a=b&b=c&dada=yes&yy=11&77=99&99=23&11=11"
|
||||
mc tag list rustfs/dada
|
||||
mc tag remove rustfs/dada
|
||||
mc tag list rustfs/dada
|
||||
|
||||
|
||||
# bucket_versioning
|
||||
mc version info rustfs/dada
|
||||
mc version enable rustfs/dada
|
||||
mc version info rustfs/dada
|
||||
mc version suspend rustfs/dada
|
||||
mc version info rustfs/dada
|
||||
|
||||
# bucket_policy
|
||||
mc anonymous get rustfs/dada
|
||||
mc anonymous set public rustfs/dada
|
||||
mc anonymous set upload rustfs/dada
|
||||
mc anonymous set download rustfs/dada
|
||||
mc anonymous list rustfs/dada
|
||||
|
||||
# lifecycle
|
||||
mc ilm ls rustfs/dada
|
||||
mc ilm rule add --expire-days 90 --noncurrent-expire-days 30 rustfs/dada
|
||||
mc ilm ls rustfs/dada
|
||||
|
||||
# bucket_encryption
|
||||
mc encrypt info rustfs/dada
|
||||
mc encrypt set sse-kms rustfs-encryption-key rustfs/dada
|
||||
mc encrypt info rustfs/dada
|
||||
mc encrypt clear rustfs/dada
|
||||
|
||||
# object_lock_config
|
||||
mc mb --with-lock rustfs/lock
|
||||
mc retention info --default rustfs/lock
|
||||
mc retention set --default GOVERNANCE "30d" rustfs/lock
|
||||
mc retention info --default rustfs/lock
|
||||
mc retention clear --default rustfs/lock
|
||||
mc rb rustfs/lock
|
||||
|
||||
# bucket_notification
|
||||
mc event list rustfs/dada
|
||||
mc event add --event "put,delete" rustfs/dada arn:aws:sqs::primary:target
|
||||
mc event list rustfs/dada
|
||||
mc event rm --event "put,delete" rustfs/dada arn:aws:sqs::primary:target
|
||||
mc event list rustfs/dada
|
||||
|
||||
# bucket_quota ? admin/v3/get-bucket-quota
|
||||
# mc quota info rustfs/dada
|
||||
# bucket_target ?
|
||||
Reference in New Issue
Block a user