@anonympins/fingerprint 0.7.4 → 0.8.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/CHANGELOG.md +59 -0
- package/README.md +1 -1
- package/package.json +1 -1
- package/public/anonympins-bot-mitigation-pow.zip +0 -0
- package/src/js/dynamic-wasm.js +218 -218
- package/src/js/fingerprint.client.js +1784 -1738
- package/src/js/fingerprint.client.obfuscated.js +1 -1
- package/src/js/fingerprint.js +489 -99
- package/src/js/fingerprint.utils.js +252 -2
- package/src/js/pow.worker.js +2 -2
- package/src/js/tests/cross_parity.test.js +3 -3
- package/src/js/tests/dns-circuit-breaker.test.js +6 -6
- package/src/js/tests/dynamic-wasm.test.js +77 -77
- package/src/js/tests/fingerprint.builder.test.js +76 -78
- package/src/js/tests/fingerprint.client.init.test.js +78 -0
- package/src/js/tests/fingerprint.client.test.js +16 -17
- package/src/js/tests/fingerprint.test.js +37 -12
- package/src/js/tests/ja3AnomalyDetector.test.js +135 -136
- package/src/js/tests/library.test.js +94 -95
- package/src/js/tests/obfuscation.test.js +8 -8
- package/src/js/tests/quicFingerprint.test.js +47 -0
- package/src/js/tests/tcpFingerprint.test.js +4 -4
- package/src/js/tests/threatIntel.test.js +40 -1
- package/src/js/upow-model-task.js +155 -112
- package/src/php/Challenge/ChallengeUtils.php +392 -86
- package/src/php/Config/SecurityProfiles.php +79 -61
- package/src/php/DirectFingerprint.php +55 -8
- package/src/php/FingerprintBuilder.php +13 -13
- package/src/php/FingerprintClient.php +6 -6
- package/src/php/FingerprintEngine.php +2122 -1690
- package/src/php/Ja3AnomalyDetector.php +22 -22
- package/src/php/Optimization/FunctionRegistry.php +4 -4
- package/src/php/Optimization/Optimization.php +6 -6
- package/src/php/RequestContext.php +11 -11
- package/src/php/Store/InMemoryStore.php +96 -66
- package/src/php/Store/MongoDbStore.php +2 -2
- package/src/php/Store/RedisStore.php +1 -1
- package/src/php/Store/StoreManager.php +48 -35
- package/src/php/Tests/ChallengeUtilsTest.php +31 -0
- package/src/php/Tests/DnsCircuitBreakerTest.php +105 -105
- package/src/php/Tests/FingerprintClientTest.php +70 -70
- package/src/php/Tests/PowTest.php +37 -39
- package/src/php/Tests/QuicFingerprintTest.php +115 -53
- package/src/php/Tests/ThreatIntelTest.php +34 -0
- package/src/php/Utils/BigInt.php +202 -202
- package/src/php/Utils/BlockList.php +13 -13
- package/src/php/Utils/Logger.php +19 -1
- package/src/php/Utils/MaliciousPatterns.php +6 -6
- package/src/php/Utils/MetricsManager.php +209 -209
- package/src/php/Utils/RequestUtils.php +362 -1
- package/src/php/Utils/TLSClientHelloParser.php +385 -369
- package/src/php/WordPress/WpDbStore.php +7 -7
- package/src/php/WordPress/anonympins-bot-mitigation-pow.php +1121 -0
- package/src/php/WordPress/fingerprint-anti-bot.php +0 -559
- package/src/php/WordPress/languages/anonympins-bot-mitigation-pow-fr_FR.mo +0 -0
- package/src/php/WordPress/languages/anonympins-bot-mitigation-pow-fr_FR.po +232 -0
- package/src/php/WordPress/languages/fingerprint-wordpress-de_DE.mo +0 -0
- package/src/php/WordPress/languages/fingerprint-wordpress-de_DE.po +297 -261
- package/src/php/WordPress/languages/fingerprint-wordpress-fr_FR.mo +0 -0
- package/src/php/WordPress/languages/fingerprint-wordpress-fr_FR.po +348 -267
- package/src/php/WordPress/package.php +80 -101
- package/src/php/WordPress/readme.txt +21 -5
- package/src/php/bin/auto-tune.php +1 -1
- package/public/fingerprint-anti-bot.zip +0 -0
|
@@ -1,210 +1,210 @@
|
|
|
1
|
-
<?php
|
|
2
|
-
|
|
3
|
-
declare(strict_types=1);
|
|
4
|
-
|
|
5
|
-
namespace Anonympins\Fingerprint\Utils;
|
|
6
|
-
|
|
7
|
-
class MetricsManager
|
|
8
|
-
{
|
|
9
|
-
/** @var array
|
|
10
|
-
private static array $counters = [];
|
|
11
|
-
|
|
12
|
-
/** @var array
|
|
13
|
-
private static array $observations = [];
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
* @param string $name
|
|
19
|
-
* @param array $labels
|
|
20
|
-
*/
|
|
21
|
-
public static function incrementCounter(string $name, array $labels = []): void
|
|
22
|
-
{
|
|
23
|
-
if (strpos($name, 'fingerprint_') !== 0) {
|
|
24
|
-
$name = 'fingerprint_' . $name;
|
|
25
|
-
}
|
|
26
|
-
ksort($labels);
|
|
27
|
-
$labelPairs = [];
|
|
28
|
-
foreach ($labels as $k => $v) {
|
|
29
|
-
$labelPairs[] = "{$k}=\"{$v}\"";
|
|
30
|
-
}
|
|
31
|
-
$labelsStr = !empty($labelPairs) ? '{' . implode(',', $labelPairs) . '}' : '';
|
|
32
|
-
$key = $name . $labelsStr;
|
|
33
|
-
|
|
34
|
-
if (!isset(self::$counters[$key])) {
|
|
35
|
-
self::$counters[$key] = [
|
|
36
|
-
'name' => $name,
|
|
37
|
-
'labelsStr' => $labelsStr,
|
|
38
|
-
'value' => 0
|
|
39
|
-
];
|
|
40
|
-
}
|
|
41
|
-
self::$counters[$key]['value']++;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
/**
|
|
45
|
-
*
|
|
46
|
-
*
|
|
47
|
-
* @param string $name
|
|
48
|
-
* @param float $value
|
|
49
|
-
* @param array $labels
|
|
50
|
-
*/
|
|
51
|
-
public static function observeValue(string $name, float $value, array $labels = []): void
|
|
52
|
-
{
|
|
53
|
-
if (strpos($name, 'fingerprint_') !== 0) {
|
|
54
|
-
$name = 'fingerprint_' . $name;
|
|
55
|
-
}
|
|
56
|
-
ksort($labels);
|
|
57
|
-
$labelPairs = [];
|
|
58
|
-
foreach ($labels as $k => $v) {
|
|
59
|
-
$labelPairs[] = "{$k}=\"{$v}\"";
|
|
60
|
-
}
|
|
61
|
-
$labelsStr = !empty($labelPairs) ? '{' . implode(',', $labelPairs) . '}' : '';
|
|
62
|
-
$key = $name . $labelsStr;
|
|
63
|
-
|
|
64
|
-
self::$observations[$key] = [
|
|
65
|
-
'name' => $name,
|
|
66
|
-
'labelsStr' => $labelsStr,
|
|
67
|
-
'value' => $value
|
|
68
|
-
];
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
/**
|
|
72
|
-
* Helper method to retrieve a specific metric's values by name.
|
|
73
|
-
*
|
|
74
|
-
* @param string $name Name of the metric.
|
|
75
|
-
* @param array $securityConfig The security configuration.
|
|
76
|
-
* @return array Associative array of labels to values.
|
|
77
|
-
*/
|
|
78
|
-
public static function getMetric(string $name, array $securityConfig = []): array
|
|
79
|
-
{
|
|
80
|
-
$result = [];
|
|
81
|
-
$queryName = str_starts_with($name, 'fingerprint_') ? $name : 'fingerprint_' . $name;
|
|
82
|
-
|
|
83
|
-
if ($queryName === 'fingerprint_security_weight') {
|
|
84
|
-
$weights = $securityConfig['weights'] ?? [];
|
|
85
|
-
foreach ($weights as $indicator => $weight) {
|
|
86
|
-
if (is_numeric($weight)) {
|
|
87
|
-
$result[$indicator] = (float)$weight;
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
} elseif ($queryName === 'fingerprint_security_threshold') {
|
|
91
|
-
$thresholds = $securityConfig['thresholds'] ?? [];
|
|
92
|
-
foreach ($thresholds as $level => $threshold) {
|
|
93
|
-
if (is_numeric($threshold)) {
|
|
94
|
-
$result[$level] = (float)$threshold;
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
} else {
|
|
98
|
-
foreach (self::$counters as $counter) {
|
|
99
|
-
if ($counter['name'] === $queryName || $counter['name'] === $name) {
|
|
100
|
-
$labelStr = trim($counter['labelsStr'], '{}');
|
|
101
|
-
$result[$labelStr !== '' ? $labelStr : 'value'] = $counter['value'];
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
foreach (self::$observations as $obs) {
|
|
105
|
-
if ($obs['name'] === $queryName || $obs['name'] === $name) {
|
|
106
|
-
$labelStr = trim($obs['labelsStr'], '{}');
|
|
107
|
-
$result[$labelStr !== '' ? $labelStr : 'value'] = $obs['value'];
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
return $result;
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
/**
|
|
115
|
-
*
|
|
116
|
-
*/
|
|
117
|
-
public static function clearMetrics(): void
|
|
118
|
-
{
|
|
119
|
-
self::$counters = [];
|
|
120
|
-
self::$observations = [];
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
/**
|
|
124
|
-
*
|
|
125
|
-
*
|
|
126
|
-
* @param array $securityConfig
|
|
127
|
-
* @param array|null $lastBestSolution
|
|
128
|
-
* @return string
|
|
129
|
-
*/
|
|
130
|
-
public static function getPrometheusMetrics(array $securityConfig = [], ?array $lastBestSolution = null): string
|
|
131
|
-
{
|
|
132
|
-
$metrics = "";
|
|
133
|
-
|
|
134
|
-
if (empty(self::$counters)) {
|
|
135
|
-
$metrics .= "# HELP fingerprint_requests_total Total requests processed.\n";
|
|
136
|
-
$metrics .= "# TYPE fingerprint_requests_total counter\n";
|
|
137
|
-
$metrics .= "fingerprint_requests_total{status=\"passed\"} 1\n";
|
|
138
|
-
} else {
|
|
139
|
-
$grouped = [];
|
|
140
|
-
foreach (self::$counters as $c) {
|
|
141
|
-
$grouped[$c['name']][] = $c;
|
|
142
|
-
}
|
|
143
|
-
foreach ($grouped as $name => $instances) {
|
|
144
|
-
$metrics .= "# HELP {$name} Total requests processed.\n";
|
|
145
|
-
$metrics .= "# TYPE {$name} counter\n";
|
|
146
|
-
foreach ($instances as $instance) {
|
|
147
|
-
$metrics .= "{$name}{$instance['labelsStr']} {$instance['value']}\n";
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
// Export
|
|
153
|
-
if (!empty(self::$observations)) {
|
|
154
|
-
$groupedObs = [];
|
|
155
|
-
foreach (self::$observations as $obs) {
|
|
156
|
-
$groupedObs[$obs['name']][] = $obs;
|
|
157
|
-
}
|
|
158
|
-
foreach ($groupedObs as $name => $instances) {
|
|
159
|
-
$metrics .= "\n# HELP {$name} Value observation.\n";
|
|
160
|
-
$metrics .= "# TYPE {$name} gauge\n";
|
|
161
|
-
foreach ($instances as $instance) {
|
|
162
|
-
$metrics .= "{$name}{$instance['labelsStr']} {$instance['value']}\n";
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
// 1. Export
|
|
168
|
-
if (isset($securityConfig['weights']) && is_array($securityConfig['weights'])) {
|
|
169
|
-
$metrics .= "\n# HELP fingerprint_security_weight Active weight for each suspicion indicator.\n";
|
|
170
|
-
$metrics .= "# TYPE fingerprint_security_weight gauge\n";
|
|
171
|
-
foreach ($securityConfig['weights'] as $indicator => $weight) {
|
|
172
|
-
if (is_numeric($weight)) {
|
|
173
|
-
$metrics .= "fingerprint_security_weight{indicator=\"{$indicator}\"} {$weight}\n";
|
|
174
|
-
}
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
// 2. Export
|
|
179
|
-
if (isset($securityConfig['thresholds']) && is_array($securityConfig['thresholds'])) {
|
|
180
|
-
$metrics .= "\n# HELP fingerprint_security_threshold Active score threshold for each enforcement action level.\n";
|
|
181
|
-
$metrics .= "# TYPE fingerprint_security_threshold gauge\n";
|
|
182
|
-
foreach ($securityConfig['thresholds'] as $level => $threshold) {
|
|
183
|
-
if (is_numeric($threshold)) {
|
|
184
|
-
$metrics .= "fingerprint_security_threshold{level=\"{$level}\"} {$threshold}\n";
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
// 3.
|
|
190
|
-
if ($lastBestSolution === null && isset($securityConfig['autotuning']['savePath'])) {
|
|
191
|
-
$savePath = $securityConfig['autotuning']['savePath'];
|
|
192
|
-
if (file_exists($savePath)) {
|
|
193
|
-
$savedData = json_decode(file_get_contents($savePath), true);
|
|
194
|
-
if (is_array($savedData) && isset($savedData['objectives'])) {
|
|
195
|
-
$lastBestSolution = $savedData;
|
|
196
|
-
}
|
|
197
|
-
}
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
// 4. Export
|
|
201
|
-
if ($lastBestSolution !== null && isset($lastBestSolution['objectives']) && is_array($lastBestSolution['objectives'])) {
|
|
202
|
-
$fpr = $lastBestSolution['objectives'][0] ?? 0.0;
|
|
203
|
-
$fnr = $lastBestSolution['objectives'][1] ?? 0.0;
|
|
204
|
-
$metrics .= "\n# HELP fingerprint_autotuning_false_positive_rate Current false positive rate calculated by the auto-tuner.\n# TYPE fingerprint_autotuning_false_positive_rate gauge\nfingerprint_autotuning_false_positive_rate {$fpr}\n";
|
|
205
|
-
$metrics .= "\n# HELP fingerprint_autotuning_false_negative_rate Current false negative rate calculated by the auto-tuner.\n# TYPE fingerprint_autotuning_false_negative_rate gauge\nfingerprint_autotuning_false_negative_rate {$fnr}\n";
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
return $metrics;
|
|
209
|
-
}
|
|
1
|
+
<?php
|
|
2
|
+
|
|
3
|
+
declare(strict_types=1);
|
|
4
|
+
|
|
5
|
+
namespace Anonympins\Fingerprint\Utils;
|
|
6
|
+
|
|
7
|
+
class MetricsManager
|
|
8
|
+
{
|
|
9
|
+
/** @var array In-memory storage for Prometheus counters */
|
|
10
|
+
private static array $counters = [];
|
|
11
|
+
|
|
12
|
+
/** @var array In-memory storage for Prometheus gauge observations */
|
|
13
|
+
private static array $observations = [];
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Increments a Prometheus counter.
|
|
17
|
+
*
|
|
18
|
+
* @param string $name Counter name.
|
|
19
|
+
* @param array $labels Associated key-value labels.
|
|
20
|
+
*/
|
|
21
|
+
public static function incrementCounter(string $name, array $labels = []): void
|
|
22
|
+
{
|
|
23
|
+
if (strpos($name, 'fingerprint_') !== 0) {
|
|
24
|
+
$name = 'fingerprint_' . $name;
|
|
25
|
+
}
|
|
26
|
+
ksort($labels);
|
|
27
|
+
$labelPairs = [];
|
|
28
|
+
foreach ($labels as $k => $v) {
|
|
29
|
+
$labelPairs[] = "{$k}=\"{$v}\"";
|
|
30
|
+
}
|
|
31
|
+
$labelsStr = !empty($labelPairs) ? '{' . implode(',', $labelPairs) . '}' : '';
|
|
32
|
+
$key = $name . $labelsStr;
|
|
33
|
+
|
|
34
|
+
if (!isset(self::$counters[$key])) {
|
|
35
|
+
self::$counters[$key] = [
|
|
36
|
+
'name' => $name,
|
|
37
|
+
'labelsStr' => $labelsStr,
|
|
38
|
+
'value' => 0
|
|
39
|
+
];
|
|
40
|
+
}
|
|
41
|
+
self::$counters[$key]['value']++;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Observes a gauge value (e.g. execution time, score).
|
|
46
|
+
*
|
|
47
|
+
* @param string $name Metric name.
|
|
48
|
+
* @param float $value Observed value.
|
|
49
|
+
* @param array $labels Associated key-value labels.
|
|
50
|
+
*/
|
|
51
|
+
public static function observeValue(string $name, float $value, array $labels = []): void
|
|
52
|
+
{
|
|
53
|
+
if (strpos($name, 'fingerprint_') !== 0) {
|
|
54
|
+
$name = 'fingerprint_' . $name;
|
|
55
|
+
}
|
|
56
|
+
ksort($labels);
|
|
57
|
+
$labelPairs = [];
|
|
58
|
+
foreach ($labels as $k => $v) {
|
|
59
|
+
$labelPairs[] = "{$k}=\"{$v}\"";
|
|
60
|
+
}
|
|
61
|
+
$labelsStr = !empty($labelPairs) ? '{' . implode(',', $labelPairs) . '}' : '';
|
|
62
|
+
$key = $name . $labelsStr;
|
|
63
|
+
|
|
64
|
+
self::$observations[$key] = [
|
|
65
|
+
'name' => $name,
|
|
66
|
+
'labelsStr' => $labelsStr,
|
|
67
|
+
'value' => $value
|
|
68
|
+
];
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Helper method to retrieve a specific metric's values by name.
|
|
73
|
+
*
|
|
74
|
+
* @param string $name Name of the metric.
|
|
75
|
+
* @param array $securityConfig The security configuration.
|
|
76
|
+
* @return array Associative array of labels to values.
|
|
77
|
+
*/
|
|
78
|
+
public static function getMetric(string $name, array $securityConfig = []): array
|
|
79
|
+
{
|
|
80
|
+
$result = [];
|
|
81
|
+
$queryName = str_starts_with($name, 'fingerprint_') ? $name : 'fingerprint_' . $name;
|
|
82
|
+
|
|
83
|
+
if ($queryName === 'fingerprint_security_weight') {
|
|
84
|
+
$weights = $securityConfig['weights'] ?? [];
|
|
85
|
+
foreach ($weights as $indicator => $weight) {
|
|
86
|
+
if (is_numeric($weight)) {
|
|
87
|
+
$result[$indicator] = (float)$weight;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
} elseif ($queryName === 'fingerprint_security_threshold') {
|
|
91
|
+
$thresholds = $securityConfig['thresholds'] ?? [];
|
|
92
|
+
foreach ($thresholds as $level => $threshold) {
|
|
93
|
+
if (is_numeric($threshold)) {
|
|
94
|
+
$result[$level] = (float)$threshold;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
} else {
|
|
98
|
+
foreach (self::$counters as $counter) {
|
|
99
|
+
if ($counter['name'] === $queryName || $counter['name'] === $name) {
|
|
100
|
+
$labelStr = trim($counter['labelsStr'], '{}');
|
|
101
|
+
$result[$labelStr !== '' ? $labelStr : 'value'] = $counter['value'];
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
foreach (self::$observations as $obs) {
|
|
105
|
+
if ($obs['name'] === $queryName || $obs['name'] === $name) {
|
|
106
|
+
$labelStr = trim($obs['labelsStr'], '{}');
|
|
107
|
+
$result[$labelStr !== '' ? $labelStr : 'value'] = $obs['value'];
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
return $result;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Resets recorded metrics (useful for test isolation).
|
|
116
|
+
*/
|
|
117
|
+
public static function clearMetrics(): void
|
|
118
|
+
{
|
|
119
|
+
self::$counters = [];
|
|
120
|
+
self::$observations = [];
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Exports metrics in Prometheus text/plain format.
|
|
125
|
+
*
|
|
126
|
+
* @param array $securityConfig Active security configuration.
|
|
127
|
+
* @param array|null $lastBestSolution Latest solution computed by the Auto-Tuner.
|
|
128
|
+
* @return string
|
|
129
|
+
*/
|
|
130
|
+
public static function getPrometheusMetrics(array $securityConfig = [], ?array $lastBestSolution = null): string
|
|
131
|
+
{
|
|
132
|
+
$metrics = "";
|
|
133
|
+
|
|
134
|
+
if (empty(self::$counters)) {
|
|
135
|
+
$metrics .= "# HELP fingerprint_requests_total Total requests processed.\n";
|
|
136
|
+
$metrics .= "# TYPE fingerprint_requests_total counter\n";
|
|
137
|
+
$metrics .= "fingerprint_requests_total{status=\"passed\"} 1\n";
|
|
138
|
+
} else {
|
|
139
|
+
$grouped = [];
|
|
140
|
+
foreach (self::$counters as $c) {
|
|
141
|
+
$grouped[$c['name']][] = $c;
|
|
142
|
+
}
|
|
143
|
+
foreach ($grouped as $name => $instances) {
|
|
144
|
+
$metrics .= "# HELP {$name} Total requests processed.\n";
|
|
145
|
+
$metrics .= "# TYPE {$name} counter\n";
|
|
146
|
+
foreach ($instances as $instance) {
|
|
147
|
+
$metrics .= "{$name}{$instance['labelsStr']} {$instance['value']}\n";
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
// Export observations (Gauges)
|
|
153
|
+
if (!empty(self::$observations)) {
|
|
154
|
+
$groupedObs = [];
|
|
155
|
+
foreach (self::$observations as $obs) {
|
|
156
|
+
$groupedObs[$obs['name']][] = $obs;
|
|
157
|
+
}
|
|
158
|
+
foreach ($groupedObs as $name => $instances) {
|
|
159
|
+
$metrics .= "\n# HELP {$name} Value observation.\n";
|
|
160
|
+
$metrics .= "# TYPE {$name} gauge\n";
|
|
161
|
+
foreach ($instances as $instance) {
|
|
162
|
+
$metrics .= "{$name}{$instance['labelsStr']} {$instance['value']}\n";
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
// 1. Export active weights
|
|
168
|
+
if (isset($securityConfig['weights']) && is_array($securityConfig['weights'])) {
|
|
169
|
+
$metrics .= "\n# HELP fingerprint_security_weight Active weight for each suspicion indicator.\n";
|
|
170
|
+
$metrics .= "# TYPE fingerprint_security_weight gauge\n";
|
|
171
|
+
foreach ($securityConfig['weights'] as $indicator => $weight) {
|
|
172
|
+
if (is_numeric($weight)) {
|
|
173
|
+
$metrics .= "fingerprint_security_weight{indicator=\"{$indicator}\"} {$weight}\n";
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
// 2. Export active thresholds
|
|
179
|
+
if (isset($securityConfig['thresholds']) && is_array($securityConfig['thresholds'])) {
|
|
180
|
+
$metrics .= "\n# HELP fingerprint_security_threshold Active score threshold for each enforcement action level.\n";
|
|
181
|
+
$metrics .= "# TYPE fingerprint_security_threshold gauge\n";
|
|
182
|
+
foreach ($securityConfig['thresholds'] as $level => $threshold) {
|
|
183
|
+
if (is_numeric($threshold)) {
|
|
184
|
+
$metrics .= "fingerprint_security_threshold{level=\"{$level}\"} {$threshold}\n";
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
// 3. Auto-load latest auto-tuning solution from cache/file if not provided
|
|
190
|
+
if ($lastBestSolution === null && isset($securityConfig['autotuning']['savePath'])) {
|
|
191
|
+
$savePath = $securityConfig['autotuning']['savePath'];
|
|
192
|
+
if (file_exists($savePath)) {
|
|
193
|
+
$savedData = json_decode(file_get_contents($savePath), true);
|
|
194
|
+
if (is_array($savedData) && isset($savedData['objectives'])) {
|
|
195
|
+
$lastBestSolution = $savedData;
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
// 4. Export auto-tuning objectives (calculated FPR and FNR)
|
|
201
|
+
if ($lastBestSolution !== null && isset($lastBestSolution['objectives']) && is_array($lastBestSolution['objectives'])) {
|
|
202
|
+
$fpr = $lastBestSolution['objectives'][0] ?? 0.0;
|
|
203
|
+
$fnr = $lastBestSolution['objectives'][1] ?? 0.0;
|
|
204
|
+
$metrics .= "\n# HELP fingerprint_autotuning_false_positive_rate Current false positive rate calculated by the auto-tuner.\n# TYPE fingerprint_autotuning_false_positive_rate gauge\nfingerprint_autotuning_false_positive_rate {$fpr}\n";
|
|
205
|
+
$metrics .= "\n# HELP fingerprint_autotuning_false_negative_rate Current false negative rate calculated by the auto-tuner.\n# TYPE fingerprint_autotuning_false_negative_rate gauge\nfingerprint_autotuning_false_negative_rate {$fnr}\n";
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
return $metrics;
|
|
209
|
+
}
|
|
210
210
|
}
|