flareguard 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Cargo.lock +2962 -0
- package/Cargo.toml +66 -0
- package/LICENSE +21 -0
- package/README.md +115 -0
- package/bin/flareguard.js +78 -0
- package/package.json +50 -0
- package/scripts/postinstall.mjs +83 -0
- package/src/bindings/ast_scanner.rs +950 -0
- package/src/bindings/cli.rs +49 -0
- package/src/bindings/jsonc.rs +166 -0
- package/src/bindings/mod.rs +7 -0
- package/src/bindings/reporter.rs +328 -0
- package/src/bindings/types.rs +129 -0
- package/src/bindings/validator.rs +227 -0
- package/src/bindings/wrangler.rs +647 -0
- package/src/cli.rs +77 -0
- package/src/lib.rs +7 -0
- package/src/main.rs +451 -0
- package/src/origin/cli.rs +92 -0
- package/src/origin/cloudflare.rs +170 -0
- package/src/origin/confidence.rs +320 -0
- package/src/origin/crtsh.rs +144 -0
- package/src/origin/dns.rs +177 -0
- package/src/origin/enumerator.rs +271 -0
- package/src/origin/error.rs +19 -0
- package/src/origin/mock.rs +320 -0
- package/src/origin/mod.rs +19 -0
- package/src/origin/models.rs +167 -0
- package/src/origin/prober.rs +260 -0
- package/src/origin/remediation.rs +73 -0
- package/src/origin/report.rs +625 -0
- package/src/origin/scanner.rs +217 -0
- package/src/secrets/cli.rs +94 -0
- package/src/secrets/env_parser.rs +464 -0
- package/src/secrets/ignore.rs +139 -0
- package/src/secrets/mod.rs +14 -0
- package/src/secrets/report/json_format.rs +97 -0
- package/src/secrets/report/mod.rs +48 -0
- package/src/secrets/report/sarif.rs +225 -0
- package/src/secrets/report/text.rs +105 -0
- package/src/secrets/rules/builtin.rs +280 -0
- package/src/secrets/rules/entropy.rs +66 -0
- package/src/secrets/rules/mod.rs +7 -0
- package/src/secrets/rules/types.rs +183 -0
- package/src/secrets/scanner.rs +444 -0
- package/src/zone/cli.rs +111 -0
- package/src/zone/client/cf_client.rs +405 -0
- package/src/zone/client/mod.rs +5 -0
- package/src/zone/client/provider.rs +12 -0
- package/src/zone/mock_data.rs +481 -0
- package/src/zone/mod.rs +125 -0
- package/src/zone/models/audit.rs +194 -0
- package/src/zone/models/cloudflare.rs +252 -0
- package/src/zone/models/mod.rs +7 -0
- package/src/zone/models/sarif.rs +89 -0
- package/src/zone/reporters/html_rep.rs +345 -0
- package/src/zone/reporters/json_rep.rs +7 -0
- package/src/zone/reporters/mod.rs +9 -0
- package/src/zone/reporters/sarif_rep.rs +100 -0
- package/src/zone/reporters/terminal.rs +322 -0
- package/src/zone/rules/definitions.rs +201 -0
- package/src/zone/rules/evaluator.rs +484 -0
- package/src/zone/rules/mod.rs +5 -0
- package/src/zone/scoring.rs +104 -0
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
use chrono::{DateTime, Utc};
|
|
2
|
+
use serde::{Deserialize, Serialize};
|
|
3
|
+
use std::fmt;
|
|
4
|
+
|
|
5
|
+
/// Security risk severity level
|
|
6
|
+
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
|
|
7
|
+
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
|
|
8
|
+
pub enum RiskLevel {
|
|
9
|
+
Info,
|
|
10
|
+
Low,
|
|
11
|
+
Medium,
|
|
12
|
+
High,
|
|
13
|
+
Critical,
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
impl fmt::Display for RiskLevel {
|
|
17
|
+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
18
|
+
match self {
|
|
19
|
+
RiskLevel::Critical => write!(f, "CRITICAL"),
|
|
20
|
+
RiskLevel::High => write!(f, "HIGH"),
|
|
21
|
+
RiskLevel::Medium => write!(f, "MEDIUM"),
|
|
22
|
+
RiskLevel::Low => write!(f, "LOW"),
|
|
23
|
+
RiskLevel::Info => write!(f, "INFO"),
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
impl RiskLevel {
|
|
29
|
+
pub fn badge_str(&self) -> &'static str {
|
|
30
|
+
match self {
|
|
31
|
+
RiskLevel::Critical => "CRITICAL",
|
|
32
|
+
RiskLevel::High => "HIGH",
|
|
33
|
+
RiskLevel::Medium => "MEDIUM",
|
|
34
|
+
RiskLevel::Low => "LOW",
|
|
35
|
+
RiskLevel::Info => "INFO",
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/// Category of security check
|
|
41
|
+
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
|
42
|
+
#[serde(rename_all = "snake_case")]
|
|
43
|
+
pub enum RuleCategory {
|
|
44
|
+
SslTls,
|
|
45
|
+
HttpsEnforcement,
|
|
46
|
+
Hsts,
|
|
47
|
+
WafSecurity,
|
|
48
|
+
BotManagement,
|
|
49
|
+
Dnssec,
|
|
50
|
+
AccessControl,
|
|
51
|
+
SecurityLevel,
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
impl fmt::Display for RuleCategory {
|
|
55
|
+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
56
|
+
match self {
|
|
57
|
+
RuleCategory::SslTls => write!(f, "SSL/TLS Configuration"),
|
|
58
|
+
RuleCategory::HttpsEnforcement => write!(f, "HTTPS Enforcement"),
|
|
59
|
+
RuleCategory::Hsts => write!(f, "HSTS Security Headers"),
|
|
60
|
+
RuleCategory::WafSecurity => write!(f, "WAF & Managed Rules"),
|
|
61
|
+
RuleCategory::BotManagement => write!(f, "Bot Management"),
|
|
62
|
+
RuleCategory::Dnssec => write!(f, "DNSSEC"),
|
|
63
|
+
RuleCategory::AccessControl => write!(f, "Access Rules & Lockdown"),
|
|
64
|
+
RuleCategory::SecurityLevel => write!(f, "Zone Security Level"),
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/// A specific security finding detected during the zone audit
|
|
70
|
+
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
|
|
71
|
+
pub struct AuditFinding {
|
|
72
|
+
pub rule_id: String,
|
|
73
|
+
pub rule_name: String,
|
|
74
|
+
pub category: RuleCategory,
|
|
75
|
+
pub risk_level: RiskLevel,
|
|
76
|
+
pub title: String,
|
|
77
|
+
pub description: String,
|
|
78
|
+
pub actual_value: String,
|
|
79
|
+
pub expected_value: String,
|
|
80
|
+
pub remediation: String,
|
|
81
|
+
pub score_penalty: u32,
|
|
82
|
+
pub doc_url: Option<String>,
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/// Summary of key settings for clean display in tables and reports
|
|
86
|
+
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Default)]
|
|
87
|
+
pub struct ZoneSettingsSummary {
|
|
88
|
+
pub ssl_mode: String,
|
|
89
|
+
pub min_tls: String,
|
|
90
|
+
pub always_https: String,
|
|
91
|
+
pub hsts_status: String,
|
|
92
|
+
pub dnssec_status: String,
|
|
93
|
+
pub waf_status: String,
|
|
94
|
+
pub bot_fight_mode: String,
|
|
95
|
+
pub security_level: String,
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/// Complete audit report for a single Cloudflare Zone
|
|
99
|
+
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
|
|
100
|
+
pub struct ZoneAuditReport {
|
|
101
|
+
pub zone_id: String,
|
|
102
|
+
pub zone_name: String,
|
|
103
|
+
pub plan_name: String,
|
|
104
|
+
pub status: String,
|
|
105
|
+
pub score: u32,
|
|
106
|
+
pub grade: String,
|
|
107
|
+
pub passed_checks_count: usize,
|
|
108
|
+
pub total_checks_count: usize,
|
|
109
|
+
pub settings_summary: ZoneSettingsSummary,
|
|
110
|
+
pub findings: Vec<AuditFinding>,
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
impl ZoneAuditReport {
|
|
114
|
+
pub fn count_by_severity(&self, severity: RiskLevel) -> usize {
|
|
115
|
+
self.findings
|
|
116
|
+
.iter()
|
|
117
|
+
.filter(|f| f.risk_level == severity)
|
|
118
|
+
.count()
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
pub fn has_critical(&self) -> bool {
|
|
122
|
+
self.findings
|
|
123
|
+
.iter()
|
|
124
|
+
.any(|f| f.risk_level == RiskLevel::Critical)
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
pub fn has_high_or_critical(&self) -> bool {
|
|
128
|
+
self.findings
|
|
129
|
+
.iter()
|
|
130
|
+
.any(|f| f.risk_level == RiskLevel::Critical || f.risk_level == RiskLevel::High)
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/// Breakdown of findings count by severity
|
|
135
|
+
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Default)]
|
|
136
|
+
pub struct SeverityCounts {
|
|
137
|
+
pub critical: usize,
|
|
138
|
+
pub high: usize,
|
|
139
|
+
pub medium: usize,
|
|
140
|
+
pub low: usize,
|
|
141
|
+
pub info: usize,
|
|
142
|
+
pub total: usize,
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/// Aggregated multi-zone compliance and security audit report
|
|
146
|
+
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
|
|
147
|
+
pub struct AggregateAuditReport {
|
|
148
|
+
pub timestamp: DateTime<Utc>,
|
|
149
|
+
pub account_id: Option<String>,
|
|
150
|
+
pub total_zones: usize,
|
|
151
|
+
pub average_score: f64,
|
|
152
|
+
pub overall_grade: String,
|
|
153
|
+
pub total_findings: SeverityCounts,
|
|
154
|
+
pub zone_reports: Vec<ZoneAuditReport>,
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
impl AggregateAuditReport {
|
|
158
|
+
pub fn new(zone_reports: Vec<ZoneAuditReport>, account_id: Option<String>) -> Self {
|
|
159
|
+
let total_zones = zone_reports.len();
|
|
160
|
+
let average_score = if total_zones == 0 {
|
|
161
|
+
100.0
|
|
162
|
+
} else {
|
|
163
|
+
let sum: u32 = zone_reports.iter().map(|z| z.score).sum();
|
|
164
|
+
(sum as f64) / (total_zones as f64)
|
|
165
|
+
};
|
|
166
|
+
|
|
167
|
+
let overall_grade =
|
|
168
|
+
crate::zone::scoring::calculate_grade(average_score.round() as u32).to_string();
|
|
169
|
+
|
|
170
|
+
let mut total_findings = SeverityCounts::default();
|
|
171
|
+
for z in &zone_reports {
|
|
172
|
+
for f in &z.findings {
|
|
173
|
+
total_findings.total += 1;
|
|
174
|
+
match f.risk_level {
|
|
175
|
+
RiskLevel::Critical => total_findings.critical += 1,
|
|
176
|
+
RiskLevel::High => total_findings.high += 1,
|
|
177
|
+
RiskLevel::Medium => total_findings.medium += 1,
|
|
178
|
+
RiskLevel::Low => total_findings.low += 1,
|
|
179
|
+
RiskLevel::Info => total_findings.info += 1,
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
Self {
|
|
185
|
+
timestamp: Utc::now(),
|
|
186
|
+
account_id,
|
|
187
|
+
total_zones,
|
|
188
|
+
average_score: (average_score * 10.0).round() / 10.0,
|
|
189
|
+
overall_grade,
|
|
190
|
+
total_findings,
|
|
191
|
+
zone_reports,
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
}
|
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
use serde::{Deserialize, Serialize};
|
|
2
|
+
|
|
3
|
+
/// Account summary information associated with a zone
|
|
4
|
+
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Default)]
|
|
5
|
+
pub struct AccountInfo {
|
|
6
|
+
pub id: String,
|
|
7
|
+
pub name: String,
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
/// Cloudflare Plan information (e.g. Free, Pro, Business, Enterprise)
|
|
11
|
+
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Default)]
|
|
12
|
+
pub struct PlanInfo {
|
|
13
|
+
pub id: Option<String>,
|
|
14
|
+
pub name: Option<String>,
|
|
15
|
+
pub price: Option<i64>,
|
|
16
|
+
pub currency: Option<String>,
|
|
17
|
+
pub is_subscribed: Option<bool>,
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/// Cloudflare Zone object
|
|
21
|
+
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Default)]
|
|
22
|
+
pub struct Zone {
|
|
23
|
+
pub id: String,
|
|
24
|
+
pub name: String,
|
|
25
|
+
pub status: String,
|
|
26
|
+
#[serde(default)]
|
|
27
|
+
pub paused: bool,
|
|
28
|
+
#[serde(rename = "type")]
|
|
29
|
+
pub zone_type: Option<String>,
|
|
30
|
+
pub development_mode: Option<i64>,
|
|
31
|
+
pub name_servers: Option<Vec<String>>,
|
|
32
|
+
pub account: Option<AccountInfo>,
|
|
33
|
+
pub plan: Option<PlanInfo>,
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/// Strict Transport Security (HSTS) configuration within security_header
|
|
37
|
+
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Default)]
|
|
38
|
+
pub struct HstsSetting {
|
|
39
|
+
#[serde(default)]
|
|
40
|
+
pub enabled: bool,
|
|
41
|
+
pub max_age: Option<u64>,
|
|
42
|
+
#[serde(default)]
|
|
43
|
+
pub include_subdomains: Option<bool>,
|
|
44
|
+
#[serde(default)]
|
|
45
|
+
pub preload: Option<bool>,
|
|
46
|
+
#[serde(default)]
|
|
47
|
+
pub nosniff: Option<bool>,
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/// Security header setting wrapper
|
|
51
|
+
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Default)]
|
|
52
|
+
pub struct SecurityHeaderSetting {
|
|
53
|
+
pub strict_transport_security: Option<HstsSetting>,
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/// Zone DNSSEC details
|
|
57
|
+
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Default)]
|
|
58
|
+
pub struct DnssecSetting {
|
|
59
|
+
#[serde(default = "default_dnssec_status")]
|
|
60
|
+
pub status: String,
|
|
61
|
+
pub flags: Option<u32>,
|
|
62
|
+
pub algorithm: Option<String>,
|
|
63
|
+
pub key_type: Option<String>,
|
|
64
|
+
pub digest_type: Option<String>,
|
|
65
|
+
pub digest_algorithm: Option<String>,
|
|
66
|
+
pub digest: Option<String>,
|
|
67
|
+
pub ds: Option<String>,
|
|
68
|
+
pub key_tag: Option<u32>,
|
|
69
|
+
pub public_key: Option<String>,
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
fn default_dnssec_status() -> String {
|
|
73
|
+
"disabled".to_string()
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/// WAF Package representation
|
|
77
|
+
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Default)]
|
|
78
|
+
pub struct WafPackage {
|
|
79
|
+
pub id: String,
|
|
80
|
+
pub name: String,
|
|
81
|
+
pub description: Option<String>,
|
|
82
|
+
pub detection_mode: Option<String>,
|
|
83
|
+
pub zone_id: Option<String>,
|
|
84
|
+
pub status: Option<String>,
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/// Ruleset representation for Modern WAF
|
|
88
|
+
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Default)]
|
|
89
|
+
pub struct RulesetInfo {
|
|
90
|
+
pub id: String,
|
|
91
|
+
pub name: String,
|
|
92
|
+
pub phase: Option<String>,
|
|
93
|
+
pub kind: Option<String>,
|
|
94
|
+
pub description: Option<String>,
|
|
95
|
+
pub rules_count: Option<usize>,
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/// Aggregated WAF Settings
|
|
99
|
+
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Default)]
|
|
100
|
+
pub struct WafSetting {
|
|
101
|
+
#[serde(default)]
|
|
102
|
+
pub waf_enabled: bool,
|
|
103
|
+
#[serde(default)]
|
|
104
|
+
pub managed_rules_active: bool,
|
|
105
|
+
#[serde(default)]
|
|
106
|
+
pub packages: Vec<WafPackage>,
|
|
107
|
+
#[serde(default)]
|
|
108
|
+
pub rulesets: Vec<RulesetInfo>,
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/// Bot Management / Bot Fight Mode configuration
|
|
112
|
+
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Default)]
|
|
113
|
+
pub struct BotManagementSetting {
|
|
114
|
+
#[serde(default)]
|
|
115
|
+
pub fight_mode: bool,
|
|
116
|
+
#[serde(default)]
|
|
117
|
+
pub using_latest_model: Option<bool>,
|
|
118
|
+
#[serde(default)]
|
|
119
|
+
pub optimize_wordpress: Option<bool>,
|
|
120
|
+
pub sbfm_definitely_automated: Option<String>,
|
|
121
|
+
pub sbfm_likely_automated: Option<String>,
|
|
122
|
+
pub sbfm_verified_bots: Option<String>,
|
|
123
|
+
pub sbfm_static_resource_protection: Option<bool>,
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/// Rate limiting rule definition
|
|
127
|
+
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Default)]
|
|
128
|
+
pub struct RateLimitRule {
|
|
129
|
+
pub id: String,
|
|
130
|
+
pub disabled: Option<bool>,
|
|
131
|
+
pub description: Option<String>,
|
|
132
|
+
pub threshold: Option<u32>,
|
|
133
|
+
pub period: Option<u32>,
|
|
134
|
+
pub action: Option<String>,
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/// Rate limiting settings
|
|
138
|
+
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Default)]
|
|
139
|
+
pub struct RateLimitSetting {
|
|
140
|
+
#[serde(default)]
|
|
141
|
+
pub rules: Vec<RateLimitRule>,
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/// Zone lockdown configuration
|
|
145
|
+
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Default)]
|
|
146
|
+
pub struct ZoneLockdownRule {
|
|
147
|
+
pub id: String,
|
|
148
|
+
pub paused: Option<bool>,
|
|
149
|
+
pub description: Option<String>,
|
|
150
|
+
pub urls: Vec<String>,
|
|
151
|
+
pub configurations: Vec<LockdownConfig>,
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Default)]
|
|
155
|
+
pub struct LockdownConfig {
|
|
156
|
+
pub target: String,
|
|
157
|
+
pub value: String,
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/// Zone Lockdown summary
|
|
161
|
+
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Default)]
|
|
162
|
+
pub struct ZoneLockdownSetting {
|
|
163
|
+
#[serde(default)]
|
|
164
|
+
pub rules: Vec<ZoneLockdownRule>,
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
/// IP Access / Firewall Rule
|
|
168
|
+
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Default)]
|
|
169
|
+
pub struct IpAccessRule {
|
|
170
|
+
pub id: String,
|
|
171
|
+
pub mode: String, // "block", "challenge", "whitelist", "js_challenge", "managed_challenge"
|
|
172
|
+
pub configuration: IpAccessConfig,
|
|
173
|
+
pub notes: Option<String>,
|
|
174
|
+
pub paused: Option<bool>,
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Default)]
|
|
178
|
+
pub struct IpAccessConfig {
|
|
179
|
+
pub target: String, // "ip", "ip_range", "asn", "country"
|
|
180
|
+
pub value: String,
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
/// IP Access Rules list
|
|
184
|
+
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Default)]
|
|
185
|
+
pub struct IpAccessRulesSetting {
|
|
186
|
+
#[serde(default)]
|
|
187
|
+
pub rules: Vec<IpAccessRule>,
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
/// Core Zone Settings (SSL, Min TLS, Always HTTPS, etc.)
|
|
191
|
+
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Default)]
|
|
192
|
+
pub struct ZoneSettings {
|
|
193
|
+
pub ssl: Option<String>, // "off", "flexible", "full", "strict"
|
|
194
|
+
pub min_tls_version: Option<String>, // "1.0", "1.1", "1.2", "1.3"
|
|
195
|
+
pub tls_1_3: Option<String>, // "on", "off", "zrt"
|
|
196
|
+
pub always_use_https: Option<String>, // "on", "off"
|
|
197
|
+
pub automatic_https_rewrites: Option<String>, // "on", "off"
|
|
198
|
+
pub opportunistic_encryption: Option<String>, // "on", "off"
|
|
199
|
+
pub security_header: Option<SecurityHeaderSetting>,
|
|
200
|
+
pub security_level: Option<String>, // "essentially_off", "low", "medium", "high", "under_attack"
|
|
201
|
+
pub browser_check: Option<String>, // "on", "off"
|
|
202
|
+
pub challenge_ttl: Option<i64>,
|
|
203
|
+
pub brotli: Option<String>,
|
|
204
|
+
pub early_hints: Option<String>,
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
/// Complete dataset gathered for a single Cloudflare Zone
|
|
208
|
+
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Default)]
|
|
209
|
+
pub struct ZoneAuditData {
|
|
210
|
+
pub zone: Zone,
|
|
211
|
+
pub settings: ZoneSettings,
|
|
212
|
+
pub dnssec: DnssecSetting,
|
|
213
|
+
pub waf: WafSetting,
|
|
214
|
+
pub bot_management: BotManagementSetting,
|
|
215
|
+
pub rate_limits: RateLimitSetting,
|
|
216
|
+
pub lockdowns: ZoneLockdownSetting,
|
|
217
|
+
pub ip_access_rules: IpAccessRulesSetting,
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
/// Standard Cloudflare API Response Envelope
|
|
221
|
+
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
222
|
+
pub struct ApiResponse<T> {
|
|
223
|
+
pub success: bool,
|
|
224
|
+
pub errors: Option<Vec<ApiMessage>>,
|
|
225
|
+
pub messages: Option<Vec<ApiMessage>>,
|
|
226
|
+
pub result: Option<T>,
|
|
227
|
+
pub result_info: Option<ResultInfo>,
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
231
|
+
pub struct ApiMessage {
|
|
232
|
+
pub code: Option<i64>,
|
|
233
|
+
pub message: String,
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
237
|
+
pub struct ResultInfo {
|
|
238
|
+
pub page: Option<u32>,
|
|
239
|
+
pub per_page: Option<u32>,
|
|
240
|
+
pub count: Option<u32>,
|
|
241
|
+
pub total_count: Option<u32>,
|
|
242
|
+
pub total_pages: Option<u32>,
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
/// Single setting item returned from /zones/{id}/settings
|
|
246
|
+
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
247
|
+
pub struct SettingItem {
|
|
248
|
+
pub id: String,
|
|
249
|
+
pub value: serde_json::Value,
|
|
250
|
+
pub editable: Option<bool>,
|
|
251
|
+
pub modified_on: Option<String>,
|
|
252
|
+
}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
use serde::{Deserialize, Serialize};
|
|
2
|
+
|
|
3
|
+
/// SARIF v2.1.0 root structure
|
|
4
|
+
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
5
|
+
pub struct SarifReport {
|
|
6
|
+
#[serde(rename = "$schema")]
|
|
7
|
+
pub schema: String,
|
|
8
|
+
pub version: String,
|
|
9
|
+
pub runs: Vec<SarifRun>,
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
13
|
+
pub struct SarifRun {
|
|
14
|
+
pub tool: SarifTool,
|
|
15
|
+
pub results: Vec<SarifResult>,
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
19
|
+
pub struct SarifTool {
|
|
20
|
+
pub driver: SarifDriver,
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
24
|
+
pub struct SarifDriver {
|
|
25
|
+
pub name: String,
|
|
26
|
+
pub version: String,
|
|
27
|
+
#[serde(rename = "informationUri")]
|
|
28
|
+
pub information_uri: String,
|
|
29
|
+
pub rules: Vec<SarifRuleDescriptor>,
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
33
|
+
pub struct SarifRuleDescriptor {
|
|
34
|
+
pub id: String,
|
|
35
|
+
pub name: String,
|
|
36
|
+
#[serde(rename = "shortDescription")]
|
|
37
|
+
pub short_description: SarifMessage,
|
|
38
|
+
#[serde(rename = "fullDescription")]
|
|
39
|
+
pub full_description: SarifMessage,
|
|
40
|
+
#[serde(rename = "defaultConfiguration")]
|
|
41
|
+
pub default_configuration: SarifRuleConfiguration,
|
|
42
|
+
#[serde(rename = "helpUri", skip_serializing_if = "Option::is_none")]
|
|
43
|
+
pub help_uri: Option<String>,
|
|
44
|
+
pub properties: Option<SarifProperties>,
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
48
|
+
pub struct SarifProperties {
|
|
49
|
+
pub tags: Vec<String>,
|
|
50
|
+
pub precision: String,
|
|
51
|
+
#[serde(rename = "security-severity")]
|
|
52
|
+
pub security_severity: Option<String>,
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
56
|
+
pub struct SarifRuleConfiguration {
|
|
57
|
+
pub level: String, // "error", "warning", "note", "none"
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
61
|
+
pub struct SarifResult {
|
|
62
|
+
#[serde(rename = "ruleId")]
|
|
63
|
+
pub rule_id: String,
|
|
64
|
+
pub level: String,
|
|
65
|
+
pub message: SarifMessage,
|
|
66
|
+
pub locations: Vec<SarifLocation>,
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
70
|
+
pub struct SarifMessage {
|
|
71
|
+
pub text: String,
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
75
|
+
pub struct SarifLocation {
|
|
76
|
+
#[serde(rename = "physicalLocation")]
|
|
77
|
+
pub physical_location: SarifPhysicalLocation,
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
81
|
+
pub struct SarifPhysicalLocation {
|
|
82
|
+
#[serde(rename = "artifactLocation")]
|
|
83
|
+
pub artifact_location: SarifArtifactLocation,
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
87
|
+
pub struct SarifArtifactLocation {
|
|
88
|
+
pub uri: String,
|
|
89
|
+
}
|