fix(bucket-tenants): make tenant lifecycle and bucket import validation safer

This commit is contained in:
2026-05-02 12:09:13 +00:00
parent 7020810b5e
commit b075de1ecd
23 changed files with 435 additions and 183 deletions
+47 -11
View File
@@ -195,11 +195,27 @@ impl StorageServer {
credential: Credential,
) -> Result<Credential> {
self.ensure_tenant_auth_enabled()?;
self.store.create_bucket(bucket_name).await?;
Ok(self
let replacement = self
.auth_runtime
.replace_bucket_tenant_credential(bucket_name, credential)
.await?)
.replace_bucket_tenant_credential_with_snapshot(bucket_name, credential)
.await?;
if let Err(error) = self.store.create_bucket(bucket_name).await {
if let Err(rollback_error) = self
.auth_runtime
.replace_credentials(replacement.previous_credentials)
.await
{
return Err(anyhow::anyhow!(
"Failed to create tenant bucket: {}; credential rollback failed: {}",
error,
rollback_error.message
));
}
return Err(error);
}
Ok(replacement.credential)
}
pub async fn rotate_bucket_tenant_credentials(
@@ -223,23 +239,43 @@ impl StorageServer {
access_key_id: Option<&str>,
) -> Result<()> {
self.ensure_tenant_auth_enabled()?;
self.auth_runtime
let removal = self
.auth_runtime
.remove_bucket_tenant_credentials(bucket_name, access_key_id)
.await?;
if access_key_id.is_none() && self.store.bucket_exists(bucket_name).await {
self.store.delete_bucket_recursive(bucket_name).await?;
if let Err(error) = self.store.delete_bucket_recursive(bucket_name).await {
if let Err(rollback_error) = self
.auth_runtime
.replace_credentials(removal.previous_credentials)
.await
{
return Err(anyhow::anyhow!(
"Failed to delete tenant bucket: {}; credential rollback failed: {}",
error,
rollback_error.message
));
}
return Err(error);
}
}
Ok(())
}
pub async fn list_bucket_tenants(&self) -> Vec<crate::auth::BucketTenantMetadata> {
self.auth_runtime.list_bucket_tenants().await
pub async fn list_bucket_tenants(&self) -> Result<Vec<crate::auth::BucketTenantMetadata>> {
self.ensure_tenant_auth_enabled()?;
Ok(self.auth_runtime.list_bucket_tenants().await)
}
pub async fn get_bucket_tenant_credential(&self, bucket_name: &str) -> Option<Credential> {
self.auth_runtime
pub async fn get_bucket_tenant_credential(
&self,
bucket_name: &str,
) -> Result<Option<Credential>> {
self.ensure_tenant_auth_enabled()?;
Ok(self
.auth_runtime
.get_bucket_tenant_credential(bucket_name)
.await
.await)
}
fn ensure_tenant_auth_enabled(&self) -> Result<()> {