bucketwarden-server 0.1.0

BucketWarden storage server runtime.
Documentation
use super::*;
use crate::ops_health_diagnostics::{
    ops_scope_and_target, scoped_audit_events, scoped_notification_events,
    scoped_replication_records,
};

impl BucketWarden {
    pub fn ops_evidence_export_report(
        &mut self,
        principal: &str,
        bucket: Option<&str>,
    ) -> Result<OpsEvidenceExportReport, RuntimeError> {
        let (scope, target) = ops_scope_and_target(bucket);
        self.require_operator_action(
            principal,
            OperatorAction::ReadAudit,
            &target,
            "ops:GetEvidenceExportReport",
        )?;
        self.require_ops_bucket_scope(bucket)?;
        let audit_events = scoped_audit_events(self, bucket);
        let notification_events = scoped_notification_events(self, bucket);
        let replication_records = scoped_replication_records(self, bucket);
        let report = OpsEvidenceExportReport {
            scope: scope.to_string(),
            target: target.to_string(),
            generated_at_epoch_seconds: self.clock_epoch_seconds,
            audit_event_count: audit_events.len(),
            notification_event_count: notification_events.len(),
            replication_record_count: replication_records.len(),
            first_audit_sequence: audit_events.first().map(|event| event.sequence),
            last_audit_sequence: audit_events.last().map(|event| event.sequence),
            first_notification_event_id: notification_events
                .first()
                .map(|event| event.event_id.clone()),
            last_notification_event_id: notification_events
                .last()
                .map(|event| event.event_id.clone()),
            first_replication_sequence: replication_records.first().map(|record| record.sequence),
            last_replication_sequence: replication_records.last().map(|record| record.sequence),
            snapshot_json: self.snapshot_json()?,
            audit_json_lines: audit_events_json_lines(&audit_events)?,
            notification_json_lines: notification_events_json_lines_scoped(&notification_events)?,
            replication_json_lines: replication_records_json_lines(&replication_records)?,
            storage_backend_evidence_json: serde_json::to_string(
                &self.storage_backend_support_report(),
            )
            .map_err(RuntimeError::SnapshotSerialize)?,
            replication_strategy_evidence_json: serde_json::to_string(
                &self.replication_strategy_support_report(),
            )
            .map_err(RuntimeError::SnapshotSerialize)?,
            erasure_coding_evidence_json: serde_json::to_string(
                &self.erasure_coding_support_report(),
            )
            .map_err(RuntimeError::SnapshotSerialize)?,
            placement_domain_evidence_json: serde_json::to_string(
                &self.placement_domain_support_report(),
            )
            .map_err(RuntimeError::SnapshotSerialize)?,
            consistency_model_evidence_json: serde_json::to_string(
                &self.consistency_model_support_report(),
            )
            .map_err(RuntimeError::SnapshotSerialize)?,
            metadata_architecture_evidence_json: serde_json::to_string(
                &self.metadata_architecture_support_report(),
            )
            .map_err(RuntimeError::SnapshotSerialize)?,
            object_layout_evidence_json: serde_json::to_string(
                &self.object_layout_support_report(),
            )
            .map_err(RuntimeError::SnapshotSerialize)?,
            small_object_optimization_evidence_json: serde_json::to_string(
                &self.small_object_optimization_report(),
            )
            .map_err(RuntimeError::SnapshotSerialize)?,
            large_object_optimization_evidence_json: serde_json::to_string(
                &self.large_object_optimization_report(),
            )
            .map_err(RuntimeError::SnapshotSerialize)?,
        };
        self.audit.append(
            principal,
            "ops:GetEvidenceExportReport",
            &target,
            AuditOutcome::Allowed,
            Some(format!(
                "audit={},notification={},replication={}",
                report.audit_event_count,
                report.notification_event_count,
                report.replication_record_count
            )),
        );
        Ok(report)
    }
}

fn audit_events_json_lines(events: &[&AuditEvent]) -> Result<String, RuntimeError> {
    let mut lines = Vec::with_capacity(events.len());
    for event in events {
        lines.push(serde_json::to_string(event).map_err(RuntimeError::SnapshotSerialize)?);
    }
    Ok(lines.join("\n"))
}

fn notification_events_json_lines_scoped(
    events: &[&NotificationEvent],
) -> Result<String, RuntimeError> {
    let mut lines = Vec::with_capacity(events.len());
    for event in events {
        lines.push(serde_json::to_string(event).map_err(RuntimeError::SnapshotSerialize)?);
    }
    Ok(lines.join("\n"))
}

fn replication_records_json_lines(events: &[&ReplicationRecord]) -> Result<String, RuntimeError> {
    let mut lines = Vec::with_capacity(events.len());
    for event in events {
        lines.push(serde_json::to_string(event).map_err(RuntimeError::SnapshotSerialize)?);
    }
    Ok(lines.join("\n"))
}