use std::sync::atomic::{AtomicU64, Ordering};
use std::sync::Arc;
#[cfg(feature = "tokio-runtime")]
use crate::security::ssrf::IpClass;
#[derive(Debug, Default, Clone)]
pub struct SecurityMetrics {
inner: Arc<SecurityMetricsInner>,
}
#[derive(Debug, Default)]
struct SecurityMetricsInner {
#[cfg_attr(not(feature = "tokio-runtime"), allow(dead_code))]
ssrf_blocked_private: AtomicU64,
#[cfg_attr(not(feature = "tokio-runtime"), allow(dead_code))]
ssrf_blocked_loopback: AtomicU64,
#[cfg_attr(not(feature = "tokio-runtime"), allow(dead_code))]
ssrf_blocked_link_local: AtomicU64,
#[cfg_attr(not(feature = "tokio-runtime"), allow(dead_code))]
ssrf_blocked_multicast: AtomicU64,
#[cfg_attr(not(feature = "tokio-runtime"), allow(dead_code))]
ssrf_blocked_reserved: AtomicU64,
dotfile_denied: AtomicU64,
}
impl SecurityMetrics {
pub fn new() -> Self {
Self::default()
}
#[cfg(feature = "tokio-runtime")]
pub fn record_ssrf_block(&self, class: IpClass) {
let counter = match class {
IpClass::Private => &self.inner.ssrf_blocked_private,
IpClass::Loopback => &self.inner.ssrf_blocked_loopback,
IpClass::LinkLocal => &self.inner.ssrf_blocked_link_local,
IpClass::Multicast => &self.inner.ssrf_blocked_multicast,
IpClass::Reserved | IpClass::Public => &self.inner.ssrf_blocked_reserved,
};
counter.fetch_add(1, Ordering::Relaxed);
}
#[cfg(feature = "tokio-runtime")]
pub fn ssrf_blocked_total(&self, class: IpClass) -> u64 {
let counter = match class {
IpClass::Private => &self.inner.ssrf_blocked_private,
IpClass::Loopback => &self.inner.ssrf_blocked_loopback,
IpClass::LinkLocal => &self.inner.ssrf_blocked_link_local,
IpClass::Multicast => &self.inner.ssrf_blocked_multicast,
IpClass::Reserved | IpClass::Public => &self.inner.ssrf_blocked_reserved,
};
counter.load(Ordering::Relaxed)
}
pub fn record_dotfile_deny(&self) {
self.inner.dotfile_denied.fetch_add(1, Ordering::Relaxed);
}
pub fn dotfile_denied_total(&self) -> u64 {
self.inner.dotfile_denied.load(Ordering::Relaxed)
}
}