use super::*;
impl BucketWarden {
pub fn console_api_audit_events(
&mut self,
access_key_id: &str,
query: ConsoleApiAuditQuery,
) -> Result<ConsoleApiAuditEvents, RuntimeError> {
let principal = self.console_api_principal(access_key_id)?;
self.require_operator_action(&principal, OperatorAction::ReadAudit, "*", "ui:GetAudit")?;
let outcome = query
.outcome
.as_deref()
.map(parse_audit_outcome)
.transpose()?;
let filter = bucketwarden_audit::AuditFilter {
subject: query.subject.as_deref(),
action: query.action.as_deref(),
resource: query.resource.as_deref(),
outcome,
min_sequence: query.min_sequence,
max_sequence: query.max_sequence,
};
let mut events = self
.audit
.filter_events(&filter)
.into_iter()
.cloned()
.collect::<Vec<_>>();
events.retain(|event| {
matches_text(
&[
&event.subject,
&event.action,
&event.resource,
&format!("{:?}", event.outcome),
event.detail.as_deref().unwrap_or_default(),
],
&query.q,
)
});
match query.sort.as_deref().unwrap_or("-sequence") {
"sequence" => events.sort_by_key(|event| event.sequence),
"-sequence" => events.sort_by(|left, right| right.sequence.cmp(&left.sequence)),
"subject" => events.sort_by(|left, right| left.subject.cmp(&right.subject)),
"-subject" => events.sort_by(|left, right| right.subject.cmp(&left.subject)),
"action" => events.sort_by(|left, right| left.action.cmp(&right.action)),
"-action" => events.sort_by(|left, right| right.action.cmp(&left.action)),
"resource" => events.sort_by(|left, right| left.resource.cmp(&right.resource)),
"-resource" => events.sort_by(|left, right| right.resource.cmp(&left.resource)),
value => {
return Err(RuntimeError::InvalidListParameter {
name: "sort".to_string(),
value: value.to_string(),
})
}
}
let list_query = ConsoleApiListQuery {
limit: query.limit,
offset: query.offset,
prefix: None,
q: query.q,
sort: query.sort,
};
let (page, events) = page_vec(events, &list_query, "-sequence")?;
Ok(ConsoleApiAuditEvents { page, events })
}
pub fn console_api_evidence_list(
&mut self,
access_key_id: &str,
query: ConsoleApiListQuery,
) -> Result<ConsoleApiEvidenceList, RuntimeError> {
let principal = self.console_api_principal(access_key_id)?;
let report = self.ops_evidence_export_report(&principal, None)?;
let mut evidence = evidence_items(&report);
match query.sort.as_deref().unwrap_or("name") {
"name" => evidence.sort_by(|left, right| left.name.cmp(&right.name)),
"-name" => evidence.sort_by(|left, right| right.name.cmp(&left.name)),
"bytes" => evidence.sort_by_key(|item| item.bytes),
"-bytes" => evidence.sort_by(|left, right| right.bytes.cmp(&left.bytes)),
"record_count" => evidence.sort_by_key(|item| item.record_count),
"-record_count" => {
evidence.sort_by(|left, right| right.record_count.cmp(&left.record_count))
}
value => {
return Err(RuntimeError::InvalidListParameter {
name: "sort".to_string(),
value: value.to_string(),
})
}
}
evidence.retain(|item| matches_text(&[&item.name, &item.content_type], &query.q));
let (page, evidence) = page_vec(evidence, &query, "name")?;
Ok(ConsoleApiEvidenceList { page, evidence })
}
pub fn console_api_evidence_export(
&mut self,
access_key_id: &str,
) -> Result<ConsoleApiEvidenceExport, RuntimeError> {
let principal = self.console_api_principal(access_key_id)?;
let report = self.ops_evidence_export_report(&principal, None)?;
Ok(ConsoleApiEvidenceExport {
filename: format!(
"bucketwarden-evidence-{}.json",
report.generated_at_epoch_seconds
),
content_type: "application/json".to_string(),
report,
})
}
}
fn parse_audit_outcome(value: &str) -> Result<AuditOutcome, RuntimeError> {
match value {
"Allowed" | "allowed" => Ok(AuditOutcome::Allowed),
"Denied" | "denied" => Ok(AuditOutcome::Denied),
"Failed" | "failed" => Ok(AuditOutcome::Failed),
_ => Err(RuntimeError::InvalidListParameter {
name: "outcome".to_string(),
value: value.to_string(),
}),
}
}
fn evidence_items(report: &OpsEvidenceExportReport) -> Vec<ConsoleApiEvidenceItem> {
vec![
item("snapshot_json", &report.snapshot_json, 1),
item(
"audit_json_lines",
&report.audit_json_lines,
report.audit_event_count,
),
item(
"notification_json_lines",
&report.notification_json_lines,
report.notification_event_count,
),
item(
"replication_json_lines",
&report.replication_json_lines,
report.replication_record_count,
),
item(
"storage_backend_evidence_json",
&report.storage_backend_evidence_json,
1,
),
item(
"replication_strategy_evidence_json",
&report.replication_strategy_evidence_json,
1,
),
item(
"metadata_architecture_evidence_json",
&report.metadata_architecture_evidence_json,
1,
),
]
}
fn item(name: &str, body: &str, record_count: usize) -> ConsoleApiEvidenceItem {
ConsoleApiEvidenceItem {
name: name.to_string(),
content_type: if name.ends_with("_lines") {
"application/jsonl".to_string()
} else {
"application/json".to_string()
},
bytes: body.len(),
record_count,
}
}