From 69cc11e1882e20f2fa000a5fd30f66f444abee87 Mon Sep 17 00:00:00 2001 From: Manuel Abascal Date: Mon, 19 Feb 2024 18:51:16 +0200 Subject: [PATCH 1/7] Created SOC_AI resource (#460) --- .../utmstack/service/soc_ai/SocAIService.java | 2 +- .../web/rest/soc_ai/UtmSocAiResource.java | 44 +++++++++++++++++++ 2 files changed, 45 insertions(+), 1 deletion(-) create mode 100644 backend/src/main/java/com/park/utmstack/web/rest/soc_ai/UtmSocAiResource.java diff --git a/backend/src/main/java/com/park/utmstack/service/soc_ai/SocAIService.java b/backend/src/main/java/com/park/utmstack/service/soc_ai/SocAIService.java index 9d2011ef5..ce5549f27 100644 --- a/backend/src/main/java/com/park/utmstack/service/soc_ai/SocAIService.java +++ b/backend/src/main/java/com/park/utmstack/service/soc_ai/SocAIService.java @@ -36,7 +36,7 @@ public SocAIService(UtmAlertSocaiProcessingRequestService socaiProcessingRequest } - private void sendData(Object data) { + public void sendData(Object data) { final String ctx = CLASSNAME + ".sendData"; try { OkHttpClient client = new OkHttpClient.Builder() diff --git a/backend/src/main/java/com/park/utmstack/web/rest/soc_ai/UtmSocAiResource.java b/backend/src/main/java/com/park/utmstack/web/rest/soc_ai/UtmSocAiResource.java new file mode 100644 index 000000000..c680903e9 --- /dev/null +++ b/backend/src/main/java/com/park/utmstack/web/rest/soc_ai/UtmSocAiResource.java @@ -0,0 +1,44 @@ +package com.park.utmstack.web.rest.soc_ai; + +import com.park.utmstack.domain.application_events.enums.ApplicationEventType; +import com.park.utmstack.service.application_events.ApplicationEventService; +import com.park.utmstack.service.soc_ai.SocAIService; +import com.park.utmstack.web.rest.AccountResource; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping("/api") +public class UtmSocAiResource { + + private final Logger log = LoggerFactory.getLogger(AccountResource.class); + + private static final String CLASSNAME = "UtmSocAiResource"; + + private final ApplicationEventService applicationEventService; + private final SocAIService socAIService; + public UtmSocAiResource(SocAIService socAIService, ApplicationEventService applicationEventService) { + this.socAIService = socAIService; + this.applicationEventService = applicationEventService; + } + + @PostMapping("/send") + public ResponseEntity sendData(@RequestBody String[] alertsId) { + final String ctx = CLASSNAME + ".sendAlertsIds"; + try { + socAIService.sendData(alertsId); + return ResponseEntity.ok("Processing successful"); + } catch (Exception e) { + String msg = ctx + ": " + e.getMessage(); + log.error(msg); + applicationEventService.createEvent(msg, ApplicationEventType.ERROR); + + return ResponseEntity.internalServerError().body(msg); + } + } +} From 9685cb6f2e1952dbb96f24a126f0ec772b544351 Mon Sep 17 00:00:00 2001 From: Manuel Abascal Date: Tue, 20 Feb 2024 18:10:16 +0200 Subject: [PATCH 2/7] Feature SOC AI rework (#460) --- .../interceptor/auth-expired.interceptor.ts | 6 ++- .../alert-soc-ai/alert-soc-ai.component.html | 32 ++++++++++++++- .../alert-soc-ai/alert-soc-ai.component.ts | 40 +++++++++++++------ .../components/alert-soc-ai/soc-ai.type.ts | 8 ++++ 4 files changed, 71 insertions(+), 15 deletions(-) diff --git a/frontend/src/app/blocks/interceptor/auth-expired.interceptor.ts b/frontend/src/app/blocks/interceptor/auth-expired.interceptor.ts index 57d91111b..9236a70ff 100644 --- a/frontend/src/app/blocks/interceptor/auth-expired.interceptor.ts +++ b/frontend/src/app/blocks/interceptor/auth-expired.interceptor.ts @@ -4,10 +4,13 @@ import {Observable} from 'rxjs'; import {tap} from 'rxjs/operators'; import {AuthServerProvider} from '../../core/auth/auth-jwt.service'; import {HttpCancelService} from '../service/httpcancel.service'; +import {AccountService} from "../../core/auth/account.service"; @Injectable() export class AuthExpiredInterceptor implements HttpInterceptor { - constructor(private authServerProvider: AuthServerProvider, private httpCancelService: HttpCancelService) { + constructor(private authServerProvider: AuthServerProvider, + private httpCancelService: HttpCancelService, + private accountService: AccountService) { } intercept(request: HttpRequest, next: HttpHandler): Observable> { @@ -19,6 +22,7 @@ export class AuthExpiredInterceptor implements HttpInterceptor { if (err instanceof HttpErrorResponse) { if (err.status === 401 || err.status === 403) { this.authServerProvider.logout().subscribe(() => { + this.accountService.authenticate(null); this.httpCancelService.cancelPendingRequests(); console.log('UTMStack 401'); }); diff --git a/frontend/src/app/data-management/alert-management/shared/components/alert-soc-ai/alert-soc-ai.component.html b/frontend/src/app/data-management/alert-management/shared/components/alert-soc-ai/alert-soc-ai.component.html index da1a9c8f0..b86a2a1a0 100644 --- a/frontend/src/app/data-management/alert-management/shared/components/alert-soc-ai/alert-soc-ai.component.html +++ b/frontend/src/app/data-management/alert-management/shared/components/alert-soc-ai/alert-soc-ai.component.html @@ -15,7 +15,7 @@ -
+
Warning! This evaluation has been made by an Artificial Intelligence beta that is still in training mode. Use this information carefully and at your own risk. @@ -36,7 +36,7 @@ -
+
{{socAiResponse.nextSteps.length > 1 ? 'Next steps' : 'Next step'}}:
+ +
+
+ Info! + The SOC AI integration did not analyze this Alert; use the button below to kick-start an analysis +
+ +
+ +
+ +
+ +
+
+ Error! + An error occurred while the SOC AI was processing this alert; use the below button to relaunch the analysis. +
+ +
+ +
+ +
diff --git a/frontend/src/app/data-management/alert-management/shared/components/alert-soc-ai/alert-soc-ai.component.ts b/frontend/src/app/data-management/alert-management/shared/components/alert-soc-ai/alert-soc-ai.component.ts index f13c033f5..4666d6a9a 100644 --- a/frontend/src/app/data-management/alert-management/shared/components/alert-soc-ai/alert-soc-ai.component.ts +++ b/frontend/src/app/data-management/alert-management/shared/components/alert-soc-ai/alert-soc-ai.component.ts @@ -4,7 +4,7 @@ import {LOG_INDEX_PATTERN, SOC_AI_INDEX_PATTERN} from '../../../../../shared/con import {ElasticOperatorsEnum} from '../../../../../shared/enums/elastic-operators.enum'; import {ElasticDataService} from '../../../../../shared/services/elasticsearch/elastic-data.service'; import {ElasticFilterType} from '../../../../../shared/types/filter/elastic-filter.type'; -import {SocAiType} from './soc-ai.type'; +import {IndexSocAiStatus, SocAiType} from './soc-ai.type'; @Component({ selector: 'app-alert-soc-ai', @@ -15,11 +15,11 @@ export class AlertSocAiComponent implements OnInit, OnDestroy { @Input() alertID: string; @Input() socAiActive: boolean; socAiResponse: SocAiType; + indexSocAiStatus = IndexSocAiStatus; loading = false; private interval: any; - constructor(private elasticDataService: ElasticDataService, ) { - } + constructor(private elasticDataService: ElasticDataService, ) {} ngOnInit() { if (this.socAiActive) { @@ -27,26 +27,35 @@ export class AlertSocAiComponent implements OnInit, OnDestroy { } } - ngOnDestroy() { - clearInterval(this.interval); - } - getSocAiResponse() { const filter: ElasticFilterType[] = [{ field: 'activityId', operator: ElasticOperatorsEnum.IS, value: this.alertID }]; - this.elasticDataService.search(1, 1, - 1, SOC_AI_INDEX_PATTERN, filter).subscribe( - (res: HttpResponse) => { + this.elasticDataService.search(1, 1, 1, SOC_AI_INDEX_PATTERN, filter) + .subscribe((res: HttpResponse) => { this.loading = false; - if (!res || res.body === null || res.body.length === 0) { + res.body.status = 'Completed'; + if (!res || res.body.status === IndexSocAiStatus.Processing) { if (!this.interval) { this.startInterval(); } } else { - this.socAiResponse = res.body[0]; + // this.socAiResponse = res.body[0]; + this.socAiResponse = { + "@timestamp": "2024-02-19T09:35:50.275613061Z", + "severity": "3", + status : 'Error', + "category": "Brute Force", + "alertName": "Attempts to Brute Force a Microsoft 365 User Account", + "activityId": "b79a8f33-e9cd-4220-a270-cab5e523572b", + "classification": "possible incident", + "reasoning": [ + "The alert indicates that there have been failed login attempts to a Microsoft 365 user account using the same username 'jhondoe@gmail.com', originating from different IP addresses, which suggests a potential brute force attack. The logs confirm multiple failed login attempts from various IP addresses within a short time frame, triggering the alert for 'Attempts to Brute Force a Microsoft 365 User Account.' The log entries show consecutive failed login attempts due to 'IdsLocked' from different ClientIP addresses, indicating an automated process attempting unauthorized access. This pattern aligns with known brute force attack techniques." + ], + "nextSteps": [] + }; } }, (res: HttpResponse) => { @@ -60,4 +69,11 @@ export class AlertSocAiComponent implements OnInit, OnDestroy { }, 10000); } + ngOnDestroy() { + clearInterval(this.interval); + } + + processAlert() { + + } } diff --git a/frontend/src/app/data-management/alert-management/shared/components/alert-soc-ai/soc-ai.type.ts b/frontend/src/app/data-management/alert-management/shared/components/alert-soc-ai/soc-ai.type.ts index 9f2ebb0d7..d41dfd9dc 100644 --- a/frontend/src/app/data-management/alert-management/shared/components/alert-soc-ai/soc-ai.type.ts +++ b/frontend/src/app/data-management/alert-management/shared/components/alert-soc-ai/soc-ai.type.ts @@ -2,6 +2,7 @@ export class SocAiType { severity: string; category: string; alertName: string; + status: string; activityId: string; classification: string; reasoning: string[]; @@ -13,3 +14,10 @@ export class SocAiNextStep { action: string; details: string; } + +export enum IndexSocAiStatus { + Completed = 'Completed', + Processing = 'Processing', + Error = 'Error', + NotFound = 'NotFound' +} From 31f37683d68575c208151f9bd508a12859bb24f8 Mon Sep 17 00:00:00 2001 From: Manuel Abascal Date: Wed, 21 Feb 2024 16:29:14 +0200 Subject: [PATCH 3/7] Created SOC_AI resource (#460) --- .../com/park/utmstack/web/rest/soc_ai/UtmSocAiResource.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/backend/src/main/java/com/park/utmstack/web/rest/soc_ai/UtmSocAiResource.java b/backend/src/main/java/com/park/utmstack/web/rest/soc_ai/UtmSocAiResource.java index c680903e9..368ed188a 100644 --- a/backend/src/main/java/com/park/utmstack/web/rest/soc_ai/UtmSocAiResource.java +++ b/backend/src/main/java/com/park/utmstack/web/rest/soc_ai/UtmSocAiResource.java @@ -13,7 +13,7 @@ import org.springframework.web.bind.annotation.RestController; @RestController -@RequestMapping("/api") +@RequestMapping("/api/soc-ai") public class UtmSocAiResource { private final Logger log = LoggerFactory.getLogger(AccountResource.class); @@ -27,7 +27,7 @@ public UtmSocAiResource(SocAIService socAIService, ApplicationEventService appli this.applicationEventService = applicationEventService; } - @PostMapping("/send") + @PostMapping("/send-alerts") public ResponseEntity sendData(@RequestBody String[] alertsId) { final String ctx = CLASSNAME + ".sendAlertsIds"; try { From e87830620635ea2b19ea69e638b78fc930fd0d7f Mon Sep 17 00:00:00 2001 From: Manuel Abascal Date: Wed, 21 Feb 2024 16:32:24 +0200 Subject: [PATCH 4/7] Fixed SOC AI Rework (#460) --- .../alert-soc-ai/alert-soc-ai.component.html | 4 +-- .../alert-soc-ai/alert-soc-ai.component.ts | 35 ++++++++----------- .../shared/services/alert-soc-ai.service.ts | 21 +++++++++++ 3 files changed, 38 insertions(+), 22 deletions(-) create mode 100644 frontend/src/app/data-management/alert-management/shared/services/alert-soc-ai.service.ts diff --git a/frontend/src/app/data-management/alert-management/shared/components/alert-soc-ai/alert-soc-ai.component.html b/frontend/src/app/data-management/alert-management/shared/components/alert-soc-ai/alert-soc-ai.component.html index b86a2a1a0..d6ae30868 100644 --- a/frontend/src/app/data-management/alert-management/shared/components/alert-soc-ai/alert-soc-ai.component.html +++ b/frontend/src/app/data-management/alert-management/shared/components/alert-soc-ai/alert-soc-ai.component.html @@ -47,7 +47,7 @@
-
+
Info! The SOC AI integration did not analyze this Alert; use the button below to kick-start an analysis @@ -62,7 +62,7 @@
-
+
Error! An error occurred while the SOC AI was processing this alert; use the below button to relaunch the analysis.
diff --git a/frontend/src/app/data-management/alert-management/shared/components/alert-soc-ai/alert-soc-ai.component.ts b/frontend/src/app/data-management/alert-management/shared/components/alert-soc-ai/alert-soc-ai.component.ts index 4666d6a9a..9b263645a 100644 --- a/frontend/src/app/data-management/alert-management/shared/components/alert-soc-ai/alert-soc-ai.component.ts +++ b/frontend/src/app/data-management/alert-management/shared/components/alert-soc-ai/alert-soc-ai.component.ts @@ -5,6 +5,7 @@ import {ElasticOperatorsEnum} from '../../../../../shared/enums/elastic-operator import {ElasticDataService} from '../../../../../shared/services/elasticsearch/elastic-data.service'; import {ElasticFilterType} from '../../../../../shared/types/filter/elastic-filter.type'; import {IndexSocAiStatus, SocAiType} from './soc-ai.type'; +import {AlertSocAiService} from "../../services/alert-soc-ai.service"; @Component({ selector: 'app-alert-soc-ai', @@ -19,7 +20,8 @@ export class AlertSocAiComponent implements OnInit, OnDestroy { loading = false; private interval: any; - constructor(private elasticDataService: ElasticDataService, ) {} + constructor(private elasticDataService: ElasticDataService, + private alertSocAiService: AlertSocAiService) {} ngOnInit() { if (this.socAiActive) { @@ -36,26 +38,11 @@ export class AlertSocAiComponent implements OnInit, OnDestroy { this.elasticDataService.search(1, 1, 1, SOC_AI_INDEX_PATTERN, filter) .subscribe((res: HttpResponse) => { this.loading = false; - res.body.status = 'Completed'; - if (!res || res.body.status === IndexSocAiStatus.Processing) { - if (!this.interval) { - this.startInterval(); - } + // res.body.status = 'Completed'; + if (!res || res.body.length === 0) { + this.socAiResponse = res.body; } else { - // this.socAiResponse = res.body[0]; - this.socAiResponse = { - "@timestamp": "2024-02-19T09:35:50.275613061Z", - "severity": "3", - status : 'Error', - "category": "Brute Force", - "alertName": "Attempts to Brute Force a Microsoft 365 User Account", - "activityId": "b79a8f33-e9cd-4220-a270-cab5e523572b", - "classification": "possible incident", - "reasoning": [ - "The alert indicates that there have been failed login attempts to a Microsoft 365 user account using the same username 'jhondoe@gmail.com', originating from different IP addresses, which suggests a potential brute force attack. The logs confirm multiple failed login attempts from various IP addresses within a short time frame, triggering the alert for 'Attempts to Brute Force a Microsoft 365 User Account.' The log entries show consecutive failed login attempts due to 'IdsLocked' from different ClientIP addresses, indicating an automated process attempting unauthorized access. This pattern aligns with known brute force attack techniques." - ], - "nextSteps": [] - }; + this.socAiResponse = res.body[0]; } }, (res: HttpResponse) => { @@ -74,6 +61,14 @@ export class AlertSocAiComponent implements OnInit, OnDestroy { } processAlert() { + this.alertSocAiService.processAlertBySoc([this.alertID]) + .subscribe((res) => { + console.log(res); + }, + error => console.log(error)); + } + isEmpty(object: any) { + return Object.keys(object).length === 0; } } diff --git a/frontend/src/app/data-management/alert-management/shared/services/alert-soc-ai.service.ts b/frontend/src/app/data-management/alert-management/shared/services/alert-soc-ai.service.ts new file mode 100644 index 000000000..37e674170 --- /dev/null +++ b/frontend/src/app/data-management/alert-management/shared/services/alert-soc-ai.service.ts @@ -0,0 +1,21 @@ +import {HttpClient, HttpResponse} from '@angular/common/http'; +import {Injectable} from '@angular/core'; +import {Observable} from 'rxjs'; +import {SERVER_API_URL} from '../../../../app.constants'; + + +@Injectable({ + providedIn: 'root' +}) +export class AlertSocAiService { + + public resourceUrl = SERVER_API_URL + 'api/soc-ai'; + + constructor(private http: HttpClient) { + } + + processAlertBySoc(alertId: string[]): Observable> { + return this.http.post>(this.resourceUrl + '/send-alerts', alertId, {observe: 'response'}); + } + +} From 4bbab23ca0836c5d98428c98954cc3eff15597ed Mon Sep 17 00:00:00 2001 From: Manuel Abascal Date: Thu, 22 Feb 2024 19:06:59 +0200 Subject: [PATCH 5/7] Feature Created SOC_AI resource (#460) --- .../park/utmstack/web/rest/soc_ai/UtmSocAiResource.java | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/backend/src/main/java/com/park/utmstack/web/rest/soc_ai/UtmSocAiResource.java b/backend/src/main/java/com/park/utmstack/web/rest/soc_ai/UtmSocAiResource.java index 368ed188a..25a3000c1 100644 --- a/backend/src/main/java/com/park/utmstack/web/rest/soc_ai/UtmSocAiResource.java +++ b/backend/src/main/java/com/park/utmstack/web/rest/soc_ai/UtmSocAiResource.java @@ -6,12 +6,15 @@ import com.park.utmstack.web.rest.AccountResource; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; +import java.util.Map; + @RestController @RequestMapping("/api/soc-ai") public class UtmSocAiResource { @@ -28,17 +31,17 @@ public UtmSocAiResource(SocAIService socAIService, ApplicationEventService appli } @PostMapping("/send-alerts") - public ResponseEntity sendData(@RequestBody String[] alertsId) { + public ResponseEntity sendData(@RequestBody String[] alertsId) { final String ctx = CLASSNAME + ".sendAlertsIds"; try { socAIService.sendData(alertsId); - return ResponseEntity.ok("Processing successful"); + return ResponseEntity.ok().body(Map.of("status", "success", "message", "Processing successful")); } catch (Exception e) { String msg = ctx + ": " + e.getMessage(); log.error(msg); applicationEventService.createEvent(msg, ApplicationEventType.ERROR); - return ResponseEntity.internalServerError().body(msg); + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(Map.of("status", "error", "message", msg)); } } } From 947e2d9f556556209e40d13e8a31123379b7d051 Mon Sep 17 00:00:00 2001 From: Manuel Abascal Date: Thu, 22 Feb 2024 19:30:53 +0200 Subject: [PATCH 6/7] Feature Created SOC_AI resource (#460) --- .../com/park/utmstack/web/rest/soc_ai/UtmSocAiResource.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/src/main/java/com/park/utmstack/web/rest/soc_ai/UtmSocAiResource.java b/backend/src/main/java/com/park/utmstack/web/rest/soc_ai/UtmSocAiResource.java index 25a3000c1..6f74e9b08 100644 --- a/backend/src/main/java/com/park/utmstack/web/rest/soc_ai/UtmSocAiResource.java +++ b/backend/src/main/java/com/park/utmstack/web/rest/soc_ai/UtmSocAiResource.java @@ -30,7 +30,7 @@ public UtmSocAiResource(SocAIService socAIService, ApplicationEventService appli this.applicationEventService = applicationEventService; } - @PostMapping("/send-alerts") + @PostMapping("/alerts") public ResponseEntity sendData(@RequestBody String[] alertsId) { final String ctx = CLASSNAME + ".sendAlertsIds"; try { From c21691747fd1817b98dcfb355001a03eaef3c2e5 Mon Sep 17 00:00:00 2001 From: Manuel Abascal Date: Thu, 22 Feb 2024 19:44:27 +0200 Subject: [PATCH 7/7] Feature SOC-AI-Rework (#460) --- .../alert-view/alert-view.component.html | 2 +- .../alert-soc-ai/alert-soc-ai.component.html | 16 ++++++--- .../alert-soc-ai/alert-soc-ai.component.ts | 33 +++++++++++++++---- .../shared/services/alert-soc-ai.service.ts | 2 +- 4 files changed, 40 insertions(+), 13 deletions(-) diff --git a/frontend/src/app/data-management/alert-management/alert-view/alert-view.component.html b/frontend/src/app/data-management/alert-management/alert-view/alert-view.component.html index 1ba44af29..e036035dc 100644 --- a/frontend/src/app/data-management/alert-management/alert-view/alert-view.component.html +++ b/frontend/src/app/data-management/alert-management/alert-view/alert-view.component.html @@ -218,7 +218,7 @@
{{getRuleName()}}
- diff --git a/frontend/src/app/data-management/alert-management/shared/components/alert-soc-ai/alert-soc-ai.component.html b/frontend/src/app/data-management/alert-management/shared/components/alert-soc-ai/alert-soc-ai.component.html index d6ae30868..ec1edcb65 100644 --- a/frontend/src/app/data-management/alert-management/shared/components/alert-soc-ai/alert-soc-ai.component.html +++ b/frontend/src/app/data-management/alert-management/shared/components/alert-soc-ai/alert-soc-ai.component.html @@ -1,5 +1,5 @@
+ *ngIf="socAiResponse && socAiResponse.status === indexSocAiStatus.Processing">

The analysis of this alert is currently in progress. @@ -54,8 +54,11 @@

-
@@ -68,8 +71,11 @@
-
diff --git a/frontend/src/app/data-management/alert-management/shared/components/alert-soc-ai/alert-soc-ai.component.ts b/frontend/src/app/data-management/alert-management/shared/components/alert-soc-ai/alert-soc-ai.component.ts index 9b263645a..b0ff5d3a8 100644 --- a/frontend/src/app/data-management/alert-management/shared/components/alert-soc-ai/alert-soc-ai.component.ts +++ b/frontend/src/app/data-management/alert-management/shared/components/alert-soc-ai/alert-soc-ai.component.ts @@ -1,11 +1,12 @@ import {HttpResponse} from '@angular/common/http'; import {Component, Input, OnDestroy, OnInit} from '@angular/core'; +import {UtmToastService} from '../../../../../shared/alert/utm-toast.service'; import {LOG_INDEX_PATTERN, SOC_AI_INDEX_PATTERN} from '../../../../../shared/constants/main-index-pattern.constant'; import {ElasticOperatorsEnum} from '../../../../../shared/enums/elastic-operators.enum'; import {ElasticDataService} from '../../../../../shared/services/elasticsearch/elastic-data.service'; import {ElasticFilterType} from '../../../../../shared/types/filter/elastic-filter.type'; +import {AlertSocAiService} from '../../services/alert-soc-ai.service'; import {IndexSocAiStatus, SocAiType} from './soc-ai.type'; -import {AlertSocAiService} from "../../services/alert-soc-ai.service"; @Component({ selector: 'app-alert-soc-ai', @@ -18,10 +19,12 @@ export class AlertSocAiComponent implements OnInit, OnDestroy { socAiResponse: SocAiType; indexSocAiStatus = IndexSocAiStatus; loading = false; + loadingProcess = false; private interval: any; constructor(private elasticDataService: ElasticDataService, - private alertSocAiService: AlertSocAiService) {} + private alertSocAiService: AlertSocAiService, + private utmToastService: UtmToastService) {} ngOnInit() { if (this.socAiActive) { @@ -30,6 +33,7 @@ export class AlertSocAiComponent implements OnInit, OnDestroy { } getSocAiResponse() { + this.loading = true; const filter: ElasticFilterType[] = [{ field: 'activityId', operator: ElasticOperatorsEnum.IS, @@ -38,14 +42,24 @@ export class AlertSocAiComponent implements OnInit, OnDestroy { this.elasticDataService.search(1, 1, 1, SOC_AI_INDEX_PATTERN, filter) .subscribe((res: HttpResponse) => { this.loading = false; - // res.body.status = 'Completed'; if (!res || res.body.length === 0) { this.socAiResponse = res.body; } else { this.socAiResponse = res.body[0]; } + + if (this.socAiResponse.status === IndexSocAiStatus.Processing) { + if (!this.interval) { + this.startInterval(); + } + } else { + if (this.interval) { + clearInterval(this.interval); + } + } }, (res: HttpResponse) => { + this.loading = false; } ); } @@ -61,14 +75,21 @@ export class AlertSocAiComponent implements OnInit, OnDestroy { } processAlert() { + this.loadingProcess = true; this.alertSocAiService.processAlertBySoc([this.alertID]) .subscribe((res) => { - console.log(res); + setTimeout(() => { + this.loadingProcess = false; + this.getSocAiResponse(); + }, 3000); }, - error => console.log(error)); + (error) => { + this.utmToastService.showError('Error', 'An error occurred while processing the alert. Please try again later.'); + this.loadingProcess = false; + }); } isEmpty(object: any) { - return Object.keys(object).length === 0; + return object && Object.keys(object).length === 0; } } diff --git a/frontend/src/app/data-management/alert-management/shared/services/alert-soc-ai.service.ts b/frontend/src/app/data-management/alert-management/shared/services/alert-soc-ai.service.ts index 37e674170..97128ba9c 100644 --- a/frontend/src/app/data-management/alert-management/shared/services/alert-soc-ai.service.ts +++ b/frontend/src/app/data-management/alert-management/shared/services/alert-soc-ai.service.ts @@ -15,7 +15,7 @@ export class AlertSocAiService { } processAlertBySoc(alertId: string[]): Observable> { - return this.http.post>(this.resourceUrl + '/send-alerts', alertId, {observe: 'response'}); + return this.http.post>(this.resourceUrl + '/alerts', alertId, {observe: 'response'}); } }