feat(Production): Complete production deployment infrastructure

- Add comprehensive health check system with multiple endpoints
- Add Prometheus metrics endpoint
- Add production logging configurations (5 strategies)
- Add complete deployment documentation suite:
  * QUICKSTART.md - 30-minute deployment guide
  * DEPLOYMENT_CHECKLIST.md - Printable verification checklist
  * DEPLOYMENT_WORKFLOW.md - Complete deployment lifecycle
  * PRODUCTION_DEPLOYMENT.md - Comprehensive technical reference
  * production-logging.md - Logging configuration guide
  * ANSIBLE_DEPLOYMENT.md - Infrastructure as Code automation
  * README.md - Navigation hub
  * DEPLOYMENT_SUMMARY.md - Executive summary
- Add deployment scripts and automation
- Add DEPLOYMENT_PLAN.md - Concrete plan for immediate deployment
- Update README with production-ready features

All production infrastructure is now complete and ready for deployment.
This commit is contained in:
2025-10-25 19:18:37 +02:00
parent caa85db796
commit fc3d7e6357
83016 changed files with 378904 additions and 20919 deletions

View File

@@ -7,10 +7,14 @@ namespace App\Framework\Waf\MachineLearning;
use App\Framework\Core\ValueObjects\Duration;
use App\Framework\Core\ValueObjects\Percentage;
use App\Framework\DateTime\Clock;
use App\Framework\MachineLearning\Core\AnomalyDetectorInterface;
use App\Framework\MachineLearning\Core\FeatureExtractorMetadata;
use App\Framework\MachineLearning\ValueObjects\AnomalyDetection;
use App\Framework\MachineLearning\ValueObjects\Baseline;
use App\Framework\MachineLearning\ValueObjects\Feature;
use App\Framework\MachineLearning\ValueObjects\FeatureType;
use App\Framework\Waf\Analysis\ValueObjects\RequestAnalysisData;
use App\Framework\Waf\MachineLearning\ValueObjects\AnomalyDetection;
use App\Framework\Waf\MachineLearning\ValueObjects\BehaviorBaseline;
use App\Framework\Waf\MachineLearning\ValueObjects\BehaviorFeature;
use App\Framework\Waf\MachineLearning\WafFeatureExtractor;
/**
* Main machine learning engine for behavioral analysis and anomaly detection
@@ -18,7 +22,7 @@ use App\Framework\Waf\MachineLearning\ValueObjects\BehaviorFeature;
final class MachineLearningEngine
{
/**
* @param FeatureExtractorInterface[] $extractors
* @param WafFeatureExtractor[] $extractors
* @param AnomalyDetectorInterface[] $detectors
*/
public function __construct(
@@ -141,7 +145,7 @@ final class MachineLearningEngine
$extractorResults[] = [
'extractor' => get_class($extractor),
'behavior_type' => $extractor->getBehaviorType()->value,
'feature_type' => $extractor->getFeatureType()->value,
'feature_count' => count($validFeatures),
'processing_time' => $extractorTime->toMilliseconds(),
'success' => true,
@@ -155,7 +159,7 @@ final class MachineLearningEngine
} catch (\Throwable $e) {
$extractorResults[] = [
'extractor' => get_class($extractor),
'behavior_type' => $extractor->getBehaviorType()->value,
'feature_type' => $extractor->getFeatureType()->value,
'feature_count' => 0,
'processing_time' => 0,
'success' => false,
@@ -239,10 +243,10 @@ final class MachineLearningEngine
{
$baselines = [];
// Group features by behavior type
// Group features by feature type
$featureGroups = [];
foreach ($features as $feature) {
if ($feature instanceof BehaviorFeature) {
if ($feature instanceof Feature) {
$typeKey = $feature->type->value;
if (! isset($featureGroups[$typeKey])) {
$featureGroups[$typeKey] = [];
@@ -251,17 +255,17 @@ final class MachineLearningEngine
}
}
// Get or create baselines for each behavior type
foreach ($featureGroups as $behaviorType => $groupFeatures) {
$cacheKey = "baseline:{$behaviorType}";
// Get or create baselines for each feature type
foreach ($featureGroups as $featureType => $groupFeatures) {
$cacheKey = "baseline:{$featureType}";
if (isset($this->baselineCache[$cacheKey])) {
$baselines[$behaviorType] = $this->baselineCache[$cacheKey];
$baselines[$featureType] = $this->baselineCache[$cacheKey];
} else {
// Create new baseline from features
$baseline = $this->createBaselineFromFeatures($groupFeatures, BehaviorType::from($behaviorType));
$baseline = $this->createBaselineFromFeatures($groupFeatures, FeatureType::from($featureType));
if ($baseline !== null) {
$baselines[$behaviorType] = $baseline;
$baselines[$featureType] = $baseline;
$this->baselineCache[$cacheKey] = $baseline;
}
}
@@ -273,13 +277,13 @@ final class MachineLearningEngine
/**
* Create behavioral baseline from feature set
*/
private function createBaselineFromFeatures(array $features, BehaviorType $behaviorType): ?BehaviorBaseline
private function createBaselineFromFeatures(array $features, FeatureType $featureType): ?Baseline
{
if (empty($features)) {
return null;
}
$values = array_map(fn (BehaviorFeature $f) => $f->value, $features);
$values = array_map(fn (Feature $f) => $f->value, $features);
if (empty($values)) {
return null;
@@ -294,28 +298,36 @@ final class MachineLearningEngine
$p95 = $values[(int)(count($values) * 0.95)];
$p99 = $values[(int)(count($values) * 0.99)];
return new BehaviorBaseline(
type: $behaviorType,
return new Baseline(
type: $featureType,
identifier: 'dynamic-baseline',
mean: $mean,
standardDeviation: $stdDev,
sampleSize: count($values),
p50: $p50,
p95: $p95,
p99: $p99,
confidence: Percentage::from(min(100.0, count($values) * 5.0)), // 5% per sample, max 100%
lastUpdated: $this->clock->time()
median: $p50,
minimum: min($values),
maximum: max($values),
percentiles: [
50 => $p50,
95 => $p95,
99 => $p99
],
sampleCount: count($values),
createdAt: $this->clock->time(),
lastUpdated: $this->clock->time(),
windowSize: Duration::fromMinutes(30),
confidence: min(1.0, count($values) * 0.05) // 5% per sample, max 100%
);
}
/**
* Get relevant baseline for a detector
*/
private function getRelevantBaseline(AnomalyDetectorInterface $detector, array $baselines): ?BehaviorBaseline
private function getRelevantBaseline(AnomalyDetectorInterface $detector, array $baselines): ?Baseline
{
$supportedTypes = $detector->getSupportedBehaviorTypes();
$supportedTypes = $detector->getSupportedFeatureTypes();
foreach ($supportedTypes as $behaviorType) {
$typeKey = $behaviorType->value;
foreach ($supportedTypes as $featureType) {
$typeKey = $featureType->value;
if (isset($baselines[$typeKey])) {
return $baselines[$typeKey];
}
@@ -332,7 +344,7 @@ final class MachineLearningEngine
$validFeatures = [];
foreach ($features as $feature) {
if ($feature instanceof BehaviorFeature) {
if ($feature instanceof Feature) {
// Validate feature values
if (is_numeric($feature->value) &&
! is_nan($feature->value) &&
@@ -530,13 +542,13 @@ final class MachineLearningEngine
*/
private function deduplicateAndRankAnomalies(array $anomalies): array
{
// Remove duplicates based on type and behavior type
// Remove duplicates based on type and feature type
$seen = [];
$unique = [];
foreach ($anomalies as $anomaly) {
if ($anomaly instanceof AnomalyDetection) {
$key = $anomaly->type->value . ':' . $anomaly->behaviorType->value;
$key = $anomaly->type->value . ':' . $anomaly->featureType->value;
if (! isset($seen[$key]) || $anomaly->confidence->getValue() > $seen[$key]->confidence->getValue()) {
$seen[$key] = $anomaly;
}
@@ -560,8 +572,8 @@ final class MachineLearningEngine
'path' => $requestData->path,
'method' => $requestData->method,
'params' => $requestData->getAllParameters(),
'user_agent' => $requestData->userAgent?->toString(),
'ip' => $requestData->clientIp?->toString(),
'user_agent' => (string) $requestData->userAgent,
'ip' => (string) $requestData->clientIp,
]));
}
@@ -574,7 +586,7 @@ final class MachineLearningEngine
$featuresByType = [];
foreach ($features as $feature) {
if ($feature instanceof BehaviorFeature) {
if ($feature instanceof Feature) {
$typeKey = $feature->type->value;
if (! isset($featuresByType[$typeKey])) {
$featuresByType[$typeKey] = [];
@@ -583,9 +595,9 @@ final class MachineLearningEngine
}
}
foreach ($featuresByType as $behaviorType => $typeFeatures) {
foreach ($featuresByType as $featureType => $typeFeatures) {
$results[] = [
'behavior_type' => $behaviorType,
'feature_type' => $featureType,
'feature_count' => count($typeFeatures),
'avg_value' => array_sum(array_map(fn ($f) => $f->value, $typeFeatures)) / count($typeFeatures),
'feature_names' => array_unique(array_map(fn ($f) => $f->name, $typeFeatures)),
@@ -632,14 +644,14 @@ final class MachineLearningEngine
{
$stats = [];
foreach ($baselines as $behaviorType => $baseline) {
if ($baseline instanceof BehaviorBaseline) {
foreach ($baselines as $featureType => $baseline) {
if ($baseline instanceof Baseline) {
$stats[] = [
'behavior_type' => $behaviorType,
'sample_size' => $baseline->sampleSize,
'feature_type' => $featureType,
'sample_size' => $baseline->sampleCount,
'mean' => $baseline->mean,
'std_dev' => $baseline->standardDeviation,
'confidence' => $baseline->confidence->getValue(),
'confidence' => $baseline->confidence,
'last_updated' => $baseline->lastUpdated->toIso8601String(),
];
}
@@ -654,7 +666,7 @@ final class MachineLearningEngine
private function recordPerformanceMetrics(Duration $processingTime, int $featureCount, int $anomalyCount): void
{
$this->performanceMetrics[] = [
'timestamp' => $this->clock->time()->toUnixTimestamp(),
'timestamp' => $this->clock->time()->toTimestamp(),
'processing_time_ms' => $processingTime->toMilliseconds(),
'feature_count' => $featureCount,
'anomaly_count' => $anomalyCount,