Skip to main content

rc_core/admin/
mod.rs

1//! Admin API module
2//!
3//! This module provides the AdminApi trait and types for managing
4//! IAM users, policies, groups, service accounts, and cluster operations.
5
6mod access_keys;
7mod account;
8mod bucket_metadata;
9mod capabilities;
10mod cluster;
11mod configuration;
12mod diagnostics;
13mod iam;
14mod inspect_archive;
15mod kms;
16mod kms_diagnostic;
17mod observability;
18mod oidc;
19mod on_demand_migration;
20mod replication;
21mod site;
22pub mod tier;
23mod types;
24
25pub use access_keys::{
26    AccessKeyKind, AccessKeyListType, AccessKeyProvider, AccessKeyRecord, BulkAccessKeyApi,
27    BulkAccessKeyQuery, IAM_ACCESS_KEYS_BULK_CAPABILITY, IAM_ACCESS_KEYS_BULK_LDAP_CAPABILITY,
28    IAM_ACCESS_KEYS_BULK_OPENID_CAPABILITY, MAX_IAM_ACCESS_KEY_RESULTS,
29    MAX_IAM_ACCESS_KEY_SELECTOR_BYTES, MAX_IAM_ACCESS_KEY_SELECTORS,
30    MAX_IAM_ACCESS_KEYS_RESPONSE_BYTES,
31};
32pub use account::{
33    ACCOUNT_CAPABILITY, ACCOUNT_MFA_CAPABILITY, AccountApi, AccountInfo, AccountMfaApi,
34    AccountMfaSummary, AccountMutability, CredentialsSource, IdentityType,
35    MAX_ACCOUNT_RESPONSE_BYTES, MfaEnrollment, MfaStatus, PasswordChangeResult, RecoveryCodes,
36    SecretValue, USER_MFA_CAPABILITY, UserCredentialApi, UserMfaStatus,
37};
38pub use bucket_metadata::{
39    BUCKET_METADATA_CAPABILITY, BucketMetadataApi, BucketMetadataArchive,
40    MAX_BUCKET_METADATA_ARCHIVE_BYTES,
41};
42pub use capabilities::{
43    AdvertisedAdminCapability, CapabilityAvailability, CapabilityEntry, CapabilityReport,
44    ClusterSnapshotMetadata, ClusterSnapshotSummary, DiagnosticCapability,
45    DiagnosticCapabilityGuardError, ExtensionMetadata, ExtensionsCatalog,
46    RuntimeCapabilitiesSnapshot, RuntimeCapabilitiesSummary, RuntimeCapabilityState,
47    RuntimeCapabilityStatus,
48};
49pub use cluster::{
50    BackendInfo, BackendType, BackgroundHealCoverage, BucketsInfo, ClusterInfo,
51    DecommissionPoolStatus, DecommissionStatus, DiskInfo, HealDriveInfo, HealDriveInfos,
52    HealResultItem, HealRuntimeState, HealScanMode, HealStartRequest, HealStatus, HealTaskRequest,
53    HealingDiskInfo, MemStats, ObjectsInfo, PoolDecommissionInfo, PoolErasureSetInfo, PoolStatus,
54    PoolTarget, RebalanceCleanupWarnings, RebalancePoolProgress, RebalancePoolStatus,
55    RebalanceStartResult, RebalanceStatus, ServerInfo, UsageInfo,
56};
57pub use configuration::{
58    ConfigApi, ConfigChange, ConfigDiff, ConfigDocument, ConfigHelp, ConfigHelpEntry,
59    ConfigHistoryEntry, ConfigMutationResult, ModuleSwitches, config_document_fields,
60    config_import_diff, config_mutation_diff, redact_config_document, validate_config_directive,
61    validate_config_import,
62};
63pub use diagnostics::{
64    ClientDevnullRequest, ClientDevnullResult, ClusterComponentSnapshot, ClusterComponentSnapshots,
65    ClusterListingSnapshot, ClusterSnapshotDocument, ClusterUsageSnapshot,
66    DEFAULT_CLIENT_DEVNULL_BYTES, DEFAULT_CLIENT_DEVNULL_CONCURRENCY,
67    DEFAULT_CLIENT_DEVNULL_TIMEOUT, DetailedHealthSnapshot, DiagnosticClusterSnapshot,
68    DiagnosticClusterSummary, DiagnosticReadApi, HealthCpuSnapshot, HealthDriveSnapshot,
69    HealthMemorySnapshot, HealthOsSnapshot, HealthProcessSnapshot,
70    MAX_CLIENT_DEVNULL_AGGREGATE_BYTES, MAX_CLIENT_DEVNULL_CONCURRENCY, MAX_CLIENT_DEVNULL_TIMEOUT,
71    MAX_DIAGNOSTIC_RESPONSE_BYTES,
72};
73pub use iam::{
74    GroupPolicyEntities, IAM_POLICY_DETACH_CAPABILITY, IAM_POLICY_ENTITIES_CAPABILITY,
75    IamArchiveApi, IamArchiveImportResult, IamArchiveImportSection, IamArchiveInventory,
76    IamArchiveResultEntities, IamMutationApi, IamReadApi, MAX_IAM_ARCHIVE_BYTES,
77    MAX_IAM_IMPORT_RESPONSE_BYTES, MAX_IAM_POLICY_DETACH_POLICIES,
78    MAX_IAM_POLICY_DETACH_REQUEST_BYTES, MAX_IAM_POLICY_DETACH_RESPONSE_BYTES,
79    MAX_IAM_POLICY_DETACH_SELECTOR_BYTES, MAX_IAM_POLICY_ENTITIES_RESPONSE_BYTES,
80    MAX_IAM_POLICY_ENTITY_SELECTOR_BYTES, MAX_IAM_POLICY_ENTITY_SELECTORS, PolicyDetachEntity,
81    PolicyDetachRequest, PolicyDetachResult, PolicyEntities, PolicyEntitiesQuery,
82    PolicyEntitiesResult, UserPolicyEntities,
83};
84pub use inspect_archive::{
85    EncryptedInspectArchive, INSPECT_ARCHIVE_CAPABILITY, INSPECT_ARCHIVE_COMPLETION,
86    INSPECT_ARCHIVE_CONTENT_TYPE, INSPECT_ARCHIVE_ENCRYPTION, INSPECT_ARCHIVE_ROUTE,
87    INSPECT_ARCHIVE_VERSION, InspectArchiveApi, InspectArchiveCancellation,
88    InspectArchiveCapabilityContract, InspectArchiveKey, InspectArchiveManifest,
89    InspectArchiveTransportRequest, MAX_INSPECT_ARCHIVE_BYTES, MAX_INSPECT_ARCHIVE_DURATION,
90    MAX_INSPECT_ARCHIVE_METADATA_BYTES_PER_DRIVE, PublishedInspectArchive, VerifiedInspectArchive,
91    decrypt_and_validate_inspect_archive, decrypt_and_validate_inspect_archive_with_cancel,
92    publish_inspect_archive, validate_inspect_archive_output_directory,
93};
94pub use kms::{
95    KmsApi, KmsBackendKind, KmsCacheSummary, KmsCancelKeyDeletionResult, KmsConfigSummary,
96    KmsConfigureRequest, KmsCreateKeyRequest, KmsCreateKeyResult, KmsDeleteKeyRequest,
97    KmsDeleteKeyResult, KmsKey, KmsKeyPage, KmsKeyState, KmsKeyUsage, KmsLocalConfigureRequest,
98    KmsServiceState, KmsStatus, KmsVaultAuthMethod, KmsVaultKv2ConfigureRequest,
99    KmsVaultTransitConfigureRequest,
100};
101pub use kms_diagnostic::{
102    KMS_DIAGNOSTIC_CONTENT_BYTES, KmsDiagnosticStore, KmsRoundTripError, KmsRoundTripErrorClass,
103    KmsRoundTripPhase, KmsRoundTripReport, KmsRoundTripTimings, run_kms_round_trip,
104};
105pub use observability::{
106    MAX_METRICS_LINE_BYTES, MAX_METRICS_RESPONSE_BYTES, MAX_METRICS_SAMPLES, MetricGroup,
107    MetricGroups, MetricsBatch, MetricsQuery, MetricsScope, ObservabilityApi, RealtimeMetrics,
108    ScannerCycleSchedule, ScannerFreshness, ScannerHealth, ScannerMetrics, ScannerRuntimeConfig,
109    ScannerRuntimeConfigValue, ScannerStatus, StorageBackend, StorageBackendKind, StorageDisk,
110    StorageDiskMetrics, StorageInfo,
111};
112pub use oidc::{
113    MAX_OIDC_RESPONSE_BYTES, OidcMutationApi, OidcMutationRequest, OidcMutationResult,
114    OidcProvider, OidcProviderList, OidcProviderSource, OidcReadApi, OidcValidationRequest,
115    OidcValidationResult,
116};
117pub use on_demand_migration::{
118    BackfillJob, BackfillJobResult, BackfillLastError, BackfillOwner, BackfillStartRequest,
119    BackfillSummary, BreakerStatus, FilterRequest, FilterView, HeadPolicy, LastSourceError,
120    LatencyBucket, MAX_CONCURRENT_PULLS, MAX_INLINE_MAX_BYTES,
121    MAX_ON_DEMAND_MIGRATION_CA_CERT_BYTES, MAX_ON_DEMAND_MIGRATION_RESPONSE_BYTES,
122    ON_DEMAND_MIGRATION_CAPABILITY, OnDemandMigrationApi, OnDemandMigrationConfigRequest,
123    OnDemandMigrationConfigResult, OnDemandMigrationConfigView, OnDemandMigrationSetResult,
124    OnDemandMigrationStatus, PathStyle, PolicyConfig, ProbeSummary, REDACTED_SECRET,
125    RangeGetPolicy, RuntimeCounters, SkipExisting, SourceCredentialsRequest, SourceCredentialsView,
126    SourceErrorPolicy, SourceLatency, SourceProvider, SourceRequest, SourceTimeout, SourceView,
127    TlsRequest, TlsView, is_terminal_backfill_state, validate_ca_cert_pem, validate_local_bucket,
128};
129pub use replication::{
130    MAX_REPLICATION_DIFF_RESPONSE_BYTES, MAX_REPLICATION_INSPECTION_RESPONSE_BYTES,
131    ReplicationCountSize, ReplicationDiff, ReplicationDiffApi, ReplicationDiffEntry,
132    ReplicationInspectionApi, ReplicationLatencyMetric, ReplicationMetricScope, ReplicationMetrics,
133    ReplicationMrf, ReplicationMrfTarget, ReplicationQueueMetric, ReplicationTargetMetric,
134    ReplicationTransferRate,
135};
136pub use site::{
137    MAX_SITE_REPLICATION_CA_CERT_BYTES, MAX_SITE_REPLICATION_ERROR_RESPONSE_BYTES,
138    MAX_SITE_REPLICATION_REPAIR_RESPONSE_BYTES, MAX_SITE_REPLICATION_REQUEST_BYTES,
139    MAX_SITE_REPLICATION_SUCCESS_RESPONSE_BYTES, PeerSiteSpec, ReplicateEditStatus,
140    SITE_REPLICATION_REPAIR_CAPABILITY, ServiceActionResult, SiteRemoveSpec, SiteReplicationInfo,
141    SiteReplicationPeer, SiteReplicationRepairApi, SiteReplicationRepairCapabilityContract,
142    SiteReplicationRepairFamilyStatus, SiteReplicationRepairOperationStatus,
143    SiteReplicationRepairPreflight, SiteReplicationRepairRequest, SiteReplicationRepairSiteStatus,
144    SiteReplicationRepairTaskStatus, SiteReplicationResyncBucketStatus,
145    SiteReplicationResyncOperation, SiteReplicationResyncStatus, SiteStatusOptions,
146    validate_site_replication_ca_bundle, validate_site_replication_repair_operation_id,
147    validate_site_replication_repair_token,
148};
149pub use tier::{
150    ManualTransitionJobResponse, ManualTransitionQueueSnapshot, ManualTransitionRunReport,
151    ManualTransitionRunRequest, ManualTransitionRunResponse, TierAliyun, TierAzure, TierConfig,
152    TierCreds, TierGCS, TierHuaweicloud, TierMinIO, TierR2, TierRustFS, TierS3, TierTencent,
153    TierType,
154};
155pub use types::{
156    AccessKeyDetails, AccessKeyInfo, BucketQuota, CreateServiceAccountRequest, Group, GroupStatus,
157    LdapAccessKeyInfo, OpenIdAccessKeyInfo, Policy, PolicyEntity, PolicyInfo, ServiceAccount,
158    ServiceAccountCreateResponse, ServiceAccountCredentials, SetPolicyRequest,
159    UpdateGroupMembersRequest, UpdateServiceAccountRequest, User, UserStatus,
160};
161
162use async_trait::async_trait;
163
164use crate::error::Result;
165
166/// Admin API trait for IAM and cluster management operations
167///
168/// This trait defines the interface for managing users, policies, groups,
169/// service accounts, and cluster operations on S3-compatible storage systems
170/// that support the RustFS Admin API.
171#[async_trait]
172pub trait AdminApi: Send + Sync {
173    // ==================== Cluster Operations ====================
174
175    /// Get cluster information including servers, disks, and usage
176    async fn cluster_info(&self) -> Result<ClusterInfo>;
177
178    /// Get current heal status
179    async fn heal_status(&self) -> Result<HealStatus>;
180
181    /// Start a heal operation
182    async fn heal_start(&self, request: HealStartRequest) -> Result<HealStatus>;
183
184    /// Get status for a token-scoped heal task
185    async fn heal_task_status(&self, request: HealTaskRequest) -> Result<HealStatus>;
186
187    /// Stop a running heal operation
188    async fn heal_stop(&self) -> Result<()>;
189
190    /// Stop a token-scoped heal task
191    async fn heal_task_stop(&self, request: HealTaskRequest) -> Result<HealStatus>;
192
193    /// List storage pools
194    async fn list_pools(&self) -> Result<Vec<PoolStatus>>;
195
196    /// Get storage pool status
197    async fn pool_status(&self, target: PoolTarget) -> Result<PoolStatus>;
198
199    /// Start decommissioning one or more storage pools
200    async fn decommission_start(&self, target: PoolTarget) -> Result<()>;
201
202    /// Cancel decommissioning a storage pool
203    async fn decommission_cancel(&self, target: PoolTarget) -> Result<()>;
204
205    /// Clear failed or canceled decommissioning metadata for a storage pool
206    async fn decommission_clear(&self, target: PoolTarget) -> Result<()>;
207
208    /// Get decommissioning status
209    async fn decommission_status(&self, target: Option<PoolTarget>) -> Result<DecommissionStatus>;
210
211    /// Start a rebalance operation
212    async fn rebalance_start(&self) -> Result<RebalanceStartResult>;
213
214    /// Get rebalance status
215    async fn rebalance_status(&self) -> Result<RebalanceStatus>;
216
217    /// Stop a running rebalance operation
218    async fn rebalance_stop(&self) -> Result<()>;
219
220    // ==================== User Operations ====================
221
222    /// List all users
223    async fn list_users(&self) -> Result<Vec<User>>;
224
225    /// Get user information
226    async fn get_user(&self, access_key: &str) -> Result<User>;
227
228    /// Create a new user
229    async fn create_user(&self, access_key: &str, secret_key: &str) -> Result<User>;
230
231    /// Delete a user
232    async fn delete_user(&self, access_key: &str) -> Result<()>;
233
234    /// Set user status (enable/disable)
235    async fn set_user_status(&self, access_key: &str, status: UserStatus) -> Result<()>;
236
237    // ==================== Policy Operations ====================
238
239    /// List all policies
240    async fn list_policies(&self) -> Result<Vec<PolicyInfo>>;
241
242    /// Get policy information
243    async fn get_policy(&self, name: &str) -> Result<Policy>;
244
245    /// Create a new policy
246    async fn create_policy(&self, name: &str, policy_document: &str) -> Result<()>;
247
248    /// Delete a policy
249    async fn delete_policy(&self, name: &str) -> Result<()>;
250
251    /// Attach policy to a user or group
252    async fn attach_policy(
253        &self,
254        policy_names: &[String],
255        entity_type: PolicyEntity,
256        entity_name: &str,
257    ) -> Result<()>;
258
259    /// Detach policy from a user or group
260    async fn detach_policy(
261        &self,
262        policy_names: &[String],
263        entity_type: PolicyEntity,
264        entity_name: &str,
265    ) -> Result<()>;
266
267    // ==================== Group Operations ====================
268
269    /// List all groups
270    async fn list_groups(&self) -> Result<Vec<String>>;
271
272    /// Get group information
273    async fn get_group(&self, name: &str) -> Result<Group>;
274
275    /// Create a new group
276    async fn create_group(&self, name: &str, members: Option<&[String]>) -> Result<Group>;
277
278    /// Delete a group
279    async fn delete_group(&self, name: &str) -> Result<()>;
280
281    /// Set group status (enable/disable)
282    async fn set_group_status(&self, name: &str, status: GroupStatus) -> Result<()>;
283
284    /// Add members to a group
285    async fn add_group_members(&self, group: &str, members: &[String]) -> Result<()>;
286
287    /// Remove members from a group
288    async fn remove_group_members(&self, group: &str, members: &[String]) -> Result<()>;
289
290    // ==================== Service Account Operations ====================
291
292    /// List service accounts for a user
293    async fn list_service_accounts(&self, user: Option<&str>) -> Result<Vec<ServiceAccount>>;
294
295    /// Get service account information
296    async fn get_service_account(&self, access_key: &str) -> Result<ServiceAccount>;
297
298    /// Create a new service account
299    async fn create_service_account(
300        &self,
301        request: CreateServiceAccountRequest,
302    ) -> Result<ServiceAccount>;
303
304    /// Update an existing service account
305    async fn update_service_account(
306        &self,
307        access_key: &str,
308        request: UpdateServiceAccountRequest,
309    ) -> Result<()>;
310
311    /// Delete a service account
312    async fn delete_service_account(&self, access_key: &str) -> Result<()>;
313
314    /// Get information for any access key type.
315    async fn get_access_key_info(&self, access_key: &str) -> Result<AccessKeyInfo>;
316
317    // ==================== Bucket Quota Operations ====================
318
319    /// Set bucket quota in bytes
320    async fn set_bucket_quota(&self, bucket: &str, quota: u64) -> Result<BucketQuota>;
321
322    /// Get bucket quota information
323    async fn get_bucket_quota(&self, bucket: &str) -> Result<BucketQuota>;
324
325    /// Clear bucket quota
326    async fn clear_bucket_quota(&self, bucket: &str) -> Result<BucketQuota>;
327
328    // ==================== Tier Operations ====================
329
330    /// List all configured storage tiers
331    async fn list_tiers(&self) -> Result<Vec<TierConfig>>;
332
333    /// Get tier statistics
334    async fn tier_stats(&self) -> Result<serde_json::Value>;
335
336    /// Add a new storage tier
337    async fn add_tier(&self, config: TierConfig) -> Result<()>;
338
339    /// Edit tier credentials
340    async fn edit_tier(&self, name: &str, creds: TierCreds) -> Result<()>;
341
342    /// Remove a storage tier
343    async fn remove_tier(&self, name: &str, force: bool) -> Result<()>;
344
345    /// Run bounded manual lifecycle transition evaluation for a bucket scope.
346    async fn run_manual_transition(
347        &self,
348        request: ManualTransitionRunRequest,
349    ) -> Result<ManualTransitionRunResponse>;
350
351    /// Start a durable manual lifecycle transition job for a bucket scope.
352    async fn run_manual_transition_async(
353        &self,
354        request: ManualTransitionRunRequest,
355    ) -> Result<ManualTransitionRunResponse>;
356
357    /// Inspect a durable manual lifecycle transition job.
358    async fn manual_transition_job_status(
359        &self,
360        job_id: &str,
361    ) -> Result<ManualTransitionJobResponse>;
362
363    /// Request cancellation for a durable manual lifecycle transition job.
364    async fn cancel_manual_transition_job(
365        &self,
366        job_id: &str,
367    ) -> Result<ManualTransitionJobResponse>;
368
369    // ==================== Replication Target Operations ====================
370
371    /// Set a remote replication target for a bucket, returns the ARN
372    async fn set_remote_target(
373        &self,
374        bucket: &str,
375        target: crate::replication::BucketTarget,
376        update: bool,
377    ) -> Result<String>;
378
379    /// List remote replication targets for a bucket
380    async fn list_remote_targets(
381        &self,
382        bucket: &str,
383    ) -> Result<Vec<crate::replication::BucketTarget>>;
384
385    /// Remove a remote replication target
386    async fn remove_remote_target(&self, bucket: &str, arn: &str) -> Result<()>;
387
388    // ==================== Service Control Operations ====================
389
390    /// Request a service action (restart, stop, freeze, unfreeze)
391    async fn service_action(&self, action: &str) -> Result<ServiceActionResult>;
392
393    // ==================== Site Replication Operations ====================
394
395    /// Get current site replication configuration
396    async fn site_replication_info(&self) -> Result<SiteReplicationInfo>;
397
398    /// Edit a peer using a complete read-modify-write snapshot
399    async fn site_replication_edit(
400        &self,
401        peer: &SiteReplicationPeer,
402    ) -> Result<ReplicateEditStatus>;
403
404    /// Start, inspect, or cancel a resync toward one complete peer snapshot
405    async fn site_replication_resync(
406        &self,
407        operation: SiteReplicationResyncOperation,
408        peer: &SiteReplicationPeer,
409    ) -> Result<SiteReplicationResyncStatus>;
410
411    /// Add peer sites to the site replication cluster
412    async fn site_replication_add(&self, sites: &[PeerSiteSpec]) -> Result<serde_json::Value>;
413
414    /// Get site replication status
415    async fn site_replication_status(
416        &self,
417        options: &SiteStatusOptions,
418    ) -> Result<serde_json::Value>;
419
420    /// Remove sites from the site replication cluster
421    async fn site_replication_remove(&self, spec: &SiteRemoveSpec) -> Result<serde_json::Value>;
422}
423
424/// Read-only RustFS runtime capability discovery.
425#[async_trait]
426pub trait CapabilityApi: Send + Sync {
427    /// Discover capabilities, bypassing the process cache when `refresh` is true.
428    async fn discover_capabilities(&self, refresh: bool) -> Result<CapabilityReport>;
429}
430
431/// Bounded active RustFS diagnostic probes.
432#[async_trait]
433pub trait DiagnosticApi: CapabilityApi {
434    /// Measure client-to-server upload throughput without persisting an object.
435    async fn client_devnull(&self, request: ClientDevnullRequest) -> Result<ClientDevnullResult>;
436}
437
438#[cfg(test)]
439mod tests {
440    use super::*;
441
442    // Test that types are re-exported correctly
443    #[test]
444    fn test_user_status_reexport() {
445        assert_eq!(UserStatus::Enabled.to_string(), "enabled");
446        assert_eq!(UserStatus::Disabled.to_string(), "disabled");
447    }
448
449    #[test]
450    fn test_group_status_reexport() {
451        assert_eq!(GroupStatus::Enabled.to_string(), "enabled");
452        assert_eq!(GroupStatus::Disabled.to_string(), "disabled");
453    }
454
455    #[test]
456    fn test_policy_entity_reexport() {
457        assert_eq!(PolicyEntity::User.to_string(), "user");
458        assert_eq!(PolicyEntity::Group.to_string(), "group");
459    }
460
461    #[test]
462    fn test_user_new() {
463        let user = User::new("testuser");
464        assert_eq!(user.access_key, "testuser");
465        assert_eq!(user.status, UserStatus::Enabled);
466    }
467
468    #[test]
469    fn test_group_new() {
470        let group = Group::new("developers");
471        assert_eq!(group.name, "developers");
472        assert_eq!(group.status, GroupStatus::Enabled);
473    }
474
475    #[test]
476    fn test_policy_new() {
477        let policy = Policy::new("readonly", r#"{"Version":"2012-10-17","Statement":[]}"#);
478        assert_eq!(policy.name, "readonly");
479        assert!(policy.parse_document().is_ok());
480    }
481
482    #[test]
483    fn test_service_account_new() {
484        let sa = ServiceAccount::new("AKIAIOSFODNN7EXAMPLE");
485        assert_eq!(sa.access_key, "AKIAIOSFODNN7EXAMPLE");
486        assert!(sa.secret_key.is_none());
487    }
488}