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 /// Target host. Often `{{scan_host}}` so it follows the CLI `--target`.
48 pub host: String,
49 /// Target port. Required at runtime for `tcp`/`udp`; for `dns`, its
50 /// presence selects wire mode over the OS resolver.
51 pub port: Option<u16>,
52 /// Optional payload bytes to send on connect.
53 pub payload: Option<Vec<u8>>,
54 /// TLS handshake before application data (TCP only).
55 pub tls: bool,
56 /// Keep connection open across multiple `send` on the same probe name.
57 pub session: bool,
58 /// Maximum bytes to read per exchange (default 65536).
59 pub read_max: u32,
60 /// After first read, keep reading until idle for this many ms (0 = single read).
61 pub read_idle_ms: u32,
62}
63
64impl Default for SocketProbeSpec {
65 fn default() -> Self {
66 Self {
67 host: String::new(),
68 port: None,
69 payload: None,
70 tls: false,
71 session: false,
72 read_max: 65_536,
73 read_idle_ms: 0,
74 }
75 }
76}
77
78/// A probe definition, tagged by transport.
79#[derive(Debug, Clone, PartialEq)]
80pub enum ProbeKind {
81 /// HTTP/HTTPS request.
82 Http(HttpRequestSpec),
83 /// DNS probe — OS resolver or wire mode (see [`SocketProbeSpec`]).
84 Dns(SocketProbeSpec),
85 /// Raw TCP (optionally TLS).
86 Tcp(SocketProbeSpec),
87 /// Raw UDP.
88 Udp(SocketProbeSpec),
89}
90
91/// The `metadata { … }` block of a check — describes the finding it emits.
92///
93/// Only `name` is required to emit a finding; the rest enriches the report and
94/// is needed to publish to the registry.
95#[derive(Debug, Clone, Default)]
96pub struct CheckMetadata {
97 /// Short finding title (the registry slug derives from this).
98 pub name: Option<String>,
99 /// What the check does.
100 pub description: Option<String>,
101 /// The risk if the check is positive.
102 pub impact: Option<String>,
103 /// Finding severity (defaults to `Info` when unset).
104 pub severity: Option<crate::contract::Severity>,
105 /// Check author.
106 pub author: Option<String>,
107 /// Associated CVE identifiers.
108 pub cve: Vec<String>,
109 /// Associated CWE identifiers.
110 pub cwe: Vec<String>,
111 /// Reference URLs (advisories, docs).
112 pub references: Vec<String>,
113 /// CVSS vector strings (e.g. base + temporal).
114 pub cvss: Vec<String>,
115 /// CVSS numeric scores.
116 pub cvss_score: Vec<String>,
117 /// Single free-text remediation note. The language rejects more than one
118 /// `mitigation` line per script at compile time (unlike `cve`/`cwe`/
119 /// `references`/`tags`, which accumulate into lists).
120 pub mitigation: Option<String>,
121 /// Free-form discovery labels (many per check).
122 pub tags: Vec<String>,
123 /// SemVer string; required at publish time, optional for local use.
124 pub version: Option<String>,
125 /// Single curated category (e.g. `web`, `network`, `database`).
126 /// Distinct from `tags`: one-per-script, used for "scan everything
127 /// in this family" selection. The allowed set is enforced by the
128 /// registry at publish time, not here.
129 pub family: Option<String>,
130}
131
132/// The non-executable part of a compiled program: the probe table and the
133/// finding metadata. The instruction stream lives in [`BytecodeProgram`].
134///
135/// [`BytecodeProgram`]: crate::BytecodeProgram
136#[derive(Debug, Clone)]
137pub struct ProgramSpec {
138 /// Probes keyed by their script name (e.g. `home`, `redis`).
139 pub probes: std::collections::HashMap<String, ProbeKind>,
140 /// The check's finding metadata.
141 pub metadata: CheckMetadata,
142}
143
144impl SocketProbeSpec {
145 /// True when this spec uses the OS resolver (a `dns` probe with neither
146 /// `port` nor `payload`) rather than DNS wire mode.
147 pub fn is_dns_resolver_mode(&self) -> bool {
148 self.port.is_none() && self.payload.is_none()
149 }
150}