Skip to main content

ruso_runtime/runtime/
spec.rs

1use crate::contract::{HttpMethod, ObjectBody};
2
3#[derive(Debug, Clone, PartialEq)]
4pub struct HttpRequestSpec {
5    pub method: HttpMethod,
6    pub path: String,
7    pub timeout: Option<String>,
8    pub follow_redirect: Option<bool>,
9    pub verify_ssl: Option<bool>,
10    pub proxy: Option<String>,
11    pub user_agent: Option<String>,
12    pub headers: Vec<(String, String)>,
13    pub cookies: Vec<(String, String)>,
14    pub queries: Vec<(String, String)>,
15    pub data_body: Option<ObjectBody>,
16    pub json_body: Option<ObjectBody>,
17    pub raw_body: Option<String>,
18    pub body_bytes: Option<String>,
19    pub multipart_body: Option<ObjectBody>,
20}
21
22impl Default for HttpRequestSpec {
23    fn default() -> Self {
24        Self {
25            method: HttpMethod::Get,
26            path: "/".into(),
27            timeout: None,
28            follow_redirect: None,
29            verify_ssl: None,
30            proxy: None,
31            user_agent: None,
32            headers: Vec::new(),
33            cookies: Vec::new(),
34            queries: Vec::new(),
35            data_body: None,
36            json_body: None,
37            raw_body: None,
38            body_bytes: None,
39            multipart_body: None,
40        }
41    }
42}
43
44/// Generic socket options (shared by dns/tcp/udp probes).
45#[derive(Debug, Clone, PartialEq)]
46pub struct SocketProbeSpec {
47    pub host: String,
48    pub port: Option<u16>,
49    pub payload: Option<Vec<u8>>,
50    /// TLS handshake before application data (TCP only).
51    pub tls: bool,
52    /// Keep connection open across multiple `send` on the same probe name.
53    pub session: bool,
54    /// Maximum bytes to read per exchange (default 65536).
55    pub read_max: u32,
56    /// After first read, keep reading until idle for this many ms (0 = single read).
57    pub read_idle_ms: u32,
58}
59
60impl Default for SocketProbeSpec {
61    fn default() -> Self {
62        Self {
63            host: String::new(),
64            port: None,
65            payload: None,
66            tls: false,
67            session: false,
68            read_max: 65_536,
69            read_idle_ms: 0,
70        }
71    }
72}
73
74#[derive(Debug, Clone, PartialEq)]
75pub enum ProbeKind {
76    Http(HttpRequestSpec),
77    Dns(SocketProbeSpec),
78    Tcp(SocketProbeSpec),
79    Udp(SocketProbeSpec),
80}
81
82#[derive(Debug, Clone, Default)]
83pub struct CheckMetadata {
84    pub name: Option<String>,
85    pub description: Option<String>,
86    pub impact: Option<String>,
87    pub severity: Option<crate::contract::Severity>,
88    pub author: Option<String>,
89    pub report_title: Option<String>,
90    pub cve: Vec<String>,
91    pub cwe: Vec<String>,
92    pub references: Vec<String>,
93    pub cvss: Vec<String>,
94    pub cvss_score: Vec<String>,
95    /// Single free-text remediation note. The language rejects more than one
96    /// `mitigation` line per script at compile time (unlike `cve`/`cwe`/
97    /// `references`/`tags`, which accumulate into lists).
98    pub mitigation: Option<String>,
99    pub tags: Vec<String>,
100    pub version: Option<String>,
101    /// Single curated category (e.g. `web`, `network`, `database`).
102    /// Distinct from `tags`: one-per-script, used for "scan everything
103    /// in this family" selection. The allowed set is enforced by the
104    /// registry at publish time, not here.
105    pub family: Option<String>,
106}
107
108#[derive(Debug, Clone)]
109pub struct ProgramSpec {
110    pub probes: std::collections::HashMap<String, ProbeKind>,
111    pub metadata: CheckMetadata,
112}
113
114impl SocketProbeSpec {
115    pub fn is_dns_resolver_mode(&self) -> bool {
116        self.port.is_none() && self.payload.is_none()
117    }
118}