Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature: Implement defender metrics #70

Merged
merged 22 commits into from
Feb 7, 2025
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
7fc002b
Initial structure of defender metrics
KennethKnudsen97 Dec 23, 2024
ae63c48
metric structure and tests
KennethKnudsen97 Dec 27, 2024
f28e3d1
generic custom metric
KennethKnudsen97 Jan 2, 2025
d76a514
Change Custom metric to use references
KennethKnudsen97 Jan 6, 2025
f631a8c
aws types with references
KennethKnudsen97 Jan 6, 2025
a58a660
impl tuple for Version
KennethKnudsen97 Jan 6, 2025
09ef37a
remove timestamp as argument for function in custom metric
KennethKnudsen97 Jan 6, 2025
817caf7
include aws metrics and use bon crate for building metric struct
KennethKnudsen97 Jan 6, 2025
825e5a0
error handling
KennethKnudsen97 Jan 14, 2025
2707cd7
error handling
KennethKnudsen97 Jan 16, 2025
8418ee6
error handling
KennethKnudsen97 Jan 21, 2025
3f9fe06
Merge branch 'feature/async' into feature/defender_metrics
KennethKnudsen97 Jan 21, 2025
042db28
feature flag for cbor and temp fix for Header serialize
KennethKnudsen97 Feb 3, 2025
0089ca9
smal changes
KennethKnudsen97 Feb 4, 2025
985ca38
String list example
KennethKnudsen97 Feb 5, 2025
ca5f8ce
Metric integration test
KennethKnudsen97 Feb 5, 2025
092ea92
Update src/defender_metrics/data_types.rs
KennethKnudsen97 Feb 7, 2025
bcdab34
Cargo clippy and unit test
KennethKnudsen97 Feb 7, 2025
fcce0f3
Merge branch 'feature/defender_metrics' of github.com:BlackbirdHQ/rus…
KennethKnudsen97 Feb 7, 2025
b1e6c35
cargo clippy fix
KennethKnudsen97 Feb 7, 2025
fa66a9c
fixed unit test and version serialization
KennethKnudsen97 Feb 7, 2025
caec287
fix test
KennethKnudsen97 Feb 7, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"rust-analyzer.checkOnSave.allTargets": false,
"rust-analyzer.checkOnSave.allTargets": true,
"rust-analyzer.cargo.features": ["log"],
"rust-analyzer.cargo.target": "x86_64-unknown-linux-gnu"
}
84 changes: 84 additions & 0 deletions src/defender_metrics/aws_types.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
use core::str::FromStr;

use heapless::{LinearMap, String, Vec};
use serde::{Deserialize, Serialize};

#[derive(Debug, Serialize, Deserialize)]
pub struct TcpConnections {
#[serde(rename = "ec")]
pub established_connections: Option<EstablishedConnections>,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct EstablishedConnections {
#[serde(rename = "cs")]
pub connections: Option<Vec<Connection, { MAX_CONNECTIONS }>>,

#[serde(rename = "t")]
pub total: Option<u64>,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct Connection {
#[serde(rename = "rad")]
pub remote_addr: String<REMOTE_ADDR_SIZE>,

/// Port number, must be >= 0
#[serde(rename = "lp")]
pub local_port: Option<u16>,

/// Interface name
#[serde(rename = "li")]
pub local_interface: Option<String<LOCAL_INTERFACE_SIZE>>,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct ListeningTcpPorts {
#[serde(rename = "pts")]
pub ports: Option<Vec<TcpPort, MAX_PORTS>>,

#[serde(rename = "t")]
pub total: Option<u64>,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct TcpPort {
#[serde(rename = "pt")]
pub port: u16,

#[serde(rename = "if")]
pub interface: Option<String<LOCAL_INTERFACE_SIZE>>,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct ListeningUdpPorts {
#[serde(rename = "pts")]
pub ports: Option<Vec<UdpPort, MAX_PORTS>>,

#[serde(rename = "t")]
pub total: Option<u64>,
}

KennethKnudsen97 marked this conversation as resolved.
Show resolved Hide resolved
#[derive(Debug, Serialize, Deserialize)]
pub struct UdpPort {
#[serde(rename = "pt")]
pub port: u16,

#[serde(rename = "if")]
pub interface: Option<String<LOCAL_INTERFACE_SIZE>>,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct NetworkStats {
#[serde(rename = "bi")]
pub bytes_in: Option<u64>,

#[serde(rename = "bo")]
pub bytes_out: Option<u64>,

#[serde(rename = "pi")]
pub packets_in: Option<u64>,

#[serde(rename = "po")]
pub packets_out: Option<u64>,
}
113 changes: 113 additions & 0 deletions src/defender_metrics/data_types.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
use core::str::FromStr;

use heapless::{String, Vec};
use serde::Serialize;

// Constants for heapless container sizes
pub const HEADER_VERSION_SIZE: usize = 6;
pub const REMOTE_ADDR_SIZE: usize = 64;
pub const LOCAL_INTERFACE_SIZE: usize = 32;
pub const MAX_METRICS: usize = 8;
pub const MAX_CUSTOM_METRICS: usize = 16;
pub const MAX_CUSTOM_METRICS_NAME: usize = 32;

pub enum MetricError {
Malformed,
Throttled,
MissingHeader,
Other,
}

#[derive(Debug, Serialize)]
pub struct Metric<C: Serialize> {
#[serde(rename = "hed")]
pub header: Header,

#[serde(rename = "cmet")]
pub custom_metrics: C,
}

impl<C: Serialize> Metric<C> {
pub fn new(custom_metrics: C, timestamp: i64) -> Self {
let header = Header {
report_id: timestamp,
version: String::<HEADER_VERSION_SIZE>::from_str("1.0").unwrap(), //FIXME: Don't
KennethKnudsen97 marked this conversation as resolved.
Show resolved Hide resolved
};

Self {
header,
custom_metrics,
}
}
}

#[derive(Debug, Serialize)]
pub struct Header {
/// Monotonically increasing value. Epoch timestamp recommended.
#[serde(rename = "rid")]
pub report_id: i64,

/// Version in Major.Minor format.
#[serde(rename = "v")]
pub version: String<HEADER_VERSION_SIZE>,
}

#[derive(Debug, Serialize)]
#[serde(rename_all = "snake_case")]
pub enum CustomMetric {
Number(i64),
NumberList(Vec<u64, MAX_METRICS>),
StringList(Vec<String<LOCAL_INTERFACE_SIZE>, MAX_METRICS>),
IpList(Vec<String<REMOTE_ADDR_SIZE>, MAX_METRICS>),
}
KennethKnudsen97 marked this conversation as resolved.
Show resolved Hide resolved

impl CustomMetric {
pub fn new_number(value: i64) -> heapless::Vec<Self, 1> {
let mut custom_metric_map = Vec::new();

custom_metric_map.push(CustomMetric::Number(value)).unwrap();

custom_metric_map
}

pub fn new_number_list(values: &[u64]) -> heapless::Vec<Self, 1> {
let mut custom_metric_map = Vec::new();

let mut vec = Vec::new();
for &v in values {
vec.push(v).unwrap();
}

custom_metric_map
.push(CustomMetric::NumberList(vec))
.unwrap();

custom_metric_map
}

pub fn new_string_list(values: &[&str]) -> heapless::Vec<Self, 1> {
let mut custom_metric_map = Vec::new();

let mut vec = Vec::new();
for &v in values {
vec.push(String::from_str(v).unwrap()).unwrap();
}
custom_metric_map
.push(CustomMetric::StringList(vec))
.unwrap();

custom_metric_map
}

pub fn new_ip_list(values: &[&str]) -> heapless::Vec<Self, 1> {
let mut custom_metric_map = Vec::new();

let mut vec = Vec::new();
for &v in values {
vec.push(String::from_str(v).unwrap()).unwrap();
}
custom_metric_map.push(CustomMetric::IpList(vec)).unwrap();

custom_metric_map
}
}
Loading
Loading