bucketwarden-server 0.1.0

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

impl BucketWarden {
    pub fn update_object_encryption(
        &mut self,
        principal: &str,
        request: UpdateObjectEncryptionRequest,
    ) -> Result<UpdateObjectEncryptionResult, RuntimeError> {
        if crate::bucket_basics::is_directory_bucket_name(&request.bucket) {
            return Err(RuntimeError::InvalidEncryption(
                "UpdateObjectEncryption is not supported for directory buckets".to_string(),
            ));
        }
        let resource = object_resource(&request.bucket, &request.key);
        self.authorize(principal, S3Action::PutObject, &resource)?;
        self.authorize(principal, S3Action::UpdateObjectEncryption, &resource)?;
        let target_version_id = if let Some(version_id) = request.version_id.as_deref() {
            version_id.to_string()
        } else {
            self.current_version(&request.bucket, &request.key)?
                .version_id
                .clone()
        };
        let current_version = self
            .version_by_id(&request.bucket, &request.key, &target_version_id)?
            .clone();
        if current_version.delete_marker {
            return Err(RuntimeError::NoSuchKey(resource));
        }
        if let Err(error) = current_version
            .lock
            .assert_deletable(self.clock_epoch_seconds, false)
        {
            self.audit_denied(
                principal,
                S3Action::UpdateObjectEncryption,
                &resource,
                Some(error.to_string()),
            );
            return Err(RuntimeError::ObjectLocked(error));
        }
        let current_encryption = current_version.metadata.encryption.clone().ok_or_else(|| {
            RuntimeError::InvalidEncryption(
                "UpdateObjectEncryption requires an encrypted source object".to_string(),
            )
        })?;
        if current_encryption.algorithm == "aws:kms:dsse" {
            return Err(RuntimeError::UnsupportedEncryption(
                "UpdateObjectEncryption does not support DSSE-KMS source objects".to_string(),
            ));
        }
        let encryption = self.normalize_encryption(request.encryption)?;
        if encryption.algorithm != "aws:kms" {
            return Err(RuntimeError::InvalidEncryption(
                "UpdateObjectEncryption requires SSE-KMS as the requested encryption type"
                    .to_string(),
            ));
        }
        let body = match self.kms.decrypt(&current_version.ciphertext) {
            Ok(body) => body,
            Err(error) => {
                self.audit_kms_failure(
                    principal,
                    "kms:Decrypt",
                    &resource,
                    &current_version.ciphertext.key_id,
                    &error.to_string(),
                );
                return Err(RuntimeError::Kms(error));
            }
        };
        let ciphertext = match self.kms.encrypt(&body) {
            Ok(ciphertext) => ciphertext,
            Err(error) => {
                let key_id = self.kms.key_id().to_string();
                self.audit_kms_failure(
                    principal,
                    "kms:Encrypt",
                    &resource,
                    &key_id,
                    &error.to_string(),
                );
                return Err(RuntimeError::Kms(error));
            }
        };
        let envelope = self.envelope_metadata(Some(&encryption), &ciphertext, &body);
        let version = self.version_by_id_mut(&request.bucket, &request.key, &target_version_id)?;
        version.ciphertext = ciphertext;
        version.envelope = envelope;
        version.metadata.encryption = Some(encryption.clone());
        self.audit_allowed(
            principal,
            S3Action::UpdateObjectEncryption,
            &object_resource(&request.bucket, &request.key),
            Some(target_version_id.clone()),
        );
        Ok(UpdateObjectEncryptionResult {
            bucket: request.bucket,
            key: request.key,
            version_id: target_version_id,
            encryption,
            bucket_key_enabled: request.bucket_key_enabled,
        })
    }
}