bucketwarden-server 0.1.0

BucketWarden storage server runtime.
Documentation
use super::*;
mod bucket_metadata_helpers;

use bucket_metadata_helpers::*;

const METADATA_TABLE_NAMESPACE: &str = "aws_s3_metadata";

impl BucketWarden {
    pub fn create_bucket_metadata_configuration(
        &mut self,
        principal: &str,
        bucket: &str,
        mut configuration: BucketMetadataConfiguration,
    ) -> Result<(), RuntimeError> {
        self.authorize(
            principal,
            S3Action::CreateBucketMetadataConfiguration,
            bucket,
        )?;
        validate_bucket_metadata_configuration(&configuration)?;
        configuration.bucket = bucket.to_string();
        let bucket_state = self.require_bucket_mut(bucket)?;
        bucket_state.metadata_table_configuration = None;
        bucket_state.metadata_configuration = Some(configuration.clone());
        self.audit_allowed(
            principal,
            S3Action::CreateBucketMetadataConfiguration,
            bucket,
            Some(metadata_configuration_audit_detail(&configuration)),
        );
        Ok(())
    }

    pub fn get_bucket_metadata_configuration(
        &mut self,
        principal: &str,
        bucket: &str,
    ) -> Result<MetadataConfigurationResult, RuntimeError> {
        self.authorize(principal, S3Action::GetBucketMetadataConfiguration, bucket)?;
        let bucket_state = self.require_bucket(bucket)?;
        let result = if let Some(configuration) = bucket_state.metadata_configuration.clone() {
            synthesize_metadata_configuration_result(&configuration)
        } else if let Some(configuration) = bucket_state.metadata_table_configuration.clone() {
            synthesize_v2_result_from_v1(&configuration)
        } else {
            return Err(RuntimeError::NoSuchBucketMetadataConfiguration(
                bucket.to_string(),
            ));
        };
        self.audit_allowed(
            principal,
            S3Action::GetBucketMetadataConfiguration,
            bucket,
            Some("compatible metadata configuration read".to_string()),
        );
        Ok(result)
    }

    pub fn delete_bucket_metadata_configuration(
        &mut self,
        principal: &str,
        bucket: &str,
    ) -> Result<(), RuntimeError> {
        self.authorize(
            principal,
            S3Action::DeleteBucketMetadataConfiguration,
            bucket,
        )?;
        let bucket_state = self.require_bucket_mut(bucket)?;
        bucket_state.metadata_configuration = None;
        bucket_state.metadata_table_configuration = None;
        self.audit_allowed(
            principal,
            S3Action::DeleteBucketMetadataConfiguration,
            bucket,
            None,
        );
        Ok(())
    }

    pub fn update_bucket_metadata_journal_table_configuration(
        &mut self,
        principal: &str,
        bucket: &str,
        journal_table_configuration: JournalTableConfiguration,
    ) -> Result<MetadataConfigurationResult, RuntimeError> {
        self.authorize(
            principal,
            S3Action::UpdateBucketMetadataJournalTableConfiguration,
            bucket,
        )?;
        validate_metadata_table_encryption(
            journal_table_configuration
                .encryption_configuration
                .as_ref(),
        )?;
        validate_record_expiration(&journal_table_configuration.record_expiration)?;
        let bucket_state = self.require_bucket_mut(bucket)?;
        let configuration = bucket_state
            .metadata_configuration
            .as_mut()
            .ok_or_else(|| RuntimeError::NoSuchBucketMetadataConfiguration(bucket.to_string()))?;
        configuration.journal_table_configuration = journal_table_configuration;
        let configuration = configuration.clone();
        self.audit_allowed(
            principal,
            S3Action::UpdateBucketMetadataJournalTableConfiguration,
            bucket,
            Some(metadata_configuration_audit_detail(&configuration)),
        );
        Ok(synthesize_metadata_configuration_result(&configuration))
    }

    pub fn update_bucket_metadata_inventory_table_configuration(
        &mut self,
        principal: &str,
        bucket: &str,
        inventory_table_configuration: InventoryTableConfiguration,
    ) -> Result<MetadataConfigurationResult, RuntimeError> {
        self.authorize(
            principal,
            S3Action::UpdateBucketMetadataInventoryTableConfiguration,
            bucket,
        )?;
        validate_metadata_table_encryption(
            inventory_table_configuration
                .encryption_configuration
                .as_ref(),
        )?;
        match inventory_table_configuration.configuration_state.as_str() {
            "ENABLED" | "DISABLED" => {}
            other => {
                return Err(RuntimeError::InvalidBucketMetadataConfiguration(format!(
                    "invalid inventory configuration state: {other}"
                )))
            }
        }
        let bucket_state = self.require_bucket_mut(bucket)?;
        let configuration = bucket_state
            .metadata_configuration
            .as_mut()
            .ok_or_else(|| RuntimeError::NoSuchBucketMetadataConfiguration(bucket.to_string()))?;
        configuration.inventory_table_configuration = Some(inventory_table_configuration);
        let configuration = configuration.clone();
        self.audit_allowed(
            principal,
            S3Action::UpdateBucketMetadataInventoryTableConfiguration,
            bucket,
            Some(metadata_configuration_audit_detail(&configuration)),
        );
        Ok(synthesize_metadata_configuration_result(&configuration))
    }

    pub fn create_bucket_metadata_table_configuration(
        &mut self,
        principal: &str,
        bucket: &str,
        mut configuration: BucketMetadataTableConfiguration,
    ) -> Result<(), RuntimeError> {
        self.authorize(
            principal,
            S3Action::CreateBucketMetadataTableConfiguration,
            bucket,
        )?;
        validate_bucket_metadata_table_configuration(&configuration)?;
        let bucket_state = self.require_bucket_mut(bucket)?;
        if bucket_state.metadata_configuration.is_some() {
            return Err(RuntimeError::BucketMetadataTableApiNotAvailable(
                bucket.to_string(),
            ));
        }
        configuration.bucket = bucket.to_string();
        bucket_state.metadata_table_configuration = Some(configuration.clone());
        self.audit_allowed(
            principal,
            S3Action::CreateBucketMetadataTableConfiguration,
            bucket,
            Some(metadata_table_configuration_audit_detail(&configuration)),
        );
        Ok(())
    }

    pub fn get_bucket_metadata_table_configuration(
        &mut self,
        principal: &str,
        bucket: &str,
    ) -> Result<GetBucketMetadataTableConfigurationResult, RuntimeError> {
        self.authorize(
            principal,
            S3Action::GetBucketMetadataTableConfiguration,
            bucket,
        )?;
        let bucket_state = self.require_bucket(bucket)?;
        if bucket_state.metadata_configuration.is_some() {
            return Err(RuntimeError::BucketMetadataTableApiNotAvailable(
                bucket.to_string(),
            ));
        }
        let configuration = bucket_state
            .metadata_table_configuration
            .clone()
            .ok_or_else(|| {
                RuntimeError::NoSuchBucketMetadataTableConfiguration(bucket.to_string())
            })?;
        let result = synthesize_metadata_table_configuration_result(&configuration);
        self.audit_allowed(
            principal,
            S3Action::GetBucketMetadataTableConfiguration,
            bucket,
            Some(metadata_table_configuration_audit_detail(&configuration)),
        );
        Ok(result)
    }

    pub fn delete_bucket_metadata_table_configuration(
        &mut self,
        principal: &str,
        bucket: &str,
    ) -> Result<(), RuntimeError> {
        self.authorize(
            principal,
            S3Action::DeleteBucketMetadataTableConfiguration,
            bucket,
        )?;
        let bucket_state = self.require_bucket_mut(bucket)?;
        if bucket_state.metadata_configuration.is_some() {
            return Err(RuntimeError::BucketMetadataTableApiNotAvailable(
                bucket.to_string(),
            ));
        }
        bucket_state.metadata_table_configuration = None;
        self.audit_allowed(
            principal,
            S3Action::DeleteBucketMetadataTableConfiguration,
            bucket,
            None,
        );
        Ok(())
    }
}