bucketwarden-server 0.1.0

BucketWarden storage server runtime.
Documentation
use super::*;
mod object_list;
impl BucketWarden {
    pub fn get_object(
        &mut self,
        principal: &str,
        bucket: &str,
        key: &str,
    ) -> Result<GetObjectResult, RuntimeError> {
        self.read_current_object(principal, bucket, key, S3Action::GetObject)
    }
    pub fn get_object_version(
        &mut self,
        principal: &str,
        bucket: &str,
        key: &str,
        version_id: &str,
    ) -> Result<GetObjectResult, RuntimeError> {
        self.read_object_version(principal, bucket, key, version_id, S3Action::GetObject)
    }
    pub fn get_object_torrent(
        &mut self,
        principal: &str,
        bucket: &str,
        key: &str,
    ) -> Result<GetObjectResult, RuntimeError> {
        self.read_current_object(principal, bucket, key, S3Action::GetObjectTorrent)
    }
    pub fn get_object_version_torrent(
        &mut self,
        principal: &str,
        bucket: &str,
        key: &str,
        version_id: &str,
    ) -> Result<GetObjectResult, RuntimeError> {
        self.read_object_version(
            principal,
            bucket,
            key,
            version_id,
            S3Action::GetObjectTorrent,
        )
    }

    fn read_current_object(
        &mut self,
        principal: &str,
        bucket: &str,
        key: &str,
        action: S3Action,
    ) -> Result<GetObjectResult, RuntimeError> {
        let resource = object_resource(bucket, key);
        let (
            context,
            result_version_id,
            etag,
            last_modified_epoch_seconds,
            ciphertext,
            metadata,
            envelope,
            integrity,
            replication_status,
        ) = {
            let version = match self.current_version(bucket, key) {
                Ok(version) => version,
                Err(error @ RuntimeError::NoSuchKey(_)) => {
                    self.authorize(principal, action, &resource)?;
                    return Err(error);
                }
                Err(error) => return Err(error),
            };
            (
                object_tag_context(version),
                version.version_id.clone(),
                version.etag.clone(),
                version.last_modified_epoch_seconds,
                version.ciphertext.clone(),
                version.metadata.clone(),
                version.envelope.clone(),
                version.integrity.clone(),
                version.replication_status.clone(),
            )
        };
        self.authorize_with_context(principal, action, &resource, &context)?;
        let body = match self.kms.decrypt(&ciphertext) {
            Ok(body) => body,
            Err(error) => {
                self.audit_kms_failure(
                    principal,
                    "kms:Decrypt",
                    &resource,
                    &ciphertext.key_id,
                    &error.to_string(),
                );
                return Err(RuntimeError::Kms(error));
            }
        };
        self.verify_integrity_record(&integrity, &body)?;
        let result = GetObjectResult {
            bucket: bucket.to_string(),
            key: key.to_string(),
            version_id: result_version_id,
            etag,
            last_modified_epoch_seconds,
            body,
            metadata,
            replication_status,
        };
        self.audit_allowed(
            principal,
            action,
            &resource,
            Some(result.version_id.clone()),
        );
        self.audit_kms_decrypt(principal, &resource, &result.version_id, &ciphertext.key_id);
        if let Some(envelope) = envelope {
            self.audit_kms_unwrap(principal, &resource, &result.version_id, &envelope.key_id);
        }
        Ok(result)
    }

    fn read_object_version(
        &mut self,
        principal: &str,
        bucket: &str,
        key: &str,
        version_id: &str,
        action: S3Action,
    ) -> Result<GetObjectResult, RuntimeError> {
        let resource = object_resource(bucket, key);
        let (
            context,
            result_version_id,
            etag,
            last_modified_epoch_seconds,
            ciphertext,
            metadata,
            envelope,
            integrity,
            replication_status,
        ) = {
            let version = self.version_by_id(bucket, key, version_id)?;
            if version.delete_marker {
                return Err(RuntimeError::NoSuchKey(object_resource(bucket, key)));
            }
            (
                object_tag_context(version),
                version.version_id.clone(),
                version.etag.clone(),
                version.last_modified_epoch_seconds,
                version.ciphertext.clone(),
                version.metadata.clone(),
                version.envelope.clone(),
                version.integrity.clone(),
                version.replication_status.clone(),
            )
        };
        self.authorize_with_context(principal, action, &resource, &context)?;
        let body = match self.kms.decrypt(&ciphertext) {
            Ok(body) => body,
            Err(error) => {
                self.audit_kms_failure(
                    principal,
                    "kms:Decrypt",
                    &resource,
                    &ciphertext.key_id,
                    &error.to_string(),
                );
                return Err(RuntimeError::Kms(error));
            }
        };
        self.verify_integrity_record(&integrity, &body)?;
        let result = GetObjectResult {
            bucket: bucket.to_string(),
            key: key.to_string(),
            version_id: result_version_id,
            etag,
            last_modified_epoch_seconds,
            body,
            metadata,
            replication_status,
        };
        self.audit_allowed(
            principal,
            action,
            &resource,
            Some(result.version_id.clone()),
        );
        self.audit_kms_decrypt(principal, &resource, &result.version_id, &ciphertext.key_id);
        if let Some(envelope) = envelope {
            self.audit_kms_unwrap(principal, &resource, &result.version_id, &envelope.key_id);
        }
        Ok(result)
    }
    pub fn head_object(
        &mut self,
        principal: &str,
        bucket: &str,
        key: &str,
    ) -> Result<HeadObjectResult, RuntimeError> {
        let resource = object_resource(bucket, key);
        self.authorize(principal, S3Action::HeadObject, &resource)?;
        let version = self.current_version(bucket, key)?;
        let result = HeadObjectResult {
            bucket: bucket.to_string(),
            key: key.to_string(),
            version_id: version.version_id.clone(),
            etag: version.etag.clone(),
            last_modified_epoch_seconds: version.last_modified_epoch_seconds,
            content_length: version.content_length(),
            metadata: version.metadata.clone(),
            replication_status: version.replication_status.clone(),
        };
        self.audit_allowed(
            principal,
            S3Action::HeadObject,
            &resource,
            Some(result.version_id.clone()),
        );
        Ok(result)
    }
    pub fn head_object_version(
        &mut self,
        principal: &str,
        bucket: &str,
        key: &str,
        version_id: &str,
    ) -> Result<HeadObjectResult, RuntimeError> {
        let resource = object_resource(bucket, key);
        self.authorize(principal, S3Action::HeadObject, &resource)?;
        let version = self.version_by_id(bucket, key, version_id)?;
        if version.delete_marker {
            return Err(RuntimeError::NoSuchKey(object_resource(bucket, key)));
        }
        let result = HeadObjectResult {
            bucket: bucket.to_string(),
            key: key.to_string(),
            version_id: version.version_id.clone(),
            etag: version.etag.clone(),
            last_modified_epoch_seconds: version.last_modified_epoch_seconds,
            content_length: version.content_length(),
            metadata: version.metadata.clone(),
            replication_status: version.replication_status.clone(),
        };
        self.audit_allowed(
            principal,
            S3Action::HeadObject,
            &resource,
            Some(result.version_id.clone()),
        );
        Ok(result)
    }
    pub fn get_object_attributes(
        &mut self,
        principal: &str,
        bucket: &str,
        key: &str,
    ) -> Result<GetObjectAttributesResult, RuntimeError> {
        let resource = object_resource(bucket, key);
        self.authorize(principal, S3Action::GetObjectAttributes, &resource)?;
        let version = self.current_version(bucket, key)?;
        let result = GetObjectAttributesResult {
            bucket: bucket.to_string(),
            key: key.to_string(),
            version_id: version.version_id.clone(),
            etag: version.etag.clone(),
            last_modified_epoch_seconds: version.last_modified_epoch_seconds,
            object_size: version.integrity.content_length,
            checksum: Checksum {
                checksum_sha256: base64_encode(version.integrity.checksum_sha256.as_bytes()),
            },
            storage_class: "STANDARD".to_string(),
            object_parts: GetObjectAttributesParts {
                total_parts_count: version.integrity.part_checksums.len(),
                part_number_marker: 0,
                max_parts: version.integrity.part_checksums.len(),
                is_truncated: false,
            },
        };
        self.audit_allowed(
            principal,
            S3Action::GetObjectAttributes,
            &resource,
            Some(result.version_id.clone()),
        );
        Ok(result)
    }
    pub fn get_object_version_attributes(
        &mut self,
        principal: &str,
        bucket: &str,
        key: &str,
        version_id: &str,
    ) -> Result<GetObjectAttributesResult, RuntimeError> {
        let resource = object_resource(bucket, key);
        self.authorize(principal, S3Action::GetObjectAttributes, &resource)?;
        let version = self.version_by_id(bucket, key, version_id)?;
        if version.delete_marker {
            return Err(RuntimeError::NoSuchKey(object_resource(bucket, key)));
        }
        let result = GetObjectAttributesResult {
            bucket: bucket.to_string(),
            key: key.to_string(),
            version_id: version.version_id.clone(),
            etag: version.etag.clone(),
            last_modified_epoch_seconds: version.last_modified_epoch_seconds,
            object_size: version.integrity.content_length,
            checksum: Checksum {
                checksum_sha256: base64_encode(version.integrity.checksum_sha256.as_bytes()),
            },
            storage_class: "STANDARD".to_string(),
            object_parts: GetObjectAttributesParts {
                total_parts_count: version.integrity.part_checksums.len(),
                part_number_marker: 0,
                max_parts: version.integrity.part_checksums.len(),
                is_truncated: false,
            },
        };
        self.audit_allowed(
            principal,
            S3Action::GetObjectAttributes,
            &resource,
            Some(result.version_id.clone()),
        );
        Ok(result)
    }
}