feat: Add Cortex XDR integration with data fetching and summary generation.

This commit is contained in:
jeremy bayse
2026-02-14 08:21:06 +01:00
parent 7555e6ea8c
commit 1f9d2f7875
2 changed files with 21 additions and 7 deletions

View File

@@ -4,6 +4,7 @@ namespace App\Http\Controllers;
use App\Services\CortexXdrService;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Cache;
class CortexXdrController extends Controller
{
@@ -23,7 +24,9 @@ class CortexXdrController extends Controller
public function getData(CortexXdrService $cortexService)
{
try {
$summary = $cortexService->getSummary();
$summary = Cache::remember('cortex_summary_data', 300, function () use ($cortexService) {
return $cortexService->getSummary();
});
return response()->json($summary);
} catch (\Exception $e) {
return response()->json(['error' => $e->getMessage()], 500);

View File

@@ -37,9 +37,9 @@ class CortexXdrService
* Get Incidents
* Using pagination to fetch up to $limit incidents.
*/
public function getIncidents($limit = 1000)
public function getIncidents($limit = 1000, $filters = [])
{
return $this->fetchAll('incidents/get_incidents', 'incidents', $limit);
return $this->fetchAll('incidents/get_incidents', 'incidents', $limit, $filters);
}
/**
@@ -54,7 +54,7 @@ class CortexXdrService
/**
* Generic fetch method with pagination.
*/
private function fetchAll($endpoint, $dataKey, $limit)
private function fetchAll($endpoint, $dataKey, $limit, $filters = [])
{
if (empty($this->apiKey) || empty($this->apiKeyId) || empty($this->baseUrl)) {
Log::warning('Cortex XDR credentials missing.');
@@ -81,10 +81,10 @@ class CortexXdrService
$response = Http::withHeaders($this->getHeaders())
->post("{$this->baseUrl}/public_api/v1/{$endpoint}/", [
'request_data' => [
'request_data' => array_merge([
'search_from' => $offset,
'search_to' => $offset + $currentBatchSize,
]
], !empty($filters) ? ['filters' => $filters] : [])
]);
if ($response->successful()) {
@@ -122,7 +122,15 @@ class CortexXdrService
public function getSummary()
{
try {
$incidents = $this->getIncidents(1000); // Limit incidents to 1000 recent
// Filter to fetch only active incidents to improve performance
$filters = [
[
'field' => 'status',
'operator' => 'in',
'value' => ['new', 'under_investigation']
]
];
$incidents = $this->getIncidents(1000, $filters); // Limit incidents to 1000 recent active
$endpoints = $this->getEndpoints(1000); // Limit endpoints to 2000
} catch (\Exception $e) {
// In dashboard context, we verify configuration separately.
@@ -137,6 +145,8 @@ class CortexXdrService
$endpointsDisconnected = collect($endpoints)->filter(fn($e) => strtolower($e['endpoint_status'] ?? '') === 'disconnected')->count();
// Filter only Active Incidents (New or Under Investigation)
// Since we now filter at API level, we can just use the result,
// but keeping the collection filter adds a layer of safety if filters change.
$activeIncidents = collect($incidents)->filter(fn($i) => in_array($i['status'] ?? '', ['new', 'under_investigation']));
//die(var_dump($activeIncidents));
@@ -163,6 +173,7 @@ class CortexXdrService
'endpoints_types' => $endpointTypes, // New Data
'recent_incidents' => collect($incidents)
->filter(fn($i) => !in_array($i['status'] ?? '', ['resolved_true_positive', 'resolved_false_positive']))
->sortByDesc('incident_id')
->slice(0, 10)
->values()
->all()