Vulnerability Management Automation

Automate vulnerability discovery, risk assessment, and compliance evidence collection using Nodeware, ConnectSecure, and Lionguard integrations for SOC 2 CC7.2 and ISO 27001 A.12.6.1.

Nodeware Integration CVE Automation Risk Scoring Compliance Evidence

Nodeware Vulnerability Connector

NodewareVulnerabilityCollector

Complete vulnerability management automation for SOC 2 CC7.2 and ISO 27001 A.12.6.1 compliance.

baseUrl = config('nodeware.base_url', 'https://api.nodeware.com');
    }
    
    public function authenticate(int $clientId): void
    {
        $this->clientId = $clientId;
        
        $apiKey = ApiKey::where('client_id', $clientId)
            ->where('provider', 'nodeware')
            ->where('is_active', true)
            ->first();
            
        if (!$apiKey) {
            throw new \Exception("No active Nodeware API key found for client {$clientId}");
        }
        
        $this->apiToken = decrypt($apiKey->api_token);
    }
    
    public function collect(int $clientId): array
    {
        $this->authenticate($clientId);
        
        $customers = $this->getCustomers();
        $results = [];
        
        foreach ($customers as $customer) {
            $customerToken = $customer['customer_token'];
            
            $results[$customerToken] = [
                'customer_info' => $customer,
                'asset_inventory' => $this->collectAssetInventory($customerToken),
                'vulnerability_summary' => $this->collectVulnerabilitySummary($customerToken),
                'critical_alerts' => $this->collectCriticalAlerts($customerToken),
                'cve_analysis' => $this->collectCVEAnalysis($customerToken),
                'compliance_evidence' => $this->generateComplianceEvidence($customerToken),
                'risk_metrics' => $this->calculateRiskMetrics($customerToken)
            ];
        }
        
        return $results;
    }
    
    private function makeRequest(string $endpoint, array $queryParams = []): array
    {
        $url = $this->baseUrl . $endpoint;
        
        if (!empty($queryParams)) {
            $url .= '?' . http_build_query($queryParams);
        }
        
        $response = Http::withHeaders([
            'Authorization' => 'Bearer ' . $this->apiToken,
            'Accept' => 'application/json'
        ])->get($url);
        
        if (!$response->successful()) {
            Log::error("Nodeware API request failed: {$response->status()} - {$response->body()}");
            throw new \Exception("API request failed: {$response->status()}");
        }
        
        return $response->json();
    }
    
    private function getCustomers(): array
    {
        return $this->makeRequest('/customers/');
    }
    
    private function collectAssetInventory(string $customerToken): array
    {
        $assets = $this->makeRequest("/assets/{$customerToken}/");
        
        return [
            'total_assets' => count($assets),
            'asset_breakdown' => $this->categorizeAssets($assets),
            'last_scan_summary' => $this->analyzeScanFreshness($assets),
            'network_coverage' => $this->analyzeNetworkCoverage($assets),
            'assets' => array_map([$this, 'processAssetData'], $assets)
        ];
    }
    
    private function collectVulnerabilitySummary(string $customerToken): array
    {
        // Get assets with vulnerability filtering
        $criticalAssets = $this->makeRequest("/assets/{$customerToken}/", [
            'severity_level' => 'critical'
        ]);
        
        $highAssets = $this->makeRequest("/assets/{$customerToken}/", [
            'severity_level' => 'high'
        ]);
        
        $allAssets = $this->makeRequest("/assets/{$customerToken}/");
        
        return [
            'vulnerability_counts' => $this->aggregateVulnerabilityCounts($allAssets),
            'critical_vulnerabilities' => $this->extractCriticalVulns($criticalAssets),
            'high_vulnerabilities' => $this->extractHighVulns($highAssets),
            'trending_cves' => $this->identifyTrendingCVEs($allAssets),
            'remediation_priorities' => $this->prioritizeRemediation($allAssets)
        ];
    }
    
    private function collectCriticalAlerts(string $customerToken): array
    {
        // Get recent critical alerts (last 7 days)
        $alerts = $this->makeRequest("/alerts/{$customerToken}/", [
            'days' => 7
        ]);
        
        $criticalAlerts = array_filter($alerts, function($alert) {
            return in_array(strtolower($alert['severity'] ?? ''), ['critical', 'high']);
        });
        
        return [
            'total_alerts' => count($alerts),
            'critical_alerts' => count($criticalAlerts),
            'alert_distribution' => $this->categorizeAlerts($alerts),
            'unresolved_critical' => $this->identifyUnresolvedCritical($criticalAlerts),
            'alert_trends' => $this->analyzeAlertTrends($alerts)
        ];
    }
    
    private function collectCVEAnalysis(string $customerToken): array
    {
        $assets = $this->makeRequest("/assets/{$customerToken}/");
        $cveData = [];
        
        foreach ($assets as $asset) {
            if (!empty($asset['uuid'])) {
                try {
                    $assetCVEs = $this->makeRequest("/asset/{$asset['uuid']}/cves/");
                    $cveData = array_merge($cveData, $assetCVEs);
                } catch (\Exception $e) {
                    Log::warning("Failed to get CVEs for asset {$asset['uuid']}: {$e->getMessage()}");
                }
            }
        }
        
        return [
            'total_cves' => count($cveData),
            'unique_cves' => $this->getUniqueCVEs($cveData),
            'cve_age_analysis' => $this->analyzeCVEAge($cveData),
            'cvss_distribution' => $this->analyzeCVSSDistribution($cveData),
            'exploit_availability' => $this->checkExploitAvailability($cveData)
        ];
    }
    
    private function generateComplianceEvidence(string $customerToken): array
    {
        $assets = $this->makeRequest("/assets/{$customerToken}/");
        $alerts = $this->makeRequest("/alerts/{$customerToken}/", ['days' => 30]);
        
        return [
            'SOC2_CC7_2' => [
                'control_description' => 'The entity monitors system components and the operation of controls',
                'evidence_collected' => [
                    'continuous_vulnerability_monitoring' => $this->evidenceVulnMonitoring($assets),
                    'security_alert_system' => $this->evidenceAlertSystem($alerts),
                    'asset_inventory_completeness' => $this->evidenceAssetInventory($assets),
                    'monitoring_coverage' => $this->evidenceMonitoringCoverage($assets)
                ],
                'compliance_score' => $this->calculateSOC2CC72Score($assets, $alerts)
            ],
            'ISO27001_A_12_6_1' => [
                'control_description' => 'Information about technical vulnerabilities should be obtained in a timely fashion',
                'evidence_collected' => [
                    'vulnerability_identification' => $this->evidenceVulnIdentification($assets),
                    'risk_assessment' => $this->evidenceRiskAssessment($assets),
                    'remediation_tracking' => $this->evidenceRemediation($assets),
                    'vulnerability_lifecycle' => $this->evidenceVulnLifecycle($assets)
                ],
                'compliance_score' => $this->calculateISO27001A1261Score($assets)
            ]
        ];
    }
    
    private function calculateRiskMetrics(string $customerToken): array
    {
        $assets = $this->makeRequest("/assets/{$customerToken}/");
        $alerts = $this->makeRequest("/alerts/{$customerToken}/", ['days' => 30]);
        
        $totalAssets = count($assets);
        $vulnerableAssets = count(array_filter($assets, fn($a) => ($a['totals']['critical'] ?? 0) > 0));
        $criticalVulns = array_sum(array_column(array_column($assets, 'totals'), 'critical'));
        $highVulns = array_sum(array_column(array_column($assets, 'totals'), 'high'));
        
        return [
            'overall_risk_score' => $this->calculateOverallRiskScore($assets),
            'asset_risk_distribution' => [
                'critical_risk_assets' => count(array_filter($assets, fn($a) => ($a['totals']['critical'] ?? 0) >= 5)),
                'high_risk_assets' => count(array_filter($assets, fn($a) => ($a['totals']['high'] ?? 0) >= 10)),
                'vulnerable_asset_percentage' => $totalAssets > 0 ? round(($vulnerableAssets / $totalAssets) * 100, 2) : 0
            ],
            'vulnerability_metrics' => [
                'total_critical' => $criticalVulns,
                'total_high' => $highVulns,
                'critical_density' => $totalAssets > 0 ? round($criticalVulns / $totalAssets, 2) : 0,
                'high_density' => $totalAssets > 0 ? round($highVulns / $totalAssets, 2) : 0
            ],
            'time_to_detection' => $this->calculateTimeToDetection($alerts),
            'remediation_sla_compliance' => $this->calculateSLACompliance($assets)
        ];
    }
    
    private function processAssetData(array $asset): array
    {
        return [
            'uuid' => $asset['uuid'],
            'hostname' => $asset['hostname'] ?? 'Unknown',
            'ip_address' => $asset['ip'] ?? null,
            'operating_system' => $asset['os'] ?? 'Unknown',
            'asset_type' => $this->determineAssetType($asset),
            'vulnerability_summary' => $asset['totals'] ?? [],
            'last_scan' => $asset['last_scan_date'] ?? null,
            'scan_freshness' => $this->calculateScanFreshness($asset['last_scan_date'] ?? null),
            'compliance_flags' => $this->generateAssetComplianceFlags($asset),
            'risk_level' => $this->calculateAssetRiskLevel($asset)
        ];
    }
    
    // Evidence generation methods for compliance frameworks
    private function evidenceVulnMonitoring(array $assets): array
    {
        $recentScans = array_filter($assets, function($asset) {
            $lastScan = $asset['last_scan_date'] ?? null;
            if (!$lastScan) return false;
            return Carbon::parse($lastScan)->diffInDays(now()) <= 7;
        });
        
        return [
            'monitoring_frequency' => 'Continuous (7-day max scan age)',
            'assets_monitored' => count($assets),
            'recent_scans' => count($recentScans),
            'monitoring_coverage_percentage' => count($assets) > 0 ? round((count($recentScans) / count($assets)) * 100, 2) : 0,
            'vulnerability_detection_active' => count($assets) > 0
        ];
    }
    
    private function evidenceAlertSystem(array $alerts): array
    {
        $criticalAlerts = array_filter($alerts, fn($a) => ($a['severity'] ?? '') === 'critical');
        
        return [
            'alert_system_active' => count($alerts) >= 0,
            'total_alerts_30_days' => count($alerts),
            'critical_alerts' => count($criticalAlerts),
            'average_alerts_per_day' => round(count($alerts) / 30, 2),
            'alert_response_capability' => 'Automated'
        ];
    }
    
    private function calculateSOC2CC72Score(array $assets, array $alerts): float
    {
        $score = 100.0;
        
        // Deduct points for assets without recent scans
        $staleAssets = array_filter($assets, function($asset) {
            $lastScan = $asset['last_scan_date'] ?? null;
            return !$lastScan || Carbon::parse($lastScan)->diffInDays(now()) > 14;
        });
        
        if (count($assets) > 0) {
            $stalePercentage = (count($staleAssets) / count($assets)) * 100;
            $score -= min($stalePercentage * 0.5, 25); // Max 25 point deduction
        }
        
        // Deduct points for unresolved critical vulnerabilities
        $criticalVulns = array_sum(array_column(array_column($assets, 'totals'), 'critical'));
        if ($criticalVulns > 0) {
            $score -= min($criticalVulns * 2, 30); // Max 30 point deduction
        }
        
        return max($score, 0);
    }
    
    private function calculateISO27001A1261Score(array $assets): float
    {
        $score = 100.0;
        
        // Evaluate vulnerability identification timeliness
        $oldVulns = 0;
        foreach ($assets as $asset) {
            // Check for vulnerabilities older than 30 days (would need CVE age analysis)
            $criticalCount = $asset['totals']['critical'] ?? 0;
            $highCount = $asset['totals']['high'] ?? 0;
            
            // Penalty for high vulnerability counts (indicates poor management)
            if ($criticalCount > 5) $score -= min($criticalCount - 5, 15);
            if ($highCount > 20) $score -= min(($highCount - 20) * 0.5, 10);
        }
        
        return max($score, 0);
    }
    
    // Additional helper methods would be implemented here...
    private function categorizeAssets(array $assets): array
    {
        return [
            'servers' => count(array_filter($assets, fn($a) => str_contains(strtolower($a['os'] ?? ''), 'server'))),
            'workstations' => count(array_filter($assets, fn($a) => str_contains(strtolower($a['os'] ?? ''), 'windows') && !str_contains(strtolower($a['os'] ?? ''), 'server'))),
            'network_devices' => count(array_filter($assets, fn($a) => empty($a['os']) || str_contains(strtolower($a['os'] ?? ''), 'ios'))),
            'linux_systems' => count(array_filter($assets, fn($a) => str_contains(strtolower($a['os'] ?? ''), 'linux')))
        ];
    }
    
    private function calculateOverallRiskScore(array $assets): float
    {
        if (empty($assets)) return 0;
        
        $totalRisk = 0;
        foreach ($assets as $asset) {
            $critical = $asset['totals']['critical'] ?? 0;
            $high = $asset['totals']['high'] ?? 0;
            $medium = $asset['totals']['medium'] ?? 0;
            
            // Weighted risk calculation: Critical=10, High=5, Medium=1
            $assetRisk = ($critical * 10) + ($high * 5) + ($medium * 1);
            $totalRisk += $assetRisk;
        }
        
        return $totalRisk / count($assets);
    }
    
    public function storeComplianceEvidence(int $clientId, array $results): void
    {
        foreach ($results as $customerToken => $customerData) {
            $evidence = $customerData['compliance_evidence'];
            
            // Store SOC 2 CC7.2 evidence
            AssessmentEventsQuestion::updateOrCreate([
                'client_id' => $clientId,
                'framework' => 'SOC2',
                'control_id' => 'CC7.2',
                'evidence_source' => 'Nodeware_Vulnerability_Management'
            ], [
                'compliance_score' => $evidence['SOC2_CC7_2']['compliance_score'],
                'evidence_collected' => json_encode($evidence['SOC2_CC7_2']['evidence_collected']),
                'analysis_date' => now(),
                'automated_collection' => true,
                'risk_level' => $this->determineRiskLevel($evidence['SOC2_CC7_2']['compliance_score']),
                'recommendations' => json_encode($this->generateSOC2Recommendations($customerData))
            ]);
            
            // Store ISO 27001 A.12.6.1 evidence
            AssessmentEventsQuestion::updateOrCreate([
                'client_id' => $clientId,
                'framework' => 'ISO27001',
                'control_id' => 'A.12.6.1',
                'evidence_source' => 'Nodeware_Vulnerability_Management'
            ], [
                'compliance_score' => $evidence['ISO27001_A_12_6_1']['compliance_score'],
                'evidence_collected' => json_encode($evidence['ISO27001_A_12_6_1']['evidence_collected']),
                'analysis_date' => now(),
                'automated_collection' => true,
                'risk_level' => $this->determineRiskLevel($evidence['ISO27001_A_12_6_1']['compliance_score']),
                'recommendations' => json_encode($this->generateISO27001Recommendations($customerData))
            ]);
        }
    }
}
?>

Vulnerability Automation Rules Engine

VulnerabilityRulesEngine

Automated vulnerability assessment and compliance validation without expensive AI calls.

 $this->checkContinuousMonitoring($vulnerabilityData),
            'asset_inventory_completeness' => $this->checkAssetInventoryCompleteness($vulnerabilityData),
            'vulnerability_detection' => $this->checkVulnerabilityDetection($vulnerabilityData),
            'incident_response' => $this->checkIncidentResponse($vulnerabilityData),
            'monitoring_coverage' => $this->checkMonitoringCoverage($vulnerabilityData)
        ];
        
        $passedRules = count(array_filter($rules, fn($r) => $r['passed']));
        $totalRules = count($rules);
        $complianceScore = ($passedRules / $totalRules) * 100;
        
        return [
            'framework' => 'SOC2',
            'control' => 'CC7.2',
            'compliance_score' => round($complianceScore, 2),
            'rules_evaluation' => $rules,
            'overall_status' => $complianceScore >= 80 ? 'COMPLIANT' : 'NON_COMPLIANT',
            'critical_findings' => $this->extractCriticalFindings($rules),
            'recommendations' => $this->generateSOC2Recommendations($rules)
        ];
    }
    
    public function evaluateISO27001A1261Compliance(array $vulnerabilityData): array
    {
        $rules = [
            'vulnerability_identification' => $this->checkVulnerabilityIdentification($vulnerabilityData),
            'risk_assessment' => $this->checkRiskAssessment($vulnerabilityData),
            'timely_remediation' => $this->checkTimelyRemediation($vulnerabilityData),
            'vulnerability_management_process' => $this->checkVulnManagementProcess($vulnerabilityData),
            'documentation_and_records' => $this->checkDocumentationRecords($vulnerabilityData)
        ];
        
        $passedRules = count(array_filter($rules, fn($r) => $r['passed']));
        $totalRules = count($rules);
        $complianceScore = ($passedRules / $totalRules) * 100;
        
        return [
            'framework' => 'ISO27001',
            'control' => 'A.12.6.1',
            'compliance_score' => round($complianceScore, 2),
            'rules_evaluation' => $rules,
            'overall_status' => $complianceScore >= 85 ? 'COMPLIANT' : 'NON_COMPLIANT',
            'critical_findings' => $this->extractCriticalFindings($rules),
            'recommendations' => $this->generateISO27001Recommendations($rules)
        ];
    }
    
    private function checkContinuousMonitoring(array $data): array
    {
        $recentScanPercentage = 0;
        $totalAssets = 0;
        
        foreach ($data as $customerData) {
            $assets = $customerData['asset_inventory']['assets'] ?? [];
            $totalAssets += count($assets);
            
            $recentScans = array_filter($assets, function($asset) {
                return $asset['scan_freshness'] <= 7; // Within 7 days
            });
            
            $recentScanPercentage += count($recentScans);
        }
        
        $scanCoveragePercentage = $totalAssets > 0 ? ($recentScanPercentage / $totalAssets) * 100 : 0;
        $passed = $scanCoveragePercentage >= 90; // 90% of assets scanned within 7 days
        
        return [
            'rule_name' => 'Continuous Monitoring',
            'passed' => $passed,
            'score' => round($scanCoveragePercentage, 2),
            'threshold' => 90,
            'description' => 'Assets must be scanned within 7 days for continuous monitoring',
            'evidence' => [
                'total_assets' => $totalAssets,
                'recently_scanned' => $recentScanPercentage,
                'coverage_percentage' => round($scanCoveragePercentage, 2)
            ]
        ];
    }
    
    private function checkAssetInventoryCompleteness(array $data): array
    {
        $totalAssets = 0;
        $assetsWithOS = 0;
        $assetsWithHostname = 0;
        
        foreach ($data as $customerData) {
            $assets = $customerData['asset_inventory']['assets'] ?? [];
            $totalAssets += count($assets);
            
            foreach ($assets as $asset) {
                if (!empty($asset['operating_system']) && $asset['operating_system'] !== 'Unknown') {
                    $assetsWithOS++;
                }
                if (!empty($asset['hostname']) && $asset['hostname'] !== 'Unknown') {
                    $assetsWithHostname++;
                }
            }
        }
        
        $osCompleteness = $totalAssets > 0 ? ($assetsWithOS / $totalAssets) * 100 : 0;
        $hostnameCompleteness = $totalAssets > 0 ? ($assetsWithHostname / $totalAssets) * 100 : 0;
        $overallCompleteness = ($osCompleteness + $hostnameCompleteness) / 2;
        
        $passed = $overallCompleteness >= 80; // 80% asset identification completeness
        
        return [
            'rule_name' => 'Asset Inventory Completeness',
            'passed' => $passed,
            'score' => round($overallCompleteness, 2),
            'threshold' => 80,
            'description' => 'Asset inventory must have complete identification information',
            'evidence' => [
                'total_assets' => $totalAssets,
                'os_identification_rate' => round($osCompleteness, 2),
                'hostname_identification_rate' => round($hostnameCompleteness, 2),
                'overall_completeness' => round($overallCompleteness, 2)
            ]
        ];
    }
    
    private function checkVulnerabilityDetection(array $data): array
    {
        $totalCriticalVulns = 0;
        $totalHighVulns = 0;
        $assetsWithVulns = 0;
        $totalAssets = 0;
        
        foreach ($data as $customerData) {
            $assets = $customerData['asset_inventory']['assets'] ?? [];
            $totalAssets += count($assets);
            
            foreach ($assets as $asset) {
                $vulnSummary = $asset['vulnerability_summary'] ?? [];
                $critical = $vulnSummary['critical'] ?? 0;
                $high = $vulnSummary['high'] ?? 0;
                
                $totalCriticalVulns += $critical;
                $totalHighVulns += $high;
                
                if ($critical > 0 || $high > 0) {
                    $assetsWithVulns++;
                }
            }
        }
        
        // Detection effectiveness: Are we finding vulnerabilities where expected?
        $detectionRate = $totalAssets > 0 ? ($assetsWithVulns / $totalAssets) * 100 : 0;
        
        // Pass if we're detecting vulnerabilities (>10% of assets have vulns) or no critical vulns exist
        $passed = $detectionRate >= 10 || $totalCriticalVulns === 0;
        
        return [
            'rule_name' => 'Vulnerability Detection',
            'passed' => $passed,
            'score' => min($detectionRate, 100),
            'threshold' => 10,
            'description' => 'Vulnerability scanning must be detecting security issues effectively',
            'evidence' => [
                'total_critical_vulnerabilities' => $totalCriticalVulns,
                'total_high_vulnerabilities' => $totalHighVulns,
                'assets_with_vulnerabilities' => $assetsWithVulns,
                'detection_rate_percentage' => round($detectionRate, 2)
            ]
        ];
    }
    
    private function checkVulnerabilityIdentification(array $data): array
    {
        $cveCount = 0;
        $uniqueCVEs = [];
        $totalAssets = 0;
        
        foreach ($data as $customerData) {
            $cveAnalysis = $customerData['cve_analysis'] ?? [];
            $cveCount += $cveAnalysis['total_cves'] ?? 0;
            $uniqueCVEs = array_merge($uniqueCVEs, $cveAnalysis['unique_cves'] ?? []);
            
            $assets = $customerData['asset_inventory']['assets'] ?? [];
            $totalAssets += count($assets);
        }
        
        $uniqueCVECount = count(array_unique($uniqueCVEs));
        $cvePerAsset = $totalAssets > 0 ? $cveCount / $totalAssets : 0;
        
        // Pass if we're identifying CVEs comprehensively
        $passed = $uniqueCVECount >= 5 || $cvePerAsset >= 1;
        
        return [
            'rule_name' => 'Vulnerability Identification',
            'passed' => $passed,
            'score' => min($uniqueCVECount * 10, 100),
            'threshold' => 50,
            'description' => 'System must identify technical vulnerabilities comprehensively',
            'evidence' => [
                'total_cves_identified' => $cveCount,
                'unique_cves' => $uniqueCVECount,
                'cve_per_asset_ratio' => round($cvePerAsset, 2),
                'identification_effectiveness' => $uniqueCVECount >= 5 ? 'Effective' : 'Needs Improvement'
            ]
        ];
    }
    
    public function calculateVulnerabilityRiskScore(array $vulnerabilityData): array
    {
        $riskFactors = [
            'critical_vulnerability_density' => $this->calculateCriticalVulnDensity($vulnerabilityData),
            'unpatched_vulnerability_age' => $this->calculateUnpatchedAge($vulnerabilityData),
            'exploit_availability' => $this->assessExploitAvailability($vulnerabilityData),
            'asset_exposure' => $this->assessAssetExposure($vulnerabilityData),
            'remediation_backlog' => $this->assessRemediationBacklog($vulnerabilityData)
        ];
        
        // Weighted risk calculation
        $weights = [
            'critical_vulnerability_density' => 0.3,
            'unpatched_vulnerability_age' => 0.25,
            'exploit_availability' => 0.2,
            'asset_exposure' => 0.15,
            'remediation_backlog' => 0.1
        ];
        
        $overallRisk = 0;
        foreach ($riskFactors as $factor => $score) {
            $overallRisk += $score * $weights[$factor];
        }
        
        return [
            'overall_risk_score' => round($overallRisk, 2),
            'risk_level' => $this->determineRiskLevel($overallRisk),
            'risk_factors' => $riskFactors,
            'risk_trends' => $this->calculateRiskTrends($vulnerabilityData),
            'immediate_actions' => $this->identifyImmediateActions($riskFactors)
        ];
    }
    
    private function determineRiskLevel(float $score): string
    {
        if ($score >= 80) return 'CRITICAL';
        if ($score >= 60) return 'HIGH';
        if ($score >= 40) return 'MEDIUM';
        if ($score >= 20) return 'LOW';
        return 'MINIMAL';
    }
}
?>

Compliance Framework Integration

SOC 2 CC7.2 - System Monitoring

Control Objective: The entity monitors system components and the operation of controls.

Automated Evidence Collection:
  • Continuous vulnerability scanning logs
  • Asset inventory completeness reports
  • Security alert generation and response
  • Monitoring system uptime and coverage
  • Vulnerability detection effectiveness metrics
Evidence Sources:
• /assets/{customer_token}/ - Asset inventory
• /alerts/{customer_token}/ - Security alerts
• /asset/{uuid}/cves/ - Vulnerability details
ISO 27001 A.12.6.1 - Technical Vulnerabilities

Control Objective: Information about technical vulnerabilities of information systems being used shall be obtained in a timely fashion.

Automated Evidence Collection:
  • Timely vulnerability identification
  • Risk assessment of identified vulnerabilities
  • Remediation tracking and timelines
  • Vulnerability management process documentation
  • Technical vulnerability lifecycle management
Evidence Sources:
• CVE identification and tracking
• CVSS risk scoring automation
• Remediation timeline tracking

Deployment Configuration

 env('NODEWARE_BASE_URL', 'https://api.nodeware.com'),
    'default_scan_frequency' => env('NODEWARE_SCAN_FREQUENCY', 7), // days
    'compliance_thresholds' => [
        'soc2_cc7_2' => [
            'scan_freshness_days' => 7,
            'asset_completeness_percentage' => 90,
            'critical_vuln_tolerance' => 0,
            'monitoring_coverage_percentage' => 95
        ],
        'iso27001_a12_6_1' => [
            'vulnerability_identification_sla' => 24, // hours
            'risk_assessment_sla' => 72, // hours
            'critical_remediation_sla' => 168, // hours (7 days)
            'documentation_completeness' => 90 // percentage
        ]
    ],
    'risk_scoring' => [
        'critical_weight' => 10,
        'high_weight' => 5,
        'medium_weight' => 1,
        'low_weight' => 0.1
    ],
    'automation_rules' => [
        'auto_collect_evidence' => true,
        'generate_compliance_reports' => true,
        'alert_on_critical_findings' => true,
        'track_remediation_sla' => true
    ]
];

// Migration for API keys
Schema::table('api_keys', function (Blueprint $table) {
    $table->string('customer_token')->nullable()->after('api_secret');
    $table->json('scan_configuration')->nullable()->after('customer_token');
});
?>
Automated Collection Schedule
# Add to your Laravel scheduler (app/Console/Kernel.php)

protected function schedule(Schedule $schedule)
{
    // Daily vulnerability data collection
    $schedule->command('nodeware:collect-vulnerabilities')
        ->dailyAt('02:00')
        ->description('Collect vulnerability data from Nodeware');
    
    // Weekly compliance evidence generation
    $schedule->command('nodeware:generate-compliance-evidence')
        ->weeklyOn(1, '03:00')
        ->description('Generate SOC 2 and ISO 27001 compliance evidence');
    
    // Real-time critical alert monitoring (every 15 minutes)
    $schedule->command('nodeware:check-critical-alerts')
        ->everyFifteenMinutes()
        ->description('Monitor for critical vulnerability alerts');
}

ConnectSecure Integration

ConnectSecureVulnerabilityCollector

Integration with ConnectSecure's vulnerability management platform for comprehensive security assessment.

baseUrl = config('connectsecure.base_url', 'https://api.connectsecure.com');
    }
    
    public function authenticate(int $clientId): void
    {
        $this->clientId = $clientId;
        
        $apiKey = ApiKey::where('client_id', $clientId)
            ->where('provider', 'connectsecure')
            ->where('is_active', true)
            ->first();
            
        if (!$apiKey) {
            throw new \Exception("No active ConnectSecure API key found for client {$clientId}");
        }
        
        $this->apiKey = decrypt($apiKey->api_token);
        $this->apiSecret = decrypt($apiKey->api_secret);
    }
    
    public function collect(int $clientId): array
    {
        $this->authenticate($clientId);
        
        return [
            'organizations' => $this->getOrganizations(),
            'vulnerability_scans' => $this->getVulnerabilityScans(),
            'security_assessments' => $this->getSecurityAssessments(),
            'compliance_reports' => $this->getComplianceReports(),
            'risk_analysis' => $this->performRiskAnalysis(),
            'compliance_evidence' => $this->generateComplianceEvidence()
        ];
    }
    
    private function makeRequest(string $endpoint, array $params = []): array
    {
        $url = $this->baseUrl . $endpoint;
        
        $response = Http::withHeaders([
            'Authorization' => 'Bearer ' . $this->generateJWT(),
            'Accept' => 'application/json',
            'Content-Type' => 'application/json'
        ])->get($url, $params);
        
        if (!$response->successful()) {
            Log::error("ConnectSecure API request failed: {$response->status()} - {$response->body()}");
            throw new \Exception("API request failed: {$response->status()}");
        }
        
        return $response->json();
    }
    
    private function generateJWT(): string
    {
        // Implement JWT generation for ConnectSecure API authentication
        $header = json_encode(['typ' => 'JWT', 'alg' => 'HS256']);
        $payload = json_encode([
            'iss' => $this->apiKey,
            'iat' => time(),
            'exp' => time() + 3600
        ]);
        
        $base64Header = str_replace(['+', '/', '='], ['-', '_', ''], base64_encode($header));
        $base64Payload = str_replace(['+', '/', '='], ['-', '_', ''], base64_encode($payload));
        
        $signature = hash_hmac('sha256', $base64Header . "." . $base64Payload, $this->apiSecret, true);
        $base64Signature = str_replace(['+', '/', '='], ['-', '_', ''], base64_encode($signature));
        
        return $base64Header . "." . $base64Payload . "." . $base64Signature;
    }
    
    private function getOrganizations(): array
    {
        try {
            return $this->makeRequest('/api/v1/organizations');
        } catch (\Exception $e) {
            Log::error("Failed to get ConnectSecure organizations: " . $e->getMessage());
            return [];
        }
    }
    
    private function getVulnerabilityScans(): array
    {
        try {
            $scans = $this->makeRequest('/api/v1/vulnerability-scans', [
                'limit' => 100,
                'status' => 'completed'
            ]);
            
            return array_map(function($scan) {
                return [
                    'scan_id' => $scan['id'],
                    'scan_name' => $scan['name'],
                    'scan_date' => $scan['completed_at'],
                    'target_assets' => $scan['target_count'],
                    'vulnerabilities_found' => $scan['vulnerability_count'],
                    'severity_breakdown' => [
                        'critical' => $scan['critical_count'] ?? 0,
                        'high' => $scan['high_count'] ?? 0,
                        'medium' => $scan['medium_count'] ?? 0,
                        'low' => $scan['low_count'] ?? 0
                    ],
                    'scan_type' => $scan['scan_type'],
                    'compliance_frameworks' => $scan['compliance_frameworks'] ?? []
                ];
            }, $scans['data'] ?? []);
        } catch (\Exception $e) {
            Log::error("Failed to get ConnectSecure vulnerability scans: " . $e->getMessage());
            return [];
        }
    }
    
    private function getSecurityAssessments(): array
    {
        try {
            $assessments = $this->makeRequest('/api/v1/security-assessments');
            
            return array_map(function($assessment) {
                return [
                    'assessment_id' => $assessment['id'],
                    'assessment_type' => $assessment['type'],
                    'completion_date' => $assessment['completed_at'],
                    'overall_score' => $assessment['security_score'],
                    'risk_level' => $assessment['risk_level'],
                    'findings' => [
                        'total_findings' => $assessment['total_findings'],
                        'critical_findings' => $assessment['critical_findings'],
                        'high_findings' => $assessment['high_findings']
                    ],
                    'compliance_status' => $assessment['compliance_status'] ?? [],
                    'remediation_items' => $assessment['remediation_count'] ?? 0
                ];
            }, $assessments['data'] ?? []);
        } catch (\Exception $e) {
            Log::error("Failed to get ConnectSecure security assessments: " . $e->getMessage());
            return [];
        }
    }
    
    private function generateComplianceEvidence(): array
    {
        $scans = $this->getVulnerabilityScans();
        $assessments = $this->getSecurityAssessments();
        
        return [
            'SOC2_CC7_2' => [
                'control_description' => 'System monitoring through vulnerability management',
                'evidence_collected' => [
                    'regular_vulnerability_scanning' => $this->evidenceRegularScanning($scans),
                    'security_assessment_program' => $this->evidenceAssessmentProgram($assessments),
                    'vulnerability_remediation_tracking' => $this->evidenceRemediationTracking($scans),
                    'continuous_monitoring' => $this->evidenceContinuousMonitoring($scans)
                ],
                'compliance_score' => $this->calculateConnectSecureSOC2Score($scans, $assessments)
            ],
            'ISO27001_A_12_6_1' => [
                'control_description' => 'Technical vulnerability management',
                'evidence_collected' => [
                    'vulnerability_assessment_process' => $this->evidenceVulnAssessment($assessments),
                    'technical_vulnerability_identification' => $this->evidenceTechVulnId($scans),
                    'risk_evaluation' => $this->evidenceRiskEvaluation($assessments),
                    'remediation_planning' => $this->evidenceRemediationPlanning($scans)
                ],
                'compliance_score' => $this->calculateConnectSecureISO27001Score($scans, $assessments)
            ]
        ];
    }
    
    private function evidenceRegularScanning(array $scans): array
    {
        $recentScans = array_filter($scans, function($scan) {
            return Carbon::parse($scan['scan_date'])->diffInDays(now()) <= 30;
        });
        
        return [
            'total_scans_30_days' => count($recentScans),
            'scan_frequency' => count($recentScans) > 0 ? 'Regular' : 'Irregular',
            'assets_scanned' => array_sum(array_column($recentScans, 'target_assets')),
            'vulnerabilities_identified' => array_sum(array_column($recentScans, 'vulnerabilities_found'))
        ];
    }
    
    private function calculateConnectSecureSOC2Score(array $scans, array $assessments): float
    {
        $score = 100.0;
        
        // Check scan frequency (should be at least monthly)
        $recentScans = array_filter($scans, function($scan) {
            return Carbon::parse($scan['scan_date'])->diffInDays(now()) <= 35;
        });
        
        if (count($recentScans) === 0) {
            $score -= 40; // Major deduction for no recent scans
        }
        
        // Check critical vulnerability count
        $totalCritical = array_sum(array_map(function($scan) {
            return $scan['severity_breakdown']['critical'];
        }, $scans));
        
        if ($totalCritical > 0) {
            $score -= min($totalCritical * 5, 30); // Max 30 point deduction
        }
        
        // Check assessment scores
        if (!empty($assessments)) {
            $avgScore = array_sum(array_column($assessments, 'overall_score')) / count($assessments);
            if ($avgScore < 70) {
                $score -= (70 - $avgScore) * 0.5;
            }
        }
        
        return max($score, 0);
    }
}
?>

Lionguard M36 Integration

LionguardM36Collector

Integration with Lionguard M36 for comprehensive cyber risk assessment and vulnerability management.

instance = config('liongard.instance', 'us1');
        $this->baseUrl = "https://{$this->instance}.app.liongard.com/api/v2";
    }
    
    public function authenticate(int $clientId): void
    {
        $this->clientId = $clientId;
        
        $apiKey = ApiKey::where('client_id', $clientId)
            ->where('provider', 'liongard')
            ->where('is_active', true)
            ->first();
            
        if (!$apiKey) {
            throw new \Exception("No active Liongard API key found for client {$clientId}");
        }
        
        $this->accessKey = decrypt($apiKey->api_token);
        $this->accessSecret = decrypt($apiKey->api_secret);
    }
    
    public function collect(int $clientId): array
    {
        $this->authenticate($clientId);
        
        return [
            'environments' => $this->getEnvironments(),
            'detections' => $this->getDetections(),
            'compliance_metrics' => $this->getComplianceMetrics(),
            'asset_inventory' => $this->getAssetInventory(),
            'timeline_audit' => $this->getTimelineAudit(),
            'system_monitoring' => $this->getSystemMonitoring(),
            'compliance_evidence' => $this->generateComplianceEvidence()
        ];
    }
    
    private function makeRequest(string $endpoint, string $method = 'GET', array $data = []): array
    {
        $url = $this->baseUrl . $endpoint;
        $authHeader = base64_encode($this->accessKey . ':' . $this->accessSecret);
        
        $response = Http::withHeaders([
            'X-ROAR-API-KEY' => $authHeader,
            'Accept' => 'application/json',
            'Content-Type' => 'application/json'
        ]);
        
        if ($method === 'POST') {
            $response = $response->post($url, $data);
        } else {
            $response = $response->get($url, $data);
        }
        
        if (!$response->successful()) {
            Log::error("Liongard API request failed: {$response->status()} - {$response->body()}");
            throw new \Exception("API request failed: {$response->status()}");
        }
        
        $result = $response->json();
        return $result['Data'] ?? [];
    }
    
    private function getEnvironments(): array
    {
        try {
            $environments = $this->makeRequest('/environments/', 'GET', [
                'pageSize' => 100
            ]);
            
            return array_map(function($environment) {
                return [
                    'environment_id' => $environment['ID'],
                    'environment_name' => $environment['Name'],
                    'created_date' => $environment['CreatedOn'],
                    'updated_date' => $environment['UpdatedOn'],
                    'status' => $environment['Status'] ?? 'Active',
                    'agent_count' => $environment['AgentCount'] ?? 0,
                    'system_count' => $environment['SystemCount'] ?? 0
                ];
            }, $environments);
        } catch (\Exception $e) {
            Log::error("Failed to get Liongard environments: " . $e->getMessage());
            return [];
        }
    }
    
    private function getDetections(): array
    {
        try {
            $detections = $this->makeRequest('/detections/', 'POST', [
                'Pagination' => ['Page' => 1, 'PageSize' => 100],
                'StartDate' => now()->subDays(30)->toISOString(),
                'EndDate' => now()->toISOString()
            ]);
            
            return array_map(function($detection) {
                return [
                    'detection_id' => $detection['ID'],
                    'environment_id' => $detection['EnvironmentID'],
                    'system_id' => $detection['SystemID'],
                    'detection_type' => $detection['DetectionType'],
                    'severity' => $detection['Severity'] ?? 'Medium',
                    'description' => $detection['Description'],
                    'detected_date' => $detection['DetectedOn'],
                    'status' => $detection['Status'],
                    'remediation_status' => $detection['RemediationStatus'] ?? 'Open'
                ];
            }, $detections);
        } catch (\Exception $e) {
            Log::error("Failed to get Liongard detections: " . $e->getMessage());
            return [];
        }
    }
    
    private function getComplianceMetrics(): array
    {
        try {
            // Get predefined compliance metrics
            $complianceQueries = [
                'workstationPctEndpointDetectionResponseSoftwareInstalled',
                'workstationPctDomainFirewallEnabled',
                'workstationPctPrivateFirewallEnabled',
                'workstationPctPublicFirewallEnabled',
                'winServerEDRSoftware',
                'm365Defender',
                'workstationOsVersionPct',
                'domainAndWebsiteSecurityDomainsWithTlsSsl'
            ];
            
            $metrics = [];
            foreach ($this->getEnvironments() as $environment) {
                $environmentMetrics = $this->makeRequest(
                    "/environments/{$environment['environment_id']}/query",
                    'POST',
                    ['queryIdentifiers' => $complianceQueries]
                );
                
                $metrics[$environment['environment_id']] = [
                    'environment_name' => $environment['environment_name'],
                    'compliance_metrics' => $environmentMetrics
                ];
            }
            
            return $metrics;
        } catch (\Exception $e) {
            Log::error("Failed to get Liongard compliance metrics: " . $e->getMessage());
            return [];
        }
    }
    
    private function getAssetInventory(): array
    {
        try {
            // Get identity assets (users)
            $identities = $this->makeRequest('/inventory/identities/query', 'POST', [
                'Pagination' => ['Page' => 1, 'PageSize' => 100]
            ]);
            
            // Get device assets
            $devices = $this->makeRequest('/inventory/device-profiles/query', 'POST', [
                'Pagination' => ['Page' => 1, 'PageSize' => 100]
            ]);
            
            return [
                'identity_assets' => array_map(function($identity) {
                    return [
                        'identity_id' => $identity['ID'],
                        'display_name' => $identity['DisplayName'],
                        'classification' => $identity['Classification'], // service, user, admin, guest, etc.
                        'status' => $identity['Status'], // active, inactive, suspended, expired
                        'environment_id' => $identity['EnvironmentID'],
                        'last_seen' => $identity['LastSeen'],
                        'is_privileged' => in_array($identity['Classification'], ['admin', 'service'])
                    ];
                }, $identities),
                'device_assets' => array_map(function($device) {
                    return [
                        'device_id' => $device['ID'],
                        'device_name' => $device['DeviceName'],
                        'device_type' => $device['DeviceType'], // compute, network, iot-printer, storage
                        'category' => $device['Category'], // server, desktop, laptop, mobile
                        'classification' => $device['Classification'], // critical, standard
                        'status' => $device['Status'],
                        'environment_id' => $device['EnvironmentID'],
                        'is_managed' => $device['IsManaged'] ?? false,
                        'operating_system' => $device['OperatingSystem'] ?? 'Unknown'
                    ];
                }, $devices)
            ];
        } catch (\Exception $e) {
            Log::error("Failed to get Liongard asset inventory: " . $e->getMessage());
            return ['identity_assets' => [], 'device_assets' => []];
        }
    }
    
    private function getTimelineAudit(): array
    {
        try {
            $timeline = $this->makeRequest('/timelines/query', 'POST', [
                'Pagination' => ['Page' => 1, 'PageSize' => 100],
                'Filters' => [
                    ['FilterBy' => 'Status', 'Op' => 'matches_exactly', 'Value' => 'Completed']
                ],
                'Sorting' => [
                    ['SortBy' => 'CreatedOn', 'Direction' => 'DESC']
                ]
            ]);
            
            return array_map(function($entry) {
                return [
                    'timeline_id' => $entry['ID'],
                    'environment_id' => $entry['EnvironmentID'],
                    'system_id' => $entry['SystemID'],
                    'system_detail_id' => $entry['SystemDetailID'],
                    'status' => $entry['Status'],
                    'change_detections' => $entry['ChangeDetections'],
                    'created_on' => $entry['CreatedOn'],
                    'completed_on' => $entry['UpdatedOn'],
                    'exit_code' => $entry['ExitCode'],
                    'exit_message' => $entry['ExitMessage']
                ];
            }, $timeline);
        } catch (\Exception $e) {
            Log::error("Failed to get Liongard timeline audit: " . $e->getMessage());
            return [];
        }
    }
    
    private function getSystemMonitoring(): array
    {
        try {
            // Get all metrics for system monitoring
            $metrics = $this->makeRequest('/metrics/evaluate', 'POST', [
                'Pagination' => ['Page' => 1, 'PageSize' => 500]
            ]);
            
            return array_map(function($metric) {
                return [
                    'system_id' => $metric['SystemID'],
                    'system_name' => $metric['FriendlyName'],
                    'inspector_name' => $metric['InspectorName'],
                    'environment_name' => $metric['EnvironmentName'],
                    'metric_name' => $metric['MetricName'],
                    'metric_value' => $metric['Value'],
                    'timeline_date' => $metric['TimelineDate'],
                    'environment_id' => $metric['EnvironmentID']
                ];
            }, $metrics);
        } catch (\Exception $e) {
            Log::error("Failed to get Liongard system monitoring: " . $e->getMessage());
            return [];
        }
    }
    
    private function generateComplianceEvidence(): array
    {
        $assessments = $this->getCyberRiskAssessments();
        $reports = $this->getVulnerabilityReports();
        $scorecard = $this->getSecurityScorecard();
        
        return [
            'SOC2_CC7_2' => [
                'control_description' => 'System monitoring through continuous detection and metrics',
                'evidence_collected' => [
                    'environment_monitoring' => $this->evidenceEnvironmentMonitoring(),
                    'detection_capabilities' => $this->evidenceDetectionCapabilities(),
                    'system_metrics_tracking' => $this->evidenceSystemMetrics(),
                    'audit_trail_maintenance' => $this->evidenceAuditTrail()
                ],
                'compliance_score' => $this->calculateLiongardSOC2Score()
            ],
            'ISO27001_A_12_6_1' => [
                'control_description' => 'Technical vulnerability management through system inspections',
                'evidence_collected' => [
                    'systematic_vulnerability_detection' => $this->evidenceSystematicDetection(),
                    'asset_inventory_management' => $this->evidenceAssetInventory(),
                    'security_configuration_monitoring' => $this->evidenceSecurityConfiguration(),
                    'change_detection_tracking' => $this->evidenceChangeDetection()
                ],
                'compliance_score' => $this->calculateLiongardISO27001Score()
            ],
            'NIST_CSF_ID_RA' => [
                'control_description' => 'Asset and risk identification through comprehensive monitoring',
                'evidence_collected' => [
                    'asset_identification_completeness' => $this->evidenceAssetIdentification(),
                    'risk_assessment_through_detections' => $this->evidenceRiskAssessment(),
                    'threat_landscape_monitoring' => $this->evidenceThreatMonitoring(),
                    'continuous_asset_discovery' => $this->evidenceContinuousDiscovery()
                ],
                'compliance_score' => $this->calculateLiongardNISTScore()
            ]
        ];
    }
    
    private function evidenceEnvironmentMonitoring(): array
    {
        $environments = $this->getEnvironments();
        $activeEnvironments = array_filter($environments, fn($env) => $env['status'] === 'Active');
        
        return [
            'total_environments' => count($environments),
            'active_environments' => count($activeEnvironments),
            'monitoring_coverage' => count($environments) > 0 ? 'Comprehensive' : 'None',
            'average_systems_per_environment' => count($environments) > 0 ? 
                array_sum(array_column($environments, 'system_count')) / count($environments) : 0
        ];
    }
    
    private function evidenceDetectionCapabilities(): array
    {
        $detections = $this->getDetections();
        $recentDetections = array_filter($detections, function($detection) {
            return Carbon::parse($detection['detected_date'])->diffInDays(now()) <= 30;
        });
        
        return [
            'total_detections_30_days' => count($recentDetections),
            'detection_types' => array_count_values(array_column($recentDetections, 'detection_type')),
            'severity_distribution' => array_count_values(array_column($recentDetections, 'severity')),
            'detection_capability' => count($recentDetections) > 0 ? 'Active' : 'Limited'
        ];
    }
    
    private function calculateLiongardSOC2Score(): float
    {
        $score = 100.0;
        
        $environments = $this->getEnvironments();
        $detections = $this->getDetections();
        $timeline = $this->getTimelineAudit();
        
        // Check environment monitoring coverage
        $activeEnvironments = array_filter($environments, fn($env) => $env['status'] === 'Active');
        if (count($activeEnvironments) === 0) {
            $score -= 40; // Major deduction for no active monitoring
        }
        
        // Check detection system effectiveness
        $recentDetections = array_filter($detections, function($detection) {
            return Carbon::parse($detection['detected_date'])->diffInDays(now()) <= 30;
        });
        
        $criticalDetections = array_filter($recentDetections, fn($d) => $d['severity'] === 'Critical');
        if (count($criticalDetections) > 10) {
            $score -= min(count($criticalDetections) * 2, 30);
        }
        
        // Check audit trail completeness
        $recentAuditEntries = array_filter($timeline, function($entry) {
            return Carbon::parse($entry['created_on'])->diffInDays(now()) <= 7;
        });
        
        if (count($recentAuditEntries) === 0) {
            $score -= 20; // Deduction for no recent audit activity
        }
        
        return max($score, 0);
    }
    
    public function storeComplianceEvidence(int $clientId, array $results): void
    {
        $evidence = $results['compliance_evidence'];
        
        // Store SOC 2 CC7.2 evidence
        AssessmentEventsQuestion::updateOrCreate([
            'client_id' => $clientId,
            'framework' => 'SOC2',
            'control_id' => 'CC7.2',
            'evidence_source' => 'Liongard_System_Monitoring'
        ], [
            'compliance_score' => $evidence['SOC2_CC7_2']['compliance_score'],
            'evidence_collected' => json_encode($evidence['SOC2_CC7_2']['evidence_collected']),
            'analysis_date' => now(),
            'automated_collection' => true,
            'risk_level' => $this->determineRiskLevel($evidence['SOC2_CC7_2']['compliance_score'])
        ]);
        
        // Store ISO 27001 A.12.6.1 evidence
        AssessmentEventsQuestion::updateOrCreate([
            'client_id' => $clientId,
            'framework' => 'ISO27001',
            'control_id' => 'A.12.6.1',
            'evidence_source' => 'Lionguard_M36_Vulnerability_Management'
        ], [
            'compliance_score' => $evidence['ISO27001_A_12_6_1']['compliance_score'],
            'evidence_collected' => json_encode($evidence['ISO27001_A_12_6_1']['evidence_collected']),
            'analysis_date' => now(),
            'automated_collection' => true,
            'risk_level' => $this->determineRiskLevel($evidence['ISO27001_A_12_6_1']['compliance_score'])
        ]);
        
        // Store NIST CSF evidence
        AssessmentEventsQuestion::updateOrCreate([
            'client_id' => $clientId,
            'framework' => 'NIST_CSF',
            'control_id' => 'ID.RA',
            'evidence_source' => 'Lionguard_M36_Risk_Assessment'
        ], [
            'compliance_score' => $evidence['NIST_CSF_ID_RA']['compliance_score'],
            'evidence_collected' => json_encode($evidence['NIST_CSF_ID_RA']['evidence_collected']),
            'analysis_date' => now(),
            'automated_collection' => true,
            'risk_level' => $this->determineRiskLevel($evidence['NIST_CSF_ID_RA']['compliance_score'])
        ]);
    }
}
?>

Unified Vulnerability Management Service

UnifiedVulnerabilityManagementService

Orchestrates data collection from all vulnerability management platforms for comprehensive compliance automation.

nodewareCollector = $nodewareCollector;
        $this->connectSecureCollector = $connectSecureCollector;
        $this->lionguardCollector = $lionguardCollector;
        $this->rulesEngine = $rulesEngine;
    }
    
    public function performComprehensiveVulnerabilityAssessment(int $clientId): array
    {
        $results = [
            'client_id' => $clientId,
            'assessment_timestamp' => now(),
            'data_sources' => [],
            'unified_analysis' => [],
            'compliance_results' => [],
            'risk_assessment' => [],
            'recommendations' => []
        ];
        
        // Collect data from all available sources
        $results['data_sources'] = $this->collectFromAllSources($clientId);
        
        // Perform unified analysis
        $results['unified_analysis'] = $this->performUnifiedAnalysis($results['data_sources']);
        
        // Generate compliance assessments
        $results['compliance_results'] = $this->generateComplianceResults($results['unified_analysis']);
        
        // Calculate comprehensive risk assessment
        $results['risk_assessment'] = $this->calculateComprehensiveRisk($results['unified_analysis']);
        
        // Generate actionable recommendations
        $results['recommendations'] = $this->generateUnifiedRecommendations($results);
        
        // Store evidence in database
        $this->storeUnifiedEvidence($clientId, $results);
        
        return $results;
    }
    
    private function collectFromAllSources(int $clientId): array
    {
        $sources = [];
        
        // Collect from Nodeware
        try {
            $sources['nodeware'] = $this->nodewareCollector->collect($clientId);
            Log::info("Successfully collected Nodeware data for client {$clientId}");
        } catch (\Exception $e) {
            Log::warning("Failed to collect Nodeware data: " . $e->getMessage());
            $sources['nodeware'] = ['error' => $e->getMessage()];
        }
        
        // Collect from ConnectSecure
        try {
            $sources['connectsecure'] = $this->connectSecureCollector->collect($clientId);
            Log::info("Successfully collected ConnectSecure data for client {$clientId}");
        } catch (\Exception $e) {
            Log::warning("Failed to collect ConnectSecure data: " . $e->getMessage());
            $sources['connectsecure'] = ['error' => $e->getMessage()];
        }
        
        // Collect from Lionguard M36
        try {
            $sources['lionguard'] = $this->lionguardCollector->collect($clientId);
            Log::info("Successfully collected Lionguard data for client {$clientId}");
        } catch (\Exception $e) {
            Log::warning("Failed to collect Lionguard data: " . $e->getMessage());
            $sources['lionguard'] = ['error' => $e->getMessage()];
        }
        
        return $sources;
    }
    
    private function performUnifiedAnalysis(array $dataSources): array
    {
        return [
            'vulnerability_summary' => $this->aggregateVulnerabilities($dataSources),
            'asset_coverage' => $this->analyzeAssetCoverage($dataSources),
            'risk_correlation' => $this->correlateRiskFactors($dataSources),
            'compliance_coverage' => $this->analyzeComplianceCoverage($dataSources),
            'data_quality_metrics' => $this->assessDataQuality($dataSources)
        ];
    }
    
    private function aggregateVulnerabilities(array $dataSources): array
    {
        $aggregated = [
            'total_vulnerabilities' => 0,
            'critical_vulnerabilities' => 0,
            'high_vulnerabilities' => 0,
            'medium_vulnerabilities' => 0,
            'low_vulnerabilities' => 0,
            'unique_cves' => [],
            'affected_assets' => [],
            'source_breakdown' => []
        ];
        
        foreach ($dataSources as $source => $data) {
            if (isset($data['error'])) continue;
            
            $sourceVulns = $this->extractVulnerabilityData($source, $data);
            $aggregated['source_breakdown'][$source] = $sourceVulns;
            
            $aggregated['total_vulnerabilities'] += $sourceVulns['total'] ?? 0;
            $aggregated['critical_vulnerabilities'] += $sourceVulns['critical'] ?? 0;
            $aggregated['high_vulnerabilities'] += $sourceVulns['high'] ?? 0;
            $aggregated['medium_vulnerabilities'] += $sourceVulns['medium'] ?? 0;
            $aggregated['low_vulnerabilities'] += $sourceVulns['low'] ?? 0;
            
            if (isset($sourceVulns['cves'])) {
                $aggregated['unique_cves'] = array_merge($aggregated['unique_cves'], $sourceVulns['cves']);
            }
        }
        
        $aggregated['unique_cves'] = array_unique($aggregated['unique_cves']);
        $aggregated['unique_cve_count'] = count($aggregated['unique_cves']);
        
        return $aggregated;
    }
    
    private function generateComplianceResults(array $unifiedAnalysis): array
    {
        return [
            'SOC2_CC7_2' => $this->rulesEngine->evaluateSOC2CC72Compliance($unifiedAnalysis),
            'ISO27001_A_12_6_1' => $this->rulesEngine->evaluateISO27001A1261Compliance($unifiedAnalysis),
            'NIST_CSF_ID_RA' => $this->evaluateNISTCSFCompliance($unifiedAnalysis),
            'overall_compliance_score' => $this->calculateOverallComplianceScore($unifiedAnalysis)
        ];
    }
    
    private function calculateComprehensiveRisk(array $unifiedAnalysis): array
    {
        $riskMetrics = $this->rulesEngine->calculateVulnerabilityRiskScore($unifiedAnalysis);
        
        return [
            'overall_risk_score' => $riskMetrics['overall_risk_score'],
            'risk_level' => $riskMetrics['risk_level'],
            'risk_factors' => $riskMetrics['risk_factors'],
            'business_impact_assessment' => $this->assessBusinessImpact($unifiedAnalysis),
            'threat_landscape_analysis' => $this->analyzeThreatLandscape($unifiedAnalysis),
            'risk_mitigation_priority' => $this->prioritizeRiskMitigation($riskMetrics)
        ];
    }
    
    public function generateExecutiveDashboard(int $clientId): array
    {
        $assessment = $this->performComprehensiveVulnerabilityAssessment($clientId);
        
        return [
            'executive_summary' => [
                'overall_security_posture' => $this->calculateSecurityPosture($assessment),
                'compliance_status' => $this->summarizeComplianceStatus($assessment),
                'top_risks' => $this->identifyTopRisks($assessment),
                'immediate_actions' => $this->identifyImmediateActions($assessment)
            ],
            'key_metrics' => [
                'total_vulnerabilities' => $assessment['unified_analysis']['vulnerability_summary']['total_vulnerabilities'],
                'critical_vulnerabilities' => $assessment['unified_analysis']['vulnerability_summary']['critical_vulnerabilities'],
                'compliance_score' => $assessment['compliance_results']['overall_compliance_score'],
                'risk_level' => $assessment['risk_assessment']['risk_level']
            ],
            'trends' => $this->calculateSecurityTrends($clientId),
            'benchmarks' => $this->provideBenchmarkComparison($assessment)
        ];
    }
}
?>