mirror of
https://github.com/rustfs/rustfs.git
synced 2026-07-28 17:18:58 +00:00
fix(admin): accept IAM service account exports (#2249)
Co-authored-by: houseme <housemecn@gmail.com>
This commit is contained in:
@@ -12,11 +12,12 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use serde::{Deserialize, Deserializer, Serialize, Serializer};
|
||||
use serde::{Deserialize, Deserializer, Serialize, Serializer, de::Error as DeError};
|
||||
use serde_json::Value;
|
||||
use serde_json::value::RawValue;
|
||||
use std::collections::HashMap;
|
||||
use time::OffsetDateTime;
|
||||
use time::format_description::well_known::Rfc3339;
|
||||
|
||||
use crate::BackendInfo;
|
||||
|
||||
@@ -492,6 +493,30 @@ impl<'de> Deserialize<'de> for SRSessionPolicy {
|
||||
}
|
||||
}
|
||||
|
||||
fn deserialize_vec_or_default<'de, D>(deserializer: D) -> Result<Vec<String>, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
Ok(Option::<Vec<String>>::deserialize(deserializer)?.unwrap_or_default())
|
||||
}
|
||||
|
||||
fn deserialize_optional_service_account_expiration<'de, D>(deserializer: D) -> Result<Option<OffsetDateTime>, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
let expiration = Option::<String>::deserialize(deserializer)?;
|
||||
let Some(expiration) = expiration else {
|
||||
return Ok(None);
|
||||
};
|
||||
|
||||
let expiration = OffsetDateTime::parse(&expiration, &Rfc3339).map_err(D::Error::custom)?;
|
||||
if expiration.unix_timestamp() == 0 {
|
||||
return Ok(None);
|
||||
}
|
||||
|
||||
Ok(Some(expiration))
|
||||
}
|
||||
|
||||
/// SRSvcAccCreate - create operation
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct SRSvcAccCreate {
|
||||
@@ -503,6 +528,7 @@ pub struct SRSvcAccCreate {
|
||||
#[serde(rename = "secretKey")]
|
||||
pub secret_key: String,
|
||||
|
||||
#[serde(default, deserialize_with = "deserialize_vec_or_default")]
|
||||
pub groups: Vec<String>,
|
||||
|
||||
pub claims: HashMap<String, serde_json::Value>,
|
||||
@@ -516,7 +542,11 @@ pub struct SRSvcAccCreate {
|
||||
|
||||
pub description: String,
|
||||
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
#[serde(
|
||||
default,
|
||||
skip_serializing_if = "Option::is_none",
|
||||
deserialize_with = "deserialize_optional_service_account_expiration"
|
||||
)]
|
||||
pub expiration: Option<OffsetDateTime>,
|
||||
|
||||
#[serde(rename = "apiVersion", skip_serializing_if = "Option::is_none")]
|
||||
|
||||
@@ -1120,6 +1120,7 @@ mod tests {
|
||||
};
|
||||
use rustfs_credentials::{Credentials, IAM_POLICY_CLAIM_NAME_SA};
|
||||
use rustfs_iam::error::Error as IamError;
|
||||
use rustfs_madmin::user::SRSvcAccCreate;
|
||||
use serde_json::Value;
|
||||
use std::collections::HashMap;
|
||||
|
||||
@@ -1205,6 +1206,57 @@ mod tests {
|
||||
assert!(imported_service_account_status("unknown").is_none());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_service_account_import_accepts_null_groups_and_epoch_expiration() {
|
||||
let payload = r#"{
|
||||
"svcalpha": {
|
||||
"parent": "useralpha",
|
||||
"accessKey": "svcalpha",
|
||||
"secretKey": "svcAlphaSecret123",
|
||||
"groups": null,
|
||||
"claims": {
|
||||
"accessKey": "svcalpha",
|
||||
"parent": "useralpha",
|
||||
"sa-policy": "inherited-policy"
|
||||
},
|
||||
"sessionPolicy": null,
|
||||
"status": "on",
|
||||
"name": "uploaderKey",
|
||||
"description": "alpha upload key",
|
||||
"expiration": "1970-01-01T00:00:00Z"
|
||||
}
|
||||
}"#;
|
||||
|
||||
let svc_accts: HashMap<String, SRSvcAccCreate> = serde_json::from_str(payload).unwrap();
|
||||
let svc = svc_accts.get("svcalpha").unwrap();
|
||||
|
||||
assert!(svc.groups.is_empty());
|
||||
assert!(svc.expiration.is_none());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_service_account_import_preserves_non_zero_expiration() {
|
||||
let payload = r#"{
|
||||
"svcalpha": {
|
||||
"parent": "useralpha",
|
||||
"accessKey": "svcalpha",
|
||||
"secretKey": "svcAlphaSecret123",
|
||||
"groups": [],
|
||||
"claims": {},
|
||||
"sessionPolicy": null,
|
||||
"status": "on",
|
||||
"name": "uploaderKey",
|
||||
"description": "alpha upload key",
|
||||
"expiration": "2030-01-02T03:04:05Z"
|
||||
}
|
||||
}"#;
|
||||
|
||||
let svc_accts: HashMap<String, SRSvcAccCreate> = serde_json::from_str(payload).unwrap();
|
||||
let svc = svc_accts.get("svcalpha").unwrap();
|
||||
|
||||
assert_eq!(svc.expiration.map(|expiration| expiration.unix_timestamp()), Some(1893553445));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_group_policy_mappings_use_regular_user_type() {
|
||||
assert_eq!(GROUP_POLICY_MAPPING_USER_TYPE, rustfs_iam::store::UserType::Reg);
|
||||
|
||||
Reference in New Issue
Block a user