use serde::Serialize;
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize)]
#[serde(rename_all = "lowercase")]
pub enum Category {
Email,
Web,
Tls,
Dns,
Takeover,
Registration,
}
impl Category {
pub const ALL: [Category; 6] = [
Category::Email,
Category::Web,
Category::Tls,
Category::Dns,
Category::Takeover,
Category::Registration,
];
pub fn weight(self) -> u32 {
match self {
Category::Email | Category::Web | Category::Tls => 20,
Category::Dns | Category::Takeover => 15,
Category::Registration => 10,
}
}
pub fn as_str(self) -> &'static str {
match self {
Category::Email => "email",
Category::Web => "web",
Category::Tls => "tls",
Category::Dns => "dns",
Category::Takeover => "takeover",
Category::Registration => "registration",
}
}
pub fn label(self) -> &'static str {
match self {
Category::Email => "Email",
Category::Web => "Web",
Category::Tls => "TLS",
Category::Dns => "DNS",
Category::Takeover => "Takeover",
Category::Registration => "Registration",
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize)]
#[serde(rename_all = "lowercase")]
pub enum Severity {
Info,
Low,
Medium,
High,
Critical,
}
impl Severity {
pub fn deduction(self) -> u32 {
match self {
Severity::Info => 0,
Severity::Low => 3,
Severity::Medium => 10,
Severity::High => 25,
Severity::Critical => 60,
}
}
pub fn as_str(self) -> &'static str {
match self {
Severity::Info => "info",
Severity::Low => "low",
Severity::Medium => "medium",
Severity::High => "high",
Severity::Critical => "critical",
}
}
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
pub struct Finding {
pub id: &'static str,
pub category: Category,
pub severity: Severity,
pub host: String,
pub title: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub evidence: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub remediation: Option<String>,
}
impl Finding {
pub(crate) fn new(
id: &'static str,
category: Category,
severity: Severity,
host: &str,
title: impl Into<String>,
) -> Self {
Self {
id,
category,
severity,
host: host.to_string(),
title: title.into(),
evidence: None,
remediation: None,
}
}
pub(crate) fn evidence(mut self, evidence: impl Into<String>) -> Self {
self.evidence = Some(evidence.into());
self
}
pub(crate) fn fix(mut self, remediation: impl Into<String>) -> Self {
self.remediation = Some(remediation.into());
self
}
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
#[serde(tag = "status", rename_all = "kebab-case")]
pub enum CheckStatus {
Ran,
Incomplete { reason: String },
NotApplicable { reason: String },
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
pub struct CheckRun {
pub check: &'static str,
pub category: Category,
#[serde(flatten)]
pub status: CheckStatus,
}