feat: Add Cortex XDR integration with data fetching and summary generation.
This commit is contained in:
@@ -4,6 +4,7 @@ namespace App\Http\Controllers;
|
|||||||
|
|
||||||
use App\Services\CortexXdrService;
|
use App\Services\CortexXdrService;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Support\Facades\Cache;
|
||||||
|
|
||||||
class CortexXdrController extends Controller
|
class CortexXdrController extends Controller
|
||||||
{
|
{
|
||||||
@@ -23,7 +24,9 @@ class CortexXdrController extends Controller
|
|||||||
public function getData(CortexXdrService $cortexService)
|
public function getData(CortexXdrService $cortexService)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
$summary = $cortexService->getSummary();
|
$summary = Cache::remember('cortex_summary_data', 300, function () use ($cortexService) {
|
||||||
|
return $cortexService->getSummary();
|
||||||
|
});
|
||||||
return response()->json($summary);
|
return response()->json($summary);
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
return response()->json(['error' => $e->getMessage()], 500);
|
return response()->json(['error' => $e->getMessage()], 500);
|
||||||
|
|||||||
@@ -37,9 +37,9 @@ class CortexXdrService
|
|||||||
* Get Incidents
|
* Get Incidents
|
||||||
* Using pagination to fetch up to $limit 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.
|
* 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)) {
|
if (empty($this->apiKey) || empty($this->apiKeyId) || empty($this->baseUrl)) {
|
||||||
Log::warning('Cortex XDR credentials missing.');
|
Log::warning('Cortex XDR credentials missing.');
|
||||||
@@ -81,10 +81,10 @@ class CortexXdrService
|
|||||||
|
|
||||||
$response = Http::withHeaders($this->getHeaders())
|
$response = Http::withHeaders($this->getHeaders())
|
||||||
->post("{$this->baseUrl}/public_api/v1/{$endpoint}/", [
|
->post("{$this->baseUrl}/public_api/v1/{$endpoint}/", [
|
||||||
'request_data' => [
|
'request_data' => array_merge([
|
||||||
'search_from' => $offset,
|
'search_from' => $offset,
|
||||||
'search_to' => $offset + $currentBatchSize,
|
'search_to' => $offset + $currentBatchSize,
|
||||||
]
|
], !empty($filters) ? ['filters' => $filters] : [])
|
||||||
]);
|
]);
|
||||||
|
|
||||||
if ($response->successful()) {
|
if ($response->successful()) {
|
||||||
@@ -122,7 +122,15 @@ class CortexXdrService
|
|||||||
public function getSummary()
|
public function getSummary()
|
||||||
{
|
{
|
||||||
try {
|
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
|
$endpoints = $this->getEndpoints(1000); // Limit endpoints to 2000
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
// In dashboard context, we verify configuration separately.
|
// 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();
|
$endpointsDisconnected = collect($endpoints)->filter(fn($e) => strtolower($e['endpoint_status'] ?? '') === 'disconnected')->count();
|
||||||
|
|
||||||
// Filter only Active Incidents (New or Under Investigation)
|
// 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']));
|
$activeIncidents = collect($incidents)->filter(fn($i) => in_array($i['status'] ?? '', ['new', 'under_investigation']));
|
||||||
|
|
||||||
//die(var_dump($activeIncidents));
|
//die(var_dump($activeIncidents));
|
||||||
@@ -163,6 +173,7 @@ class CortexXdrService
|
|||||||
'endpoints_types' => $endpointTypes, // New Data
|
'endpoints_types' => $endpointTypes, // New Data
|
||||||
'recent_incidents' => collect($incidents)
|
'recent_incidents' => collect($incidents)
|
||||||
->filter(fn($i) => !in_array($i['status'] ?? '', ['resolved_true_positive', 'resolved_false_positive']))
|
->filter(fn($i) => !in_array($i['status'] ?? '', ['resolved_true_positive', 'resolved_false_positive']))
|
||||||
|
->sortByDesc('incident_id')
|
||||||
->slice(0, 10)
|
->slice(0, 10)
|
||||||
->values()
|
->values()
|
||||||
->all()
|
->all()
|
||||||
|
|||||||
Reference in New Issue
Block a user