From 3ecb0127d5c395c44fea173a44d6b51ef4d8023b Mon Sep 17 00:00:00 2001 From: Manuel Abascal Date: Fri, 28 Mar 2025 11:40:14 -0500 Subject: [PATCH 01/70] fix: move exception handling to prevent workflow interruptions --- .../service/UtmAlertTagRuleService.java | 66 ++++++++++--------- 1 file changed, 35 insertions(+), 31 deletions(-) diff --git a/backend/src/main/java/com/park/utmstack/service/UtmAlertTagRuleService.java b/backend/src/main/java/com/park/utmstack/service/UtmAlertTagRuleService.java index 761a26124..16e541ea6 100644 --- a/backend/src/main/java/com/park/utmstack/service/UtmAlertTagRuleService.java +++ b/backend/src/main/java/com/park/utmstack/service/UtmAlertTagRuleService.java @@ -104,7 +104,7 @@ public Page findByFilter(AlertTagRuleFilterVM filters, Pageable TypedParameterValue isDeleted = new TypedParameterValue(new BooleanType(), filters.getRuleDeleted()); return alertTagRuleRepository.findByFilter(id, name, conditionField, - conditionValue, tagIds, isActive, isDeleted, pageable); + conditionValue, tagIds, isActive, isDeleted, pageable); } catch (Exception e) { throw new Exception(ctx + ": " + e.getMessage()); } @@ -145,7 +145,7 @@ public void automaticReview() { final String ctx = CLASSNAME + ".automaticReview"; try { // If no new alerts have been received, stop execution - if (alertUtil.countAlertsByStatus(AlertStatus.AUTOMATIC_REVIEW.getCode()) == 0) + if (alertUtil.countAlertsByStatus(AlertStatus.OPEN.getCode()) == 0) return; // Getting all registered rules @@ -154,12 +154,12 @@ public void automaticReview() { // Getting rules that are actives and are not deleted if (!CollectionUtils.isEmpty(tagRules)) tagRules = tagRules.stream() - .filter(rule -> rule.getRuleActive() && !rule.getRuleDeleted()) - .collect(Collectors.toList()); + .filter(rule -> rule.getRuleActive() && !rule.getRuleDeleted()) + .collect(Collectors.toList()); // Getting rule evaluation start time Instant rulesEvaluationStart = LocalDateTime.now().toInstant(ZoneOffset.UTC) - .truncatedTo(ChronoUnit.SECONDS); + .truncatedTo(ChronoUnit.SECONDS); // If there is any rule if (!CollectionUtils.isEmpty(tagRules)) @@ -174,17 +174,17 @@ public void automaticReview() { } } - private void releaseToOpen(Instant rulesEvaluationStart) throws Exception { + private void releaseToOpen(Instant rulesEvaluationStart) { final String ctx = CLASSNAME + ".releaseToOpen"; try { String ruleScript = "ctx._source.status=%1$s;" + - "ctx._source.statusLabel='%2$s';" + - "ctx._source.statusObservation='%3$s';"; + "ctx._source.statusLabel='%2$s';" + + "ctx._source.statusObservation='%3$s';"; String statusObservation = "This alert has been evaluated by the tag rules engine"; String script = String.format(ruleScript, AlertStatus.OPEN.getCode(), AlertStatus.OPEN.getName(), - statusObservation); + statusObservation); List filters = new ArrayList<>(); filters.add(new FilterType(Constants.alertStatus, OperatorType.IS, AlertStatus.AUTOMATIC_REVIEW.getCode())); @@ -196,16 +196,18 @@ private void releaseToOpen(Instant rulesEvaluationStart) throws Exception { elasticsearchService.updateByQuery(query, indexPattern, script); alertPointcut.automaticAlertStatusChangePointcut(query, AlertStatus.OPEN.getCode(), - statusObservation, indexPattern); + statusObservation, indexPattern); } catch (Exception e) { - throw new Exception(ctx + ": " + e.getMessage()); + String msg = ctx + ": " + e.getMessage(); + eventService.createEvent(msg, ApplicationEventType.ERROR); + log.error(msg, e.getMessage(), e); } } - private void applyTagRule(List rules, Instant rulesEvaluationStart) throws Exception { + private void applyTagRule(List rules, Instant rulesEvaluationStart) { final String ctx = CLASSNAME + ".applyTagRule"; - try { - for (UtmAlertTagRule rule : rules) { + for (UtmAlertTagRule rule : rules) { + try { List filters = rule.getConditions(); filters.add(new FilterType(Constants.alertStatus, OperatorType.IS, AlertStatus.AUTOMATIC_REVIEW.getCode())); filters.add(new FilterType(Constants.timestamp, OperatorType.IS_LESS_THAN_OR_EQUALS, rulesEvaluationStart.toString())); @@ -213,20 +215,20 @@ private void applyTagRule(List rules, Instant rulesEvaluationSt Query query = SearchUtil.toQuery(filters); String script = "if (!ctx._source.containsKey('tags') || ctx._source.tags == null || ctx._source.tags.empty)\n" + - "\tctx._source.tags = new ArrayList();\n" + - "ctx._source.tags.addAll([%1$s]);\n" + - "ctx._source.tags = ctx._source.tags.stream().distinct().collect(Collectors.toList());\n" + - "\n" + - "if (!ctx._source.containsKey('TagRulesApplied') || ctx._source.TagRulesApplied == null || ctx._source.TagRulesApplied.empty)\n" + - "\tctx._source.TagRulesApplied = new ArrayList();\n" + - "ctx._source.TagRulesApplied.add(%2$s);\n" + - "ctx._source.TagRulesApplied = ctx._source.TagRulesApplied.stream().distinct().collect(Collectors.toList());" + - "\n" + - "if (ctx._source.tags.contains('False positive')) {\n" + - "\tctx._source.status=%3$s;\n" + - "\tctx._source.statusLabel='%4$s';\n" + - "\tctx._source.statusObservation='Status changed to completed because alert was tagged as False positive';\n" + - "\n}"; + "\tctx._source.tags = new ArrayList();\n" + + "ctx._source.tags.addAll([%1$s]);\n" + + "ctx._source.tags = ctx._source.tags.stream().distinct().collect(Collectors.toList());\n" + + "\n" + + "if (!ctx._source.containsKey('TagRulesApplied') || ctx._source.TagRulesApplied == null || ctx._source.TagRulesApplied.empty)\n" + + "\tctx._source.TagRulesApplied = new ArrayList();\n" + + "ctx._source.TagRulesApplied.add(%2$s);\n" + + "ctx._source.TagRulesApplied = ctx._source.TagRulesApplied.stream().distinct().collect(Collectors.toList());" + + "\n" + + "if (ctx._source.tags.contains('False positive')) {\n" + + "\tctx._source.status=%3$s;\n" + + "\tctx._source.statusLabel='%4$s';\n" + + "\tctx._source.statusObservation='Status changed to completed because alert was tagged as False positive';\n" + + "\n}"; List tags = alertTagService.findAllByIdIn(rule.getAppliedTagsAsListOfLong()); String indexPattern = Constants.SYS_INDEX_PATTERN.get(SystemIndexPattern.ALERTS); @@ -234,13 +236,15 @@ private void applyTagRule(List rules, Instant rulesEvaluationSt String tagsForInsert = tags.stream().map(tag -> "'" + tag.getTagName() + "'").collect(Collectors.joining(",")); elasticsearchService.updateByQuery(query, indexPattern, String.format(script, tagsForInsert, rule.getId(), - AlertStatus.COMPLETED.getCode(), AlertStatus.COMPLETED.getName())); + AlertStatus.COMPLETED.getCode(), AlertStatus.COMPLETED.getName())); String tagsForLogs = tags.stream().map(UtmAlertTag::getTagName).collect(Collectors.joining(",")); alertPointcut.automaticAlertTagsChangePointcut(query, tagsForLogs, rule.getRuleName(), indexPattern); + } catch (Exception e) { + String msg = String.format("%s: Error applying rule '%s' - %s", ctx, rule.getRuleName(), e.getMessage()); + eventService.createEvent(msg, ApplicationEventType.ERROR); + log.error(msg, e.getMessage(), e); } - } catch (Exception e) { - throw new Exception(ctx + ": " + e.getMessage()); } } } From 6740b67bf6985f633fdd546bf0fbe50b36d7b3ae Mon Sep 17 00:00:00 2001 From: Manuel Abascal Date: Fri, 28 Mar 2025 11:48:36 -0500 Subject: [PATCH 02/70] chore: set version --- version.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.yml b/version.yml index 63b9aa799..50c4306b0 100644 --- a/version.yml +++ b/version.yml @@ -1 +1 @@ -version: 10.7.1 +version: 10.7.3 From a47755af665e03cb0a084e945c779a22a09825fb Mon Sep 17 00:00:00 2001 From: Manuel Abascal Date: Fri, 28 Mar 2025 11:49:39 -0500 Subject: [PATCH 03/70] chore: set version --- version.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.yml b/version.yml index 50c4306b0..21c159ed9 100644 --- a/version.yml +++ b/version.yml @@ -1 +1 @@ -version: 10.7.3 +version: 10.7.3 \ No newline at end of file From aa09097e1f9bfe2f149aab2b8b47b8a25c7fbda1 Mon Sep 17 00:00:00 2001 From: Manuel Abascal Date: Fri, 28 Mar 2025 11:49:47 -0500 Subject: [PATCH 04/70] chore: update changelog --- CHANGELOG.md | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 544de8d50..22d29718e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,15 +1,4 @@ -# UTMStack 10.7.1 Release Notes +# UTMStack 10.7.2 Release Notes ### Bug Fixes --- Fixed responsive text alignment for action buttons in Log Explorer to enhance visual consistency. --- Fixed issues with loading data from saved queries in Log Explorer, ensuring the correct filter values are applied. --- Fixed issue where tabs remained open when navigating outside the Log Explorer scope to improve user experience. --- Fixed time filter issue where the date range was not applied correctly. --- Fixed incorrect query behavior when filtering incidents by ID. - -## New Features and Improvements --- Added organization name in app settings to distinguish alert and notification emails for better clarity. --- Enhanced the email notification system by including the organization name to improve recipient identification. --- Introduced new compliance reports aligned with the PCI DSS standard to expand auditing capabilities. --- Added new menu item **New Dashboard**. --- Added new menu item **New Visualization**. \ No newline at end of file +-- Improved exception handling in `automaticReview` to prevent the process from stopping due to errors, ensuring the system continues evaluating alerts even if a specific rule fails. \ No newline at end of file From 45a095d0ad180fbe54942e73badc3c666e79c99b Mon Sep 17 00:00:00 2001 From: Manuel Abascal Date: Mon, 31 Mar 2025 10:05:59 -0500 Subject: [PATCH 05/70] feat: filter compliance reports based on active integration --- .../config/UtmComplianceReportConfigService.java | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/backend/src/main/java/com/park/utmstack/service/compliance/config/UtmComplianceReportConfigService.java b/backend/src/main/java/com/park/utmstack/service/compliance/config/UtmComplianceReportConfigService.java index 00267b73c..0eba1978a 100644 --- a/backend/src/main/java/com/park/utmstack/service/compliance/config/UtmComplianceReportConfigService.java +++ b/backend/src/main/java/com/park/utmstack/service/compliance/config/UtmComplianceReportConfigService.java @@ -9,11 +9,13 @@ import com.park.utmstack.domain.compliance.UtmComplianceStandard; import com.park.utmstack.domain.compliance.UtmComplianceStandardSection; import com.park.utmstack.domain.compliance.enums.ComplianceStatus; +import com.park.utmstack.domain.index_pattern.UtmIndexPattern; import com.park.utmstack.repository.compliance.UtmComplianceReportConfigRepository; import com.park.utmstack.service.chart_builder.UtmDashboardService; import com.park.utmstack.service.chart_builder.UtmDashboardVisualizationService; import com.park.utmstack.service.elasticsearch.ElasticsearchService; import com.park.utmstack.service.elasticsearch.SearchUtil; +import com.park.utmstack.service.index_pattern.UtmIndexPatternService; import com.park.utmstack.util.UtilPagination; import com.park.utmstack.util.chart_builder.elasticsearch_dsl.requests.RequestDsl; import com.park.utmstack.util.exceptions.UtmElasticsearchException; @@ -21,6 +23,7 @@ import org.springframework.dao.DataIntegrityViolationException; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageImpl; +import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Pageable; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -32,6 +35,7 @@ import java.util.List; import java.util.Objects; import java.util.Optional; +import java.util.stream.Collectors; @Service public class UtmComplianceReportConfigService { @@ -52,7 +56,7 @@ public UtmComplianceReportConfigService(UtmComplianceReportConfigRepository comp UtmComplianceStandardService standardService, UtmComplianceStandardSectionService standardSectionService, UtmDashboardVisualizationService dashboardVisualizationService, ElasticsearchService elasticsearchService, - EntityManager em) { + EntityManager em, UtmIndexPatternService indexPatternService) { this.complianceReportConfigRepository = complianceReportConfigRepository; this.dashboardService = dashboardService; this.standardService = standardService; @@ -116,7 +120,12 @@ public Page getReportsByFilters(Long standardId, Stri } } - return page; + List activeCompliance = page.getContent() + .stream() + .filter(cp -> !cp.getDashboard().isEmpty() && cp.getDashboard().stream().allMatch(v -> v.getVisualization().getPattern().getActive())) + .collect(Collectors.toList()); + + return new PageImpl<>(activeCompliance, pageable, activeCompliance.size()); } From 1a4f237f0b4589747c8dde5d17cf8666f66a989e Mon Sep 17 00:00:00 2001 From: Manuel Abascal Date: Mon, 31 Mar 2025 10:06:23 -0500 Subject: [PATCH 06/70] chore: update changeLog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 22d29718e..0c4cc593f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,5 @@ # UTMStack 10.7.2 Release Notes +-- Implemented backend support for filtering compliance reports based on active integrations, optimizing query performance and data retrieval. ### Bug Fixes -- Improved exception handling in `automaticReview` to prevent the process from stopping due to errors, ensuring the system continues evaluating alerts even if a specific rule fails. \ No newline at end of file From 6689b604b6845d60d557bfeed12671e66f391c71 Mon Sep 17 00:00:00 2001 From: Manuel Abascal Date: Mon, 31 Mar 2025 10:36:46 -0500 Subject: [PATCH 07/70] feat: filter compliance reports based on active integration --- .../compliance-reports-view.component.ts | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/frontend/src/app/compliance/compliance-reports-view/compliance-reports-view.component.ts b/frontend/src/app/compliance/compliance-reports-view/compliance-reports-view.component.ts index 90819fef6..42c161763 100644 --- a/frontend/src/app/compliance/compliance-reports-view/compliance-reports-view.component.ts +++ b/frontend/src/app/compliance/compliance-reports-view/compliance-reports-view.component.ts @@ -79,10 +79,7 @@ export class ComplianceReportsViewComponent implements OnInit, OnChanges, OnDest })), tap(res => this.totalItems = Number(res.headers.get('X-Total-Count'))), map((res) => { - return res.body.filter(r => r.dashboard.length > 0 && r.dashboard.every(v => v.visualization.pattern.active)); - }), - map((res) => { - return res.map((r, index) => { + return res.body.map((r, index) => { return { ...r, selected: index === this.selected From 6b08e6a15542336f2f1bafac52e972499857f19d Mon Sep 17 00:00:00 2001 From: Manuel Abascal Date: Mon, 31 Mar 2025 10:42:03 -0500 Subject: [PATCH 08/70] fix: improve field value validation for "contains one of" and "does not contain one of" operators --- .../elastic-filter-add/elastic-filter-add.component.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/frontend/src/app/shared/components/utm/filters/utm-elastic-filter/elastic-filter-add/elastic-filter-add.component.ts b/frontend/src/app/shared/components/utm/filters/utm-elastic-filter/elastic-filter-add/elastic-filter-add.component.ts index ccd3d90e9..a9bc17c2c 100644 --- a/frontend/src/app/shared/components/utm/filters/utm-elastic-filter/elastic-filter-add/elastic-filter-add.component.ts +++ b/frontend/src/app/shared/components/utm/filters/utm-elastic-filter/elastic-filter-add/elastic-filter-add.component.ts @@ -250,7 +250,8 @@ export class ElasticFilterAddComponent implements OnInit { */ operatorFieldSelectable(): boolean { return this.operator === this.operatorEnum.IS || this.operator === this.operatorEnum.IS_NOT || - this.operator === this.operatorEnum.IS_ONE_OF || this.operator === this.operatorEnum.IS_NOT_ONE_OF; + this.operator === this.operatorEnum.IS_ONE_OF || this.operator === this.operatorEnum.IS_NOT_ONE_OF || + this.operator === this.operatorEnum.CONTAIN_ONE_OF || this.operator === this.operatorEnum.DOES_NOT_CONTAIN_ONE_OF; } /** From 418f4cd155cea75f6a06a5678400795e3668536f Mon Sep 17 00:00:00 2001 From: Manuel Abascal Date: Wed, 2 Apr 2025 09:42:10 -0500 Subject: [PATCH 09/70] feat: improve operator selection based on field type --- CHANGELOG.md | 3 +- .../alert-rule-create.component.html | 2 +- .../alert-rule-create.component.ts | 16 ++++++- .../elastic-filter-add.component.ts | 28 +++++++++--- .../shared/util/find-inverse-operator.util.ts | 3 -- .../shared/util/operator.service.ts | 45 +++++++++++++++++++ .../shared/enums/elastic-data-types.enum.ts | 3 +- 7 files changed, 87 insertions(+), 13 deletions(-) delete mode 100644 frontend/src/app/shared/components/utm/filters/utm-elastic-filter/shared/util/find-inverse-operator.util.ts create mode 100644 frontend/src/app/shared/components/utm/filters/utm-elastic-filter/shared/util/operator.service.ts diff --git a/CHANGELOG.md b/CHANGELOG.md index 0c4cc593f..351842a2c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,4 +2,5 @@ -- Implemented backend support for filtering compliance reports based on active integrations, optimizing query performance and data retrieval. ### Bug Fixes --- Improved exception handling in `automaticReview` to prevent the process from stopping due to errors, ensuring the system continues evaluating alerts even if a specific rule fails. \ No newline at end of file +-- Improved exception handling in `automaticReview` to prevent the process from stopping due to errors, ensuring the system continues evaluating alerts even if a specific rule fails. +-- Improved operator selection for more accurate and consistent filtering. \ No newline at end of file diff --git a/frontend/src/app/data-management/alert-management/shared/components/alert-rule-create/alert-rule-create.component.html b/frontend/src/app/data-management/alert-management/shared/components/alert-rule-create/alert-rule-create.component.html index b6071db27..77bcdddca 100644 --- a/frontend/src/app/data-management/alert-management/shared/components/alert-rule-create/alert-rule-create.component.html +++ b/frontend/src/app/data-management/alert-management/shared/components/alert-rule-create/alert-rule-create.component.html @@ -86,7 +86,7 @@ {{getFieldName(filter.field)}}:  !this.excludeFields.includes(value.field)); this.operators = FILTER_OPERATORS.filter(value => !this.excludeOperators.includes(value.operator)); } @@ -241,4 +247,12 @@ export class AlertRuleCreateComponent implements OnInit { isFalsePositive() { return this.selected.findIndex(value => value.tagName.includes('False positive')) !== -1; } + + getOperators(filter: ElasticFilterType) { + const field = this.fields.find(f => f.field === filter.field); + if (field) { + return this.operatorService.getOperators({name: field.field, type: field.type}, this.operators); + } + return this.operators; + } } diff --git a/frontend/src/app/shared/components/utm/filters/utm-elastic-filter/elastic-filter-add/elastic-filter-add.component.ts b/frontend/src/app/shared/components/utm/filters/utm-elastic-filter/elastic-filter-add/elastic-filter-add.component.ts index a9bc17c2c..0c7a3a30c 100644 --- a/frontend/src/app/shared/components/utm/filters/utm-elastic-filter/elastic-filter-add/elastic-filter-add.component.ts +++ b/frontend/src/app/shared/components/utm/filters/utm-elastic-filter/elastic-filter-add/elastic-filter-add.component.ts @@ -13,6 +13,7 @@ import {ElasticFilterType} from '../../../../../types/filter/elastic-filter.type import {OperatorsType} from '../../../../../types/filter/operators.type'; import {TimeFilterType} from '../../../../../types/time-filter.type'; import {resolveIcon} from '../../../../../util/elastic-fields.util'; +import {OperatorService} from '../shared/util/operator.service'; @Component({ selector: 'app-elastic-filter-add', @@ -63,7 +64,8 @@ export class ElasticFilterAddComponent implements OnInit { constructor(private fb: FormBuilder, private fieldDataBehavior: FieldDataService, - private elasticSearchIndexService: ElasticSearchIndexService) { + private elasticSearchIndexService: ElasticSearchIndexService, + private operatorService: OperatorService) { } ngOnInit() { @@ -289,14 +291,15 @@ export class ElasticFilterAddComponent implements OnInit { } } - /** + /*/!** * Return operators based on field type - */ + *!/ getOperators() { const index = this.getIndexField(); if (index !== -1) { const fieldType = this.fields[index].type; - if (fieldType === ElasticDataTypesEnum.TEXT || fieldType === ElasticDataTypesEnum.STRING) { + if (fieldType === ElasticDataTypesEnum.TEXT || fieldType === ElasticDataTypesEnum.STRING || + fieldType === ElasticDataTypesEnum.KEYWORD) { if (!this.field.name.includes('.keyword')) { this.operators = FILTER_OPERATORS.filter(value => value.operator !== ElasticOperatorsEnum.IS_BETWEEN && @@ -306,18 +309,31 @@ export class ElasticFilterAddComponent implements OnInit { value.operator !== ElasticOperatorsEnum.IS_BETWEEN && value.operator !== ElasticOperatorsEnum.CONTAIN && value.operator !== ElasticOperatorsEnum.DOES_NOT_CONTAIN && - value.operator !== ElasticOperatorsEnum.IS_NOT_BETWEEN); + value.operator !== ElasticOperatorsEnum.IS_NOT_BETWEEN && + value.operator !== ElasticOperatorsEnum.ENDS_WITH && + value.operator !== ElasticOperatorsEnum.NOT_ENDS_WITH && + value.operator !== ElasticOperatorsEnum.START_WITH && + value.operator !== ElasticOperatorsEnum.NOT_START_WITH); } } else if (fieldType === ElasticDataTypesEnum.LONG || fieldType === ElasticDataTypesEnum.NUMBER || fieldType === ElasticDataTypesEnum.DATE) { this.operators = FILTER_OPERATORS.filter(value => value.operator !== ElasticOperatorsEnum.CONTAIN && - value.operator !== ElasticOperatorsEnum.DOES_NOT_CONTAIN); + value.operator !== ElasticOperatorsEnum.DOES_NOT_CONTAIN && + value.operator !== ElasticOperatorsEnum.START_WITH && + value.operator !== ElasticOperatorsEnum.NOT_START_WITH); } else { this.operators = FILTER_OPERATORS; } } + }*/ + + getOperators() { + const index = this.getIndexField(); + if (index !== -1) { + this.operators = this.operatorService.getOperators(this.fields[index], this.operators); + } } /** diff --git a/frontend/src/app/shared/components/utm/filters/utm-elastic-filter/shared/util/find-inverse-operator.util.ts b/frontend/src/app/shared/components/utm/filters/utm-elastic-filter/shared/util/find-inverse-operator.util.ts deleted file mode 100644 index 82c9f5737..000000000 --- a/frontend/src/app/shared/components/utm/filters/utm-elastic-filter/shared/util/find-inverse-operator.util.ts +++ /dev/null @@ -1,3 +0,0 @@ -export function findInverseOperator() { - -} diff --git a/frontend/src/app/shared/components/utm/filters/utm-elastic-filter/shared/util/operator.service.ts b/frontend/src/app/shared/components/utm/filters/utm-elastic-filter/shared/util/operator.service.ts new file mode 100644 index 000000000..b6ec7e576 --- /dev/null +++ b/frontend/src/app/shared/components/utm/filters/utm-elastic-filter/shared/util/operator.service.ts @@ -0,0 +1,45 @@ +import {Injectable} from '@angular/core'; +import {FILTER_OPERATORS} from '../../../../../../constants/filter-operators.const'; +import {ElasticDataTypesEnum} from '../../../../../../enums/elastic-data-types.enum'; +import {ElasticOperatorsEnum} from '../../../../../../enums/elastic-operators.enum'; +import {ElasticSearchFieldInfoType} from '../../../../../../types/elasticsearch/elastic-search-field-info.type'; +import {OperatorsType} from '../../../../../../types/filter/operators.type'; + +@Injectable({ + providedIn: 'root' +}) +export class OperatorService { + + getOperators(field: ElasticSearchFieldInfoType, operators: OperatorsType[]) { + if (field.type === ElasticDataTypesEnum.TEXT || field.type === ElasticDataTypesEnum.STRING || + field.type === ElasticDataTypesEnum.KEYWORD) { + if (!field.name.includes('.keyword')) { + operators = FILTER_OPERATORS.filter(value => + value.operator !== ElasticOperatorsEnum.IS_BETWEEN && + value.operator !== ElasticOperatorsEnum.IS_NOT_BETWEEN); + } else { + operators = FILTER_OPERATORS.filter(value => + value.operator !== ElasticOperatorsEnum.IS_BETWEEN && + value.operator !== ElasticOperatorsEnum.CONTAIN && + value.operator !== ElasticOperatorsEnum.DOES_NOT_CONTAIN && + value.operator !== ElasticOperatorsEnum.IS_NOT_BETWEEN && + value.operator !== ElasticOperatorsEnum.ENDS_WITH && + value.operator !== ElasticOperatorsEnum.NOT_ENDS_WITH && + value.operator !== ElasticOperatorsEnum.START_WITH && + value.operator !== ElasticOperatorsEnum.NOT_START_WITH); + } + + } else if (field.type === ElasticDataTypesEnum.LONG || + field.type === ElasticDataTypesEnum.NUMBER || field.type === ElasticDataTypesEnum.DATE) { + operators = FILTER_OPERATORS.filter(value => + value.operator !== ElasticOperatorsEnum.CONTAIN && + value.operator !== ElasticOperatorsEnum.DOES_NOT_CONTAIN && + value.operator !== ElasticOperatorsEnum.START_WITH && + value.operator !== ElasticOperatorsEnum.NOT_START_WITH); + } else { + operators = FILTER_OPERATORS; + } + + return operators; + } +} diff --git a/frontend/src/app/shared/enums/elastic-data-types.enum.ts b/frontend/src/app/shared/enums/elastic-data-types.enum.ts index 2e627b095..22422368b 100644 --- a/frontend/src/app/shared/enums/elastic-data-types.enum.ts +++ b/frontend/src/app/shared/enums/elastic-data-types.enum.ts @@ -11,5 +11,6 @@ export enum ElasticDataTypesEnum { IP = 'ip', GEO = 'GEO', OBJECT = 'object', - BOOLEAN = 'boolean' + BOOLEAN = 'boolean', + KEYWORD = 'keyword' } From fe8aaa221a3f4129c8b3017078f74ebd7641209f Mon Sep 17 00:00:00 2001 From: Manuel Abascal Date: Wed, 2 Apr 2025 12:20:42 -0500 Subject: [PATCH 10/70] feat: improve operator selection based on field type --- .../log-analyzer-view/log-analyzer-view.component.html | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/frontend/src/app/log-analyzer/explorer/log-analyzer-view/log-analyzer-view.component.html b/frontend/src/app/log-analyzer/explorer/log-analyzer-view/log-analyzer-view.component.html index 3a08c50a0..aecf6d624 100644 --- a/frontend/src/app/log-analyzer/explorer/log-analyzer-view/log-analyzer-view.component.html +++ b/frontend/src/app/log-analyzer/explorer/log-analyzer-view/log-analyzer-view.component.html @@ -17,24 +17,19 @@ -
-
+
-
- -
-
From 3b5ff923d8dbd2db07c8dc97bceb9c9ae6158cbb Mon Sep 17 00:00:00 2001 From: Manuel Abascal Date: Fri, 4 Apr 2025 18:48:33 -0500 Subject: [PATCH 11/70] feat: allow edit and delete for non-owners only in dev mode --- .../utm-cp-reports.component.html | 6 +++--- .../utm-cp-reports/utm-cp-reports.component.ts | 6 ++++++ .../utm-cp-standard-section.component.html | 4 ++-- .../utm-cp-standard-section.component.ts | 6 ++++++ .../utm-cp-standard.component.html | 4 ++-- .../utm-cp-standard.component.ts | 6 ++++++ .../compliance-print-view.component.ts | 7 +++++++ .../shared/type/compliance-standard.type.ts | 1 + .../dashboard-list.component.html | 4 ++-- .../dashboard-list/dashboard-list.component.ts | 6 ++++++ .../viewer/table-view/table-view.component.ts | 4 +++- .../visualization-list.component.html | 4 ++-- .../visualization-list.component.ts | 6 ++++++ .../shared/chart/types/visualization.type.ts | 1 + .../shared/services/util/enviroment.service.ts | 18 ++++++++++++++++++ 15 files changed, 71 insertions(+), 12 deletions(-) create mode 100644 frontend/src/app/shared/services/util/enviroment.service.ts diff --git a/frontend/src/app/compliance/compliance-management/utm-cp-reports/utm-cp-reports.component.html b/frontend/src/app/compliance/compliance-management/utm-cp-reports/utm-cp-reports.component.html index fdba1b7cd..07932f3d0 100644 --- a/frontend/src/app/compliance/compliance-management/utm-cp-reports/utm-cp-reports.component.html +++ b/frontend/src/app/compliance/compliance-management/utm-cp-reports/utm-cp-reports.component.html @@ -23,15 +23,15 @@
- - - - - dashboards class="icon-copy3 cursor-pointer mr-2" ngbTooltip="Copy dashboard URL" tooltipClass="utm-tooltip-top"> - - diff --git a/frontend/src/app/graphic-builder/dashboard-builder/dashboard-list/dashboard-list.component.ts b/frontend/src/app/graphic-builder/dashboard-builder/dashboard-list/dashboard-list.component.ts index f8c78e168..6395d7465 100644 --- a/frontend/src/app/graphic-builder/dashboard-builder/dashboard-list/dashboard-list.component.ts +++ b/frontend/src/app/graphic-builder/dashboard-builder/dashboard-list/dashboard-list.component.ts @@ -17,6 +17,7 @@ import {DashboardImportComponent} from '../dashboard-import/dashboard-import.com import {UtmDashboardVisualizationService} from '../shared/services/utm-dashboard-visualization.service'; import {UtmDashboardService} from '../shared/services/utm-dashboard.service'; import {buildDashboardUrl} from '../shared/util/get-menu-url'; +import {EnvironmentService} from "../../../shared/services/util/enviroment.service"; @Component({ selector: 'app-dashboard-list', @@ -50,6 +51,7 @@ export class DashboardListComponent implements OnInit { private dashboardService: UtmDashboardService, private utmToastService: UtmToastService, private spinner: NgxSpinnerService, + private environment: EnvironmentService, private dashboardVisualizationService: UtmDashboardVisualizationService, private router: Router) { } @@ -63,6 +65,10 @@ export class DashboardListComponent implements OnInit { this.getDashboardList(); } + isDev(){ + return this.environment.isDev(); + } + onSortBy($event) { } diff --git a/frontend/src/app/graphic-builder/shared/components/viewer/table-view/table-view.component.ts b/frontend/src/app/graphic-builder/shared/components/viewer/table-view/table-view.component.ts index 6816c35cb..b36bf3577 100644 --- a/frontend/src/app/graphic-builder/shared/components/viewer/table-view/table-view.component.ts +++ b/frontend/src/app/graphic-builder/shared/components/viewer/table-view/table-view.component.ts @@ -130,7 +130,9 @@ export class TableViewComponent implements OnInit, AfterViewInit, OnChanges { runVisualization() { this.loadingOption = true; - this.runVisualizationService.run(this.visualization).subscribe(data => { + const request = this.visualization.page ? this.visualization.page : {}; + console.log(request); + this.runVisualizationService.run(this.visualization, request).subscribe(data => { this.empty = data.length === 0 || data[0].rows.length === 0; this.data = data.length > 0 ? data[0] : []; if (!this.empty) { diff --git a/frontend/src/app/graphic-builder/visualization/visualization-list/visualization-list.component.html b/frontend/src/app/graphic-builder/visualization/visualization-list/visualization-list.component.html index 1db7ea203..53977b3a4 100644 --- a/frontend/src/app/graphic-builder/visualization/visualization-list/visualization-list.component.html +++ b/frontend/src/app/graphic-builder/visualization/visualization-list/visualization-list.component.html @@ -126,11 +126,11 @@
Visualizations
- - diff --git a/frontend/src/app/graphic-builder/visualization/visualization-list/visualization-list.component.ts b/frontend/src/app/graphic-builder/visualization/visualization-list/visualization-list.component.ts index b1d7cd221..166224e3c 100644 --- a/frontend/src/app/graphic-builder/visualization/visualization-list/visualization-list.component.ts +++ b/frontend/src/app/graphic-builder/visualization/visualization-list/visualization-list.component.ts @@ -18,6 +18,7 @@ import {VisualizationService} from '../shared/services/visualization.service'; import {VisualizationCreateComponent} from '../visualization-create/visualization-create.component'; import {VisualizationDeleteComponent} from '../visualization-delete/visualization-delete.component'; import {VisualizationImportComponent} from '../visualization-import/visualization-import.component'; +import {EnvironmentService} from "../../../shared/services/util/enviroment.service"; @Component({ selector: 'app-visualization-list', @@ -52,6 +53,7 @@ export class VisualizationListComponent implements OnInit { private visualizationService: VisualizationService, private spinner: NgxSpinnerService, private router: Router, + private environment: EnvironmentService, private activatedRoute: ActivatedRoute) { } @@ -70,6 +72,10 @@ export class VisualizationListComponent implements OnInit { }); } + isDev(){ + return this.environment.isDev(); + } + editVisualization(vis: VisualizationType) { this.spinner.show('loadingSpinner'); const queryParams = {}; diff --git a/frontend/src/app/shared/chart/types/visualization.type.ts b/frontend/src/app/shared/chart/types/visualization.type.ts index 8ace01447..d3b4765aa 100644 --- a/frontend/src/app/shared/chart/types/visualization.type.ts +++ b/frontend/src/app/shared/chart/types/visualization.type.ts @@ -21,6 +21,7 @@ export class VisualizationType { aggregationType?: MetricDataType; chartAction?: any; systemOwner?: boolean; + page?: any; } diff --git a/frontend/src/app/shared/services/util/enviroment.service.ts b/frontend/src/app/shared/services/util/enviroment.service.ts new file mode 100644 index 000000000..fa469e6d3 --- /dev/null +++ b/frontend/src/app/shared/services/util/enviroment.service.ts @@ -0,0 +1,18 @@ +import { Injectable } from '@angular/core'; +import {environment} from '../../../../environments/environment'; + +@Injectable({ + providedIn: 'root' +}) +export class EnvironmentService { + + constructor() { } + + isDev(): boolean { + return !environment.production; + } + + isProd(): boolean { + return environment.production; + } +} From 37aff64812187958f0ef14f4c0d64099458b97a3 Mon Sep 17 00:00:00 2001 From: Manuel Abascal Date: Fri, 4 Apr 2025 19:18:18 -0500 Subject: [PATCH 12/70] feat: allow edit and delete for non-owners only in dev mode --- .../utm-cp-reports/utm-cp-reports.component.html | 4 ++-- .../utm-cp-reports/utm-cp-reports.component.ts | 10 +++------- .../utm-cp-standard-section.component.html | 4 ++-- .../utm-cp-standard-section.component.ts | 9 ++------- .../utm-cp-standard/utm-cp-standard.component.ts | 6 ------ .../dashboard-list/dashboard-list.component.html | 4 ++-- .../dashboard-list/dashboard-list.component.ts | 10 +++------- .../visualization-list.component.html | 4 ++-- .../visualization-list/visualization-list.component.ts | 10 +++------- 9 files changed, 19 insertions(+), 42 deletions(-) diff --git a/frontend/src/app/compliance/compliance-management/utm-cp-reports/utm-cp-reports.component.html b/frontend/src/app/compliance/compliance-management/utm-cp-reports/utm-cp-reports.component.html index 07932f3d0..261258c36 100644 --- a/frontend/src/app/compliance/compliance-management/utm-cp-reports/utm-cp-reports.component.html +++ b/frontend/src/app/compliance/compliance-management/utm-cp-reports/utm-cp-reports.component.html @@ -24,14 +24,14 @@ class="w-100 card p-2 d-flex flex-column flex-grow-1"> - - dashboards class="icon-copy3 cursor-pointer mr-2" ngbTooltip="Copy dashboard URL" tooltipClass="utm-tooltip-top"> - - diff --git a/frontend/src/app/graphic-builder/dashboard-builder/dashboard-list/dashboard-list.component.ts b/frontend/src/app/graphic-builder/dashboard-builder/dashboard-list/dashboard-list.component.ts index 6395d7465..22fdcef65 100644 --- a/frontend/src/app/graphic-builder/dashboard-builder/dashboard-list/dashboard-list.component.ts +++ b/frontend/src/app/graphic-builder/dashboard-builder/dashboard-list/dashboard-list.component.ts @@ -1,5 +1,5 @@ import {HttpResponse} from '@angular/common/http'; -import {Component, OnInit} from '@angular/core'; +import {Component, isDevMode, OnInit} from '@angular/core'; import {Router} from '@angular/router'; import {NgbModal} from '@ng-bootstrap/ng-bootstrap'; import * as moment from 'moment'; @@ -17,7 +17,6 @@ import {DashboardImportComponent} from '../dashboard-import/dashboard-import.com import {UtmDashboardVisualizationService} from '../shared/services/utm-dashboard-visualization.service'; import {UtmDashboardService} from '../shared/services/utm-dashboard.service'; import {buildDashboardUrl} from '../shared/util/get-menu-url'; -import {EnvironmentService} from "../../../shared/services/util/enviroment.service"; @Component({ selector: 'app-dashboard-list', @@ -46,12 +45,12 @@ export class DashboardListComponent implements OnInit { checkbox: boolean; selected: number[] = []; exporting = false; + isDevMode = isDevMode; constructor(private modalService: NgbModal, private dashboardService: UtmDashboardService, private utmToastService: UtmToastService, private spinner: NgxSpinnerService, - private environment: EnvironmentService, private dashboardVisualizationService: UtmDashboardVisualizationService, private router: Router) { } @@ -65,10 +64,6 @@ export class DashboardListComponent implements OnInit { this.getDashboardList(); } - isDev(){ - return this.environment.isDev(); - } - onSortBy($event) { } @@ -216,4 +211,5 @@ export class DashboardListComponent implements OnInit { this.searching = false; this.loading = false; } + } diff --git a/frontend/src/app/graphic-builder/visualization/visualization-list/visualization-list.component.html b/frontend/src/app/graphic-builder/visualization/visualization-list/visualization-list.component.html index 53977b3a4..e02e075a7 100644 --- a/frontend/src/app/graphic-builder/visualization/visualization-list/visualization-list.component.html +++ b/frontend/src/app/graphic-builder/visualization/visualization-list/visualization-list.component.html @@ -126,11 +126,11 @@
Visualizations
- - diff --git a/frontend/src/app/graphic-builder/visualization/visualization-list/visualization-list.component.ts b/frontend/src/app/graphic-builder/visualization/visualization-list/visualization-list.component.ts index 166224e3c..bd0cd015a 100644 --- a/frontend/src/app/graphic-builder/visualization/visualization-list/visualization-list.component.ts +++ b/frontend/src/app/graphic-builder/visualization/visualization-list/visualization-list.component.ts @@ -1,5 +1,5 @@ import {HttpResponse} from '@angular/common/http'; -import {Component, OnInit, QueryList, ViewChildren} from '@angular/core'; +import {Component, isDevMode, OnInit, QueryList, ViewChildren} from '@angular/core'; import {ActivatedRoute, Router} from '@angular/router'; import {NgbModal} from '@ng-bootstrap/ng-bootstrap'; @@ -18,7 +18,6 @@ import {VisualizationService} from '../shared/services/visualization.service'; import {VisualizationCreateComponent} from '../visualization-create/visualization-create.component'; import {VisualizationDeleteComponent} from '../visualization-delete/visualization-delete.component'; import {VisualizationImportComponent} from '../visualization-import/visualization-import.component'; -import {EnvironmentService} from "../../../shared/services/util/enviroment.service"; @Component({ selector: 'app-visualization-list', @@ -48,12 +47,12 @@ export class VisualizationListComponent implements OnInit { allPageSelected: boolean; sort: SortEvent; private requestParams: any; + isDevMode = isDevMode; constructor(private modalService: NgbModal, private visualizationService: VisualizationService, private spinner: NgxSpinnerService, private router: Router, - private environment: EnvironmentService, private activatedRoute: ActivatedRoute) { } @@ -72,10 +71,6 @@ export class VisualizationListComponent implements OnInit { }); } - isDev(){ - return this.environment.isDev(); - } - editVisualization(vis: VisualizationType) { this.spinner.show('loadingSpinner'); const queryParams = {}; @@ -204,4 +199,5 @@ export class VisualizationListComponent implements OnInit { private onError(error) { // this.alertService.error(error.error, error.message, null); } + } From bc841ba872df07b22613171930c702dbdf290b70 Mon Sep 17 00:00:00 2001 From: Manuel Abascal Date: Sat, 5 Apr 2025 10:10:09 -0500 Subject: [PATCH 13/70] feat: add tag rule --- .../alert-rules/alert-rules.component.html | 3 ++ .../alert-rules/alert-rules.component.ts | 16 +++++++++ .../alert-rule-create.component.html | 20 +++++++++++ .../alert-rule-create.component.ts | 35 ++++++++++++++++--- 4 files changed, 70 insertions(+), 4 deletions(-) diff --git a/frontend/src/app/data-management/alert-management/alert-rules/alert-rules.component.html b/frontend/src/app/data-management/alert-management/alert-rules/alert-rules.component.html index fcdd50a7b..8f927abdf 100644 --- a/frontend/src/app/data-management/alert-management/alert-rules/alert-rules.component.html +++ b/frontend/src/app/data-management/alert-management/alert-rules/alert-rules.component.html @@ -7,6 +7,9 @@
Alerts rules
routerLink="/data/alert/view"> Manage alerts +
diff --git a/frontend/src/app/data-management/alert-management/alert-rules/alert-rules.component.ts b/frontend/src/app/data-management/alert-management/alert-rules/alert-rules.component.ts index eda6db80f..848205759 100644 --- a/frontend/src/app/data-management/alert-management/alert-rules/alert-rules.component.ts +++ b/frontend/src/app/data-management/alert-management/alert-rules/alert-rules.component.ts @@ -12,6 +12,8 @@ import {TimeFilterType} from '../../../shared/types/time-filter.type'; import {AlertRulesService} from '../shared/services/alert-rules.service'; import {AlertTagService} from '../shared/services/alert-tag.service'; import {AlertRuleType} from './alert-rule.type'; +import {AlertRuleCreateComponent} from "../shared/components/alert-rule-create/alert-rule-create.component"; +import {FALSE_POSITIVE_OBJECT} from "../../../shared/constants/alert/alert-field.constant"; @Component({ selector: 'app-rules', @@ -35,6 +37,7 @@ export class AlertRulesComponent implements OnInit { }; viewRule: AlertRuleType; tags: AlertTags[]; + rule: AlertRuleType; constructor(private sourcesService: SourcesService, @@ -127,4 +130,17 @@ export class AlertRulesComponent implements OnInit { this.request.tagIds = $event.length === 0 ? null : $event.map(value => value.id); this.getRules(); } + + createRule() { + const modal = this.modalService.open(AlertRuleCreateComponent, {centered: true, size: 'lg'}); + const falsePositive: AlertTags[] = [FALSE_POSITIVE_OBJECT]; + if (this.rule) { + modal.componentInstance.rule = this.rule; + } + modal.componentInstance.isForComplete = true; + modal.componentInstance.tags = falsePositive; + modal.componentInstance.ruleAdd.subscribe(rule => { + this.rule = rule; + }); + } } diff --git a/frontend/src/app/data-management/alert-management/shared/components/alert-rule-create/alert-rule-create.component.html b/frontend/src/app/data-management/alert-management/shared/components/alert-rule-create/alert-rule-create.component.html index 77bcdddca..45417cb43 100644 --- a/frontend/src/app/data-management/alert-management/shared/components/alert-rule-create/alert-rule-create.component.html +++ b/frontend/src/app/data-management/alert-management/shared/components/alert-rule-create/alert-rule-create.component.html @@ -74,6 +74,26 @@
+
+ +
+ + +
+
+
diff --git a/frontend/src/app/data-management/alert-management/shared/components/alert-rule-create/alert-rule-create.component.ts b/frontend/src/app/data-management/alert-management/shared/components/alert-rule-create/alert-rule-create.component.ts index 35b2eff82..0a0832322 100644 --- a/frontend/src/app/data-management/alert-management/shared/components/alert-rule-create/alert-rule-create.component.ts +++ b/frontend/src/app/data-management/alert-management/shared/components/alert-rule-create/alert-rule-create.component.ts @@ -29,17 +29,18 @@ import { ALERT_STATUS_LABEL_FIELD, ALERT_TAGS_FIELD, ALERT_TIMESTAMP_FIELD, - EVENT_IS_ALERT, + EVENT_IS_ALERT, INCIDENT_AUTOMATION_ALERT_FIELDS, LOG_RELATED_ID_EVENT_FIELD } from '../../../../../shared/constants/alert/alert-field.constant'; import {CLOSED} from '../../../../../shared/constants/alert/alert-status.constant'; import {FILTER_OPERATORS} from '../../../../../shared/constants/filter-operators.const'; +import {ALERT_INDEX_PATTERN} from "../../../../../shared/constants/main-index-pattern.constant"; import {ElasticOperatorsEnum} from '../../../../../shared/enums/elastic-operators.enum'; +import {ElasticSearchIndexService} from "../../../../../shared/services/elasticsearch/elasticsearch-index.service"; import {AlertTags} from '../../../../../shared/types/alert/alert-tag.type'; import {UtmAlertType} from '../../../../../shared/types/alert/utm-alert.type'; import {ElasticFilterType} from '../../../../../shared/types/filter/elastic-filter.type'; import {OperatorsType} from '../../../../../shared/types/filter/operators.type'; -import {UtmFieldType} from '../../../../../shared/types/table/utm-field.type'; import {getValueFromPropertyPath} from '../../../../../shared/util/get-value-object-from-property-path.util'; import {InputClassResolve} from '../../../../../shared/util/input-class-resolve'; import {AlertRuleType} from '../../../alert-rules/alert-rule.type'; @@ -49,7 +50,8 @@ import {AlertManagementService} from '../../services/alert-management.service'; import {AlertRulesService} from '../../services/alert-rules.service'; import {AlertTagService} from '../../services/alert-tag.service'; import {setAlertPropertyValue} from '../../util/alert-util-function'; -import {ElasticSearchFieldInfoType} from "../../../../../shared/types/elasticsearch/elastic-search-field-info.type"; +import {sanitizeFilters} from "../../../../../shared/util/elastic-filter.util"; +import {HttpResponse} from "@angular/common/http"; @Component({ selector: 'app-alert-rule-create', @@ -100,6 +102,8 @@ export class AlertRuleCreateComponent implements OnInit { uuid = UUID.UUID(); tagging = false; ElasticOperatorsEnum = ElasticOperatorsEnum; + alerts = []; + loadingAlerts: boolean = false; constructor(public activeModal: NgbActiveModal, public inputClass: InputClassResolve, @@ -110,12 +114,17 @@ export class AlertRuleCreateComponent implements OnInit { private alertUpdateTagBehavior: AlertUpdateTagBehavior, private alertServiceManagement: AlertManagementService, private alertTagService: AlertTagService, - private operatorService: OperatorService) { + private operatorService: OperatorService, + private elasticDataService: ElasticSearchIndexService) { + this.fields = ALERT_FIELDS.filter(value => !this.excludeFields.includes(value.field)); this.operators = FILTER_OPERATORS.filter(value => !this.excludeOperators.includes(value.operator)); } ngOnInit() { + if ( !this.alert) { + this.getAlerts(); + } this.getTags(); this.initForm(); this.createDefaultFilters(); @@ -255,4 +264,22 @@ export class AlertRuleCreateComponent implements OnInit { } return this.operators; } + + getAlert() { + this.elasticDataService.search( + this.page, + this.itemsPerPage, + 100000000, + this.dataNature, + sanitizeFilters(this.filters), this.sortBy).subscribe( + (res: HttpResponse) => { + this.alerts = res.body; + this.loading = false; + this.refreshingAlert = false; + }, + (res: HttpResponse) => { + this.utmToastService.showError('Error', 'An error occurred while listing the alerts. Please try again later.'); + } + ); + } } From 0d74492a385fc73fe596d834793e3dcb4261ce39 Mon Sep 17 00:00:00 2001 From: Manuel Abascal Date: Sat, 5 Apr 2025 10:59:00 -0500 Subject: [PATCH 14/70] feat: add tag rule --- .../alert-rule-create.component.html | 27 ++++---- .../alert-rule-create.component.ts | 64 ++++++++++++++++--- 2 files changed, 70 insertions(+), 21 deletions(-) diff --git a/frontend/src/app/data-management/alert-management/shared/components/alert-rule-create/alert-rule-create.component.html b/frontend/src/app/data-management/alert-management/shared/components/alert-rule-create/alert-rule-create.component.html index 45417cb43..08936079d 100644 --- a/frontend/src/app/data-management/alert-management/shared/components/alert-rule-create/alert-rule-create.component.html +++ b/frontend/src/app/data-management/alert-management/shared/components/alert-rule-create/alert-rule-create.component.html @@ -77,19 +77,20 @@
- +
diff --git a/frontend/src/app/data-management/alert-management/shared/components/alert-rule-create/alert-rule-create.component.ts b/frontend/src/app/data-management/alert-management/shared/components/alert-rule-create/alert-rule-create.component.ts index 0a0832322..14a457b0c 100644 --- a/frontend/src/app/data-management/alert-management/shared/components/alert-rule-create/alert-rule-create.component.ts +++ b/frontend/src/app/data-management/alert-management/shared/components/alert-rule-create/alert-rule-create.component.ts @@ -52,6 +52,7 @@ import {AlertTagService} from '../../services/alert-tag.service'; import {setAlertPropertyValue} from '../../util/alert-util-function'; import {sanitizeFilters} from "../../../../../shared/util/elastic-filter.util"; import {HttpResponse} from "@angular/common/http"; +import {ElasticDataService} from "../../../../../shared/services/elasticsearch/elastic-data.service"; @Component({ selector: 'app-alert-rule-create', @@ -103,7 +104,20 @@ export class AlertRuleCreateComponent implements OnInit { tagging = false; ElasticOperatorsEnum = ElasticOperatorsEnum; alerts = []; - loadingAlerts: boolean = false; + alertRequest = { + page: 0, + size: 100, + sort: '@timestamp,desc', + index: ALERT_INDEX_PATTERN, + filters: [ + {field: 'status', operator: 'IS_NOT', value: 1}, + {field: 'tags', operator: 'IS_NOT', value: 'False positive'}, + {field: '@timestamp', operator: 'IS_BETWEEN', value: ['now-30d', 'now']} + ], + dataNature: null, + }; + loading = false; + refreshingAlert = false; constructor(public activeModal: NgbActiveModal, public inputClass: InputClassResolve, @@ -115,7 +129,7 @@ export class AlertRuleCreateComponent implements OnInit { private alertServiceManagement: AlertManagementService, private alertTagService: AlertTagService, private operatorService: OperatorService, - private elasticDataService: ElasticSearchIndexService) { + private elasticDataService: ElasticDataService) { this.fields = ALERT_FIELDS.filter(value => !this.excludeFields.includes(value.field)); this.operators = FILTER_OPERATORS.filter(value => !this.excludeOperators.includes(value.operator)); @@ -252,7 +266,6 @@ export class AlertRuleCreateComponent implements OnInit { }); } - isFalsePositive() { return this.selected.findIndex(value => value.tagName.includes('False positive')) !== -1; } @@ -265,13 +278,48 @@ export class AlertRuleCreateComponent implements OnInit { return this.operators; } - getAlert() { + onDataTypeChange(selectedDataTypes: DataType[]) { + this.ruleForm.get('dataTypes').patchValue(selectedDataTypes); + this.dataTypeService.resetTypes(); + this.daTypeRequest.page = -1; + this.loadDataTypes(); + } + + onSearch(event: { term: string; items: any[] }) { + this.alertRequest = { + ...this.alertRequest, + filters: [ + ...this.alertRequest.filters.filter(f => f.operator !== ElasticOperatorsEnum.IS_IN_FIELD), + {field: 'name', operator: ElasticOperatorsEnum.IS_IN_FIELD, value: event.term} + ] + }; + + this.getAlerts(); + } + + loadDataTypes() { + this.daTypeRequest.page = this.daTypeRequest.page + 1; + this.loadingDataTypes = true; + + this.dataTypeService.getAll(this.daTypeRequest) + .subscribe(data => { + this.loadingDataTypes = false; + }); + } + + + trackByFn(alert: any) { + return alert.id; + } + + getAlerts() { this.elasticDataService.search( - this.page, - this.itemsPerPage, + this.alertRequest.page, + this.alertRequest.size, 100000000, - this.dataNature, - sanitizeFilters(this.filters), this.sortBy).subscribe( + this.alertRequest.dataNature, + sanitizeFilters(this.alertRequest.filters), + this.alertRequest.sort).subscribe( (res: HttpResponse) => { this.alerts = res.body; this.loading = false; From 6479ea3b93bab7e5fdf5826a5749b9e4b1df885a Mon Sep 17 00:00:00 2001 From: Manuel Abascal Date: Mon, 7 Apr 2025 14:30:23 -0500 Subject: [PATCH 15/70] feat: enable create and update for incident response --- .../alert-rules/alert-rules.component.html | 4 +- .../alert-rules/alert-rules.component.ts | 21 ++- .../alert-tags-apply.component.ts | 1 + .../alert-complete.component.ts | 1 + .../alert-rule-create.component.html | 55 +++---- .../alert-rule-create.component.ts | 151 +++++++++++++----- .../shared/services/alert.service.ts | 39 +++++ 7 files changed, 192 insertions(+), 80 deletions(-) create mode 100644 frontend/src/app/incident-response/shared/services/alert.service.ts diff --git a/frontend/src/app/data-management/alert-management/alert-rules/alert-rules.component.html b/frontend/src/app/data-management/alert-management/alert-rules/alert-rules.component.html index 8f927abdf..1a038d97e 100644 --- a/frontend/src/app/data-management/alert-management/alert-rules/alert-rules.component.html +++ b/frontend/src/app/data-management/alert-management/alert-rules/alert-rules.component.html @@ -77,7 +77,9 @@
Alerts rules
{{rule.lastModifiedDate | date:'short' }} {{rule.createdBy }} - + + diff --git a/frontend/src/app/data-management/alert-management/alert-rules/alert-rules.component.ts b/frontend/src/app/data-management/alert-management/alert-rules/alert-rules.component.ts index 848205759..db456d788 100644 --- a/frontend/src/app/data-management/alert-management/alert-rules/alert-rules.component.ts +++ b/frontend/src/app/data-management/alert-management/alert-rules/alert-rules.component.ts @@ -12,8 +12,8 @@ import {TimeFilterType} from '../../../shared/types/time-filter.type'; import {AlertRulesService} from '../shared/services/alert-rules.service'; import {AlertTagService} from '../shared/services/alert-tag.service'; import {AlertRuleType} from './alert-rule.type'; -import {AlertRuleCreateComponent} from "../shared/components/alert-rule-create/alert-rule-create.component"; -import {FALSE_POSITIVE_OBJECT} from "../../../shared/constants/alert/alert-field.constant"; +import {AlertRuleCreateComponent} from '../shared/components/alert-rule-create/alert-rule-create.component'; +import {FALSE_POSITIVE_OBJECT} from '../../../shared/constants/alert/alert-field.constant'; @Component({ selector: 'app-rules', @@ -131,16 +131,23 @@ export class AlertRulesComponent implements OnInit { this.getRules(); } - createRule() { + createRule(rule?: AlertRuleType) { const modal = this.modalService.open(AlertRuleCreateComponent, {centered: true, size: 'lg'}); const falsePositive: AlertTags[] = [FALSE_POSITIVE_OBJECT]; - if (this.rule) { - modal.componentInstance.rule = this.rule; + if (rule) { + modal.componentInstance.rule = rule; } - modal.componentInstance.isForComplete = true; + modal.componentInstance.isForComplete = rule; + modal.componentInstance.action = rule ? 'update' : 'create'; modal.componentInstance.tags = falsePositive; modal.componentInstance.ruleAdd.subscribe(rule => { - this.rule = rule; + this.rule = null; + this.getRules(); + this.getTags(); }); } + + editRuleAction(rule: AlertRuleType) { + this.createRule(rule); + } } diff --git a/frontend/src/app/data-management/alert-management/shared/components/alert-actions/alert-apply-tags/alert-tags-apply.component.ts b/frontend/src/app/data-management/alert-management/shared/components/alert-actions/alert-apply-tags/alert-tags-apply.component.ts index f0b0cefa4..d427ea542 100644 --- a/frontend/src/app/data-management/alert-management/shared/components/alert-actions/alert-apply-tags/alert-tags-apply.component.ts +++ b/frontend/src/app/data-management/alert-management/shared/components/alert-actions/alert-apply-tags/alert-tags-apply.component.ts @@ -52,6 +52,7 @@ export class AlertTagsApplyComponent implements OnInit, OnChanges { addNewTagRule() { const modalRef = this.modalService.open(AlertRuleCreateComponent, {centered: true, size: 'lg'}); modalRef.componentInstance.alert = this.alert; + modalRef.componentInstance.action = 'select'; modalRef.componentInstance.ruleAdd.subscribe((created) => { this.icon = this.getTagIcon(); this.color = this.getColor(); diff --git a/frontend/src/app/data-management/alert-management/shared/components/alert-complete/alert-complete.component.ts b/frontend/src/app/data-management/alert-management/shared/components/alert-complete/alert-complete.component.ts index 0cc6d4792..e82d086da 100644 --- a/frontend/src/app/data-management/alert-management/shared/components/alert-complete/alert-complete.component.ts +++ b/frontend/src/app/data-management/alert-management/shared/components/alert-complete/alert-complete.component.ts @@ -67,6 +67,7 @@ export class AlertCompleteComponent implements OnInit { modal.componentInstance.rule = this.rule; } modal.componentInstance.alert = this.alert; + modal.componentInstance.action = 'select'; modal.componentInstance.isForComplete = true; modal.componentInstance.tags = falsePositive; modal.componentInstance.ruleAdd.subscribe(rule => { diff --git a/frontend/src/app/data-management/alert-management/shared/components/alert-rule-create/alert-rule-create.component.html b/frontend/src/app/data-management/alert-management/shared/components/alert-rule-create/alert-rule-create.component.html index 08936079d..71cc4e550 100644 --- a/frontend/src/app/data-management/alert-management/shared/components/alert-rule-create/alert-rule-create.component.html +++ b/frontend/src/app/data-management/alert-management/shared/components/alert-rule-create/alert-rule-create.component.html @@ -1,6 +1,6 @@ - +
-
+
-
@@ -30,6 +30,23 @@
+ + +
+ + +
+
+
@@ -56,7 +73,7 @@
+ ({{ 512 - formRule.get('description').value.length }})
-
-
-
+
+
By creating a False Positive rule, future alerts where the fields and values match the operator defined will be tagged as False positive. The alerts that match with this rule will be marked as Completed. +
-
-
+
View rule fields    -
-
-
- {{ getFieldName(filter.field) }}:  - - - -
-
- +
+
+
+ {{ getFieldName(condition.get('field').value) }}:  + + + + + + +
+
+ +
+
+
+
+
+ +
+ + +
+
+
diff --git a/frontend/src/app/data-management/alert-management/shared/components/alert-rule-create/alert-rule-create.component.ts b/frontend/src/app/data-management/alert-management/shared/components/alert-rule-create/alert-rule-create.component.ts index 35b2eff82..0a0832322 100644 --- a/frontend/src/app/data-management/alert-management/shared/components/alert-rule-create/alert-rule-create.component.ts +++ b/frontend/src/app/data-management/alert-management/shared/components/alert-rule-create/alert-rule-create.component.ts @@ -29,17 +29,18 @@ import { ALERT_STATUS_LABEL_FIELD, ALERT_TAGS_FIELD, ALERT_TIMESTAMP_FIELD, - EVENT_IS_ALERT, + EVENT_IS_ALERT, INCIDENT_AUTOMATION_ALERT_FIELDS, LOG_RELATED_ID_EVENT_FIELD } from '../../../../../shared/constants/alert/alert-field.constant'; import {CLOSED} from '../../../../../shared/constants/alert/alert-status.constant'; import {FILTER_OPERATORS} from '../../../../../shared/constants/filter-operators.const'; +import {ALERT_INDEX_PATTERN} from "../../../../../shared/constants/main-index-pattern.constant"; import {ElasticOperatorsEnum} from '../../../../../shared/enums/elastic-operators.enum'; +import {ElasticSearchIndexService} from "../../../../../shared/services/elasticsearch/elasticsearch-index.service"; import {AlertTags} from '../../../../../shared/types/alert/alert-tag.type'; import {UtmAlertType} from '../../../../../shared/types/alert/utm-alert.type'; import {ElasticFilterType} from '../../../../../shared/types/filter/elastic-filter.type'; import {OperatorsType} from '../../../../../shared/types/filter/operators.type'; -import {UtmFieldType} from '../../../../../shared/types/table/utm-field.type'; import {getValueFromPropertyPath} from '../../../../../shared/util/get-value-object-from-property-path.util'; import {InputClassResolve} from '../../../../../shared/util/input-class-resolve'; import {AlertRuleType} from '../../../alert-rules/alert-rule.type'; @@ -49,7 +50,8 @@ import {AlertManagementService} from '../../services/alert-management.service'; import {AlertRulesService} from '../../services/alert-rules.service'; import {AlertTagService} from '../../services/alert-tag.service'; import {setAlertPropertyValue} from '../../util/alert-util-function'; -import {ElasticSearchFieldInfoType} from "../../../../../shared/types/elasticsearch/elastic-search-field-info.type"; +import {sanitizeFilters} from "../../../../../shared/util/elastic-filter.util"; +import {HttpResponse} from "@angular/common/http"; @Component({ selector: 'app-alert-rule-create', @@ -100,6 +102,8 @@ export class AlertRuleCreateComponent implements OnInit { uuid = UUID.UUID(); tagging = false; ElasticOperatorsEnum = ElasticOperatorsEnum; + alerts = []; + loadingAlerts: boolean = false; constructor(public activeModal: NgbActiveModal, public inputClass: InputClassResolve, @@ -110,12 +114,17 @@ export class AlertRuleCreateComponent implements OnInit { private alertUpdateTagBehavior: AlertUpdateTagBehavior, private alertServiceManagement: AlertManagementService, private alertTagService: AlertTagService, - private operatorService: OperatorService) { + private operatorService: OperatorService, + private elasticDataService: ElasticSearchIndexService) { + this.fields = ALERT_FIELDS.filter(value => !this.excludeFields.includes(value.field)); this.operators = FILTER_OPERATORS.filter(value => !this.excludeOperators.includes(value.operator)); } ngOnInit() { + if ( !this.alert) { + this.getAlerts(); + } this.getTags(); this.initForm(); this.createDefaultFilters(); @@ -255,4 +264,22 @@ export class AlertRuleCreateComponent implements OnInit { } return this.operators; } + + getAlert() { + this.elasticDataService.search( + this.page, + this.itemsPerPage, + 100000000, + this.dataNature, + sanitizeFilters(this.filters), this.sortBy).subscribe( + (res: HttpResponse) => { + this.alerts = res.body; + this.loading = false; + this.refreshingAlert = false; + }, + (res: HttpResponse) => { + this.utmToastService.showError('Error', 'An error occurred while listing the alerts. Please try again later.'); + } + ); + } } From acdb0f5debe86ce5839bd6db74c2d2089b79d311 Mon Sep 17 00:00:00 2001 From: Manuel Abascal Date: Sat, 5 Apr 2025 10:59:00 -0500 Subject: [PATCH 53/70] feat: add tag rule --- .../alert-rule-create.component.html | 27 ++++---- .../alert-rule-create.component.ts | 64 ++++++++++++++++--- 2 files changed, 70 insertions(+), 21 deletions(-) diff --git a/frontend/src/app/data-management/alert-management/shared/components/alert-rule-create/alert-rule-create.component.html b/frontend/src/app/data-management/alert-management/shared/components/alert-rule-create/alert-rule-create.component.html index 134b949fc..416b7eae7 100644 --- a/frontend/src/app/data-management/alert-management/shared/components/alert-rule-create/alert-rule-create.component.html +++ b/frontend/src/app/data-management/alert-management/shared/components/alert-rule-create/alert-rule-create.component.html @@ -94,19 +94,20 @@
- +
diff --git a/frontend/src/app/data-management/alert-management/shared/components/alert-rule-create/alert-rule-create.component.ts b/frontend/src/app/data-management/alert-management/shared/components/alert-rule-create/alert-rule-create.component.ts index 0a0832322..14a457b0c 100644 --- a/frontend/src/app/data-management/alert-management/shared/components/alert-rule-create/alert-rule-create.component.ts +++ b/frontend/src/app/data-management/alert-management/shared/components/alert-rule-create/alert-rule-create.component.ts @@ -52,6 +52,7 @@ import {AlertTagService} from '../../services/alert-tag.service'; import {setAlertPropertyValue} from '../../util/alert-util-function'; import {sanitizeFilters} from "../../../../../shared/util/elastic-filter.util"; import {HttpResponse} from "@angular/common/http"; +import {ElasticDataService} from "../../../../../shared/services/elasticsearch/elastic-data.service"; @Component({ selector: 'app-alert-rule-create', @@ -103,7 +104,20 @@ export class AlertRuleCreateComponent implements OnInit { tagging = false; ElasticOperatorsEnum = ElasticOperatorsEnum; alerts = []; - loadingAlerts: boolean = false; + alertRequest = { + page: 0, + size: 100, + sort: '@timestamp,desc', + index: ALERT_INDEX_PATTERN, + filters: [ + {field: 'status', operator: 'IS_NOT', value: 1}, + {field: 'tags', operator: 'IS_NOT', value: 'False positive'}, + {field: '@timestamp', operator: 'IS_BETWEEN', value: ['now-30d', 'now']} + ], + dataNature: null, + }; + loading = false; + refreshingAlert = false; constructor(public activeModal: NgbActiveModal, public inputClass: InputClassResolve, @@ -115,7 +129,7 @@ export class AlertRuleCreateComponent implements OnInit { private alertServiceManagement: AlertManagementService, private alertTagService: AlertTagService, private operatorService: OperatorService, - private elasticDataService: ElasticSearchIndexService) { + private elasticDataService: ElasticDataService) { this.fields = ALERT_FIELDS.filter(value => !this.excludeFields.includes(value.field)); this.operators = FILTER_OPERATORS.filter(value => !this.excludeOperators.includes(value.operator)); @@ -252,7 +266,6 @@ export class AlertRuleCreateComponent implements OnInit { }); } - isFalsePositive() { return this.selected.findIndex(value => value.tagName.includes('False positive')) !== -1; } @@ -265,13 +278,48 @@ export class AlertRuleCreateComponent implements OnInit { return this.operators; } - getAlert() { + onDataTypeChange(selectedDataTypes: DataType[]) { + this.ruleForm.get('dataTypes').patchValue(selectedDataTypes); + this.dataTypeService.resetTypes(); + this.daTypeRequest.page = -1; + this.loadDataTypes(); + } + + onSearch(event: { term: string; items: any[] }) { + this.alertRequest = { + ...this.alertRequest, + filters: [ + ...this.alertRequest.filters.filter(f => f.operator !== ElasticOperatorsEnum.IS_IN_FIELD), + {field: 'name', operator: ElasticOperatorsEnum.IS_IN_FIELD, value: event.term} + ] + }; + + this.getAlerts(); + } + + loadDataTypes() { + this.daTypeRequest.page = this.daTypeRequest.page + 1; + this.loadingDataTypes = true; + + this.dataTypeService.getAll(this.daTypeRequest) + .subscribe(data => { + this.loadingDataTypes = false; + }); + } + + + trackByFn(alert: any) { + return alert.id; + } + + getAlerts() { this.elasticDataService.search( - this.page, - this.itemsPerPage, + this.alertRequest.page, + this.alertRequest.size, 100000000, - this.dataNature, - sanitizeFilters(this.filters), this.sortBy).subscribe( + this.alertRequest.dataNature, + sanitizeFilters(this.alertRequest.filters), + this.alertRequest.sort).subscribe( (res: HttpResponse) => { this.alerts = res.body; this.loading = false; From e74fed16c07a4ceb4a298d46b443bd350235bf6a Mon Sep 17 00:00:00 2001 From: Manuel Abascal Date: Mon, 7 Apr 2025 14:30:23 -0500 Subject: [PATCH 54/70] feat: enable create and update for incident response --- .../alert-rule-create.component.html | 21 --- .../alert-rule-create.component.ts | 151 +++++++++++++----- 2 files changed, 108 insertions(+), 64 deletions(-) diff --git a/frontend/src/app/data-management/alert-management/shared/components/alert-rule-create/alert-rule-create.component.html b/frontend/src/app/data-management/alert-management/shared/components/alert-rule-create/alert-rule-create.component.html index 416b7eae7..71cc4e550 100644 --- a/frontend/src/app/data-management/alert-management/shared/components/alert-rule-create/alert-rule-create.component.html +++ b/frontend/src/app/data-management/alert-management/shared/components/alert-rule-create/alert-rule-create.component.html @@ -91,27 +91,6 @@
-
- -
- - -
-
-
diff --git a/frontend/src/app/data-management/alert-management/shared/components/alert-rule-create/alert-rule-create.component.ts b/frontend/src/app/data-management/alert-management/shared/components/alert-rule-create/alert-rule-create.component.ts index 14a457b0c..79931f59e 100644 --- a/frontend/src/app/data-management/alert-management/shared/components/alert-rule-create/alert-rule-create.component.ts +++ b/frontend/src/app/data-management/alert-management/shared/components/alert-rule-create/alert-rule-create.component.ts @@ -1,8 +1,11 @@ -import {Component, EventEmitter, Input, OnInit, Output} from '@angular/core'; +import {HttpResponse} from '@angular/common/http'; +import {Component, EventEmitter, Input, OnDestroy, OnInit, Output} from '@angular/core'; import {FormBuilder, FormGroup, Validators} from '@angular/forms'; import {NgbActiveModal, NgbModal} from '@ng-bootstrap/ng-bootstrap'; import {UUID} from 'angular2-uuid'; -import {debounceTime} from 'rxjs/operators'; +import {Observable, Subject} from 'rxjs'; +import {concatMap, debounceTime, filter, takeUntil, tap} from 'rxjs/operators'; +import {AlertService} from '../../../../../incident-response/shared/services/alert.service'; import {UtmToastService} from '../../../../../shared/alert/utm-toast.service'; import { OperatorService @@ -29,18 +32,18 @@ import { ALERT_STATUS_LABEL_FIELD, ALERT_TAGS_FIELD, ALERT_TIMESTAMP_FIELD, - EVENT_IS_ALERT, INCIDENT_AUTOMATION_ALERT_FIELDS, - LOG_RELATED_ID_EVENT_FIELD + EVENT_IS_ALERT, FALSE_POSITIVE_OBJECT, LOG_RELATED_ID_EVENT_FIELD } from '../../../../../shared/constants/alert/alert-field.constant'; -import {CLOSED} from '../../../../../shared/constants/alert/alert-status.constant'; +import {AUTOMATIC_REVIEW, CLOSED} from '../../../../../shared/constants/alert/alert-status.constant'; import {FILTER_OPERATORS} from '../../../../../shared/constants/filter-operators.const'; -import {ALERT_INDEX_PATTERN} from "../../../../../shared/constants/main-index-pattern.constant"; +import {ALERT_INDEX_PATTERN} from '../../../../../shared/constants/main-index-pattern.constant'; import {ElasticOperatorsEnum} from '../../../../../shared/enums/elastic-operators.enum'; -import {ElasticSearchIndexService} from "../../../../../shared/services/elasticsearch/elasticsearch-index.service"; +import {ElasticDataService} from '../../../../../shared/services/elasticsearch/elastic-data.service'; import {AlertTags} from '../../../../../shared/types/alert/alert-tag.type'; import {UtmAlertType} from '../../../../../shared/types/alert/utm-alert.type'; import {ElasticFilterType} from '../../../../../shared/types/filter/elastic-filter.type'; import {OperatorsType} from '../../../../../shared/types/filter/operators.type'; +import {sanitizeFilters} from '../../../../../shared/util/elastic-filter.util'; import {getValueFromPropertyPath} from '../../../../../shared/util/get-value-object-from-property-path.util'; import {InputClassResolve} from '../../../../../shared/util/input-class-resolve'; import {AlertRuleType} from '../../../alert-rules/alert-rule.type'; @@ -50,18 +53,17 @@ import {AlertManagementService} from '../../services/alert-management.service'; import {AlertRulesService} from '../../services/alert-rules.service'; import {AlertTagService} from '../../services/alert-tag.service'; import {setAlertPropertyValue} from '../../util/alert-util-function'; -import {sanitizeFilters} from "../../../../../shared/util/elastic-filter.util"; -import {HttpResponse} from "@angular/common/http"; -import {ElasticDataService} from "../../../../../shared/services/elasticsearch/elastic-data.service"; @Component({ selector: 'app-alert-rule-create', templateUrl: './alert-rule-create.component.html', styleUrls: ['./alert-rule-create.component.scss'] }) -export class AlertRuleCreateComponent implements OnInit { +export class AlertRuleCreateComponent implements OnInit, OnDestroy { @Input() alert: UtmAlertType; @Input() isForComplete = false; + @Input() action: 'create' | 'update' | 'select' = 'create'; + @Input() rule: AlertRuleType; @Output() ruleAdd = new EventEmitter(); tags: AlertTags[]; selected: AlertTags[] = []; @@ -106,18 +108,19 @@ export class AlertRuleCreateComponent implements OnInit { alerts = []; alertRequest = { page: 0, - size: 100, + size: 10, sort: '@timestamp,desc', - index: ALERT_INDEX_PATTERN, filters: [ - {field: 'status', operator: 'IS_NOT', value: 1}, - {field: 'tags', operator: 'IS_NOT', value: 'False positive'}, + {field: ALERT_STATUS_FIELD_AUTO, operator: ElasticOperatorsEnum.IS_NOT, value: AUTOMATIC_REVIEW}, + {field: ALERT_TAGS_FIELD, operator: ElasticOperatorsEnum.IS_NOT, value: FALSE_POSITIVE_OBJECT.tagName}, {field: '@timestamp', operator: 'IS_BETWEEN', value: ['now-30d', 'now']} ], - dataNature: null, + dataNature: ALERT_INDEX_PATTERN, }; loading = false; refreshingAlert = false; + alerts$: Observable; + destroy$ = new Subject(); constructor(public activeModal: NgbActiveModal, public inputClass: InputClassResolve, @@ -129,31 +132,49 @@ export class AlertRuleCreateComponent implements OnInit { private alertServiceManagement: AlertManagementService, private alertTagService: AlertTagService, private operatorService: OperatorService, - private elasticDataService: ElasticDataService) { + private elasticDataService: ElasticDataService, + private alertService: AlertService) { this.fields = ALERT_FIELDS.filter(value => !this.excludeFields.includes(value.field)); this.operators = FILTER_OPERATORS.filter(value => !this.excludeOperators.includes(value.operator)); } ngOnInit() { - if ( !this.alert) { - this.getAlerts(); - } - this.getTags(); + this.initForm(); - this.createDefaultFilters(); + this.getTags(); this.formRule.get('name').valueChanges.pipe(debounceTime(3000)).subscribe(ruleName => { this.searchRule(ruleName); }); + + if (!this.alert) { + this.loading = true; + this.alertService.notifyRefresh(true); + } else { + this.createDefaultFilters(); + } + + if (this.rule) { + this.filters = [... this.rule.conditions]; + this.selected = this.rule.tags.length > 0 ? [...this.rule.tags] : []; + } + + this.alerts$ = this.alertService.onRefresh$ + .pipe( + takeUntil(this.destroy$), + filter(loading => loading), + concatMap(() => this.alertService.fetchData(this.alertRequest))) + .pipe( + tap((res) => this.loading = !this.loading)); } initForm() { this.formRule = this.fb.group({ - id: [], - name: ['', Validators.required], - description: ['', Validators.required], - conditions: [[], Validators.required], - tags: [null, Validators.required], + id: [this.rule ? this.rule.id : null], + name: [ this.rule ? this.rule.name : '', Validators.required], + description: [this.rule ? this.rule.description : '', Validators.required], + conditions: [ this.rule ? this.rule.conditions : [], Validators.required], + tags: [this.rule ? this.rule.tags : null, Validators.required], }); } @@ -174,6 +195,41 @@ export class AlertRuleCreateComponent implements OnInit { return this.fields.filter(value => value.field === field)[0].label; } + saveRule() { + const request$ = this.action === 'update' + ? this.alertRulesService.update(this.formRule.value) + : this.alertRulesService.create(this.formRule.value); + + const tags = this.selected.map(t => t.tagName); + + request$.subscribe(() => { + const action = this.action === 'update' ? 'updated' : 'created'; + this.utmToastService.showSuccessBottom(`Rule ${this.formRule.get('name').value} ${action} successfully`); + + if (this.alert) { + const alertId = this.alert.id; + this.alertServiceManagement.updateAlertTags([alertId], tags, true).subscribe(() => { + this.alertUpdateTagBehavior.$tagRefresh.next(true); + this.utmToastService.showSuccessBottom('Tags updated successfully'); + this.tagging = false; + + this.alert = setAlertPropertyValue(ALERT_TAGS_FIELD, tags, this.alert); + + if (this.isFalsePositive()) { + const observation = `Tag rule ${this.formRule.get('name').value} applied`; + this.alertServiceManagement.updateAlertStatus([alertId], CLOSED, observation).subscribe(() => { + this.finalizeRule(); + }); + } else { + this.finalizeRule(); + } + }); + } else { + this.finalizeRule(); + } + }); + } + createRule() { if (!this.isForComplete) { this.alertRulesService.create(this.formRule.value).subscribe(response => { @@ -243,12 +299,12 @@ export class AlertRuleCreateComponent implements OnInit { return this.selected.findIndex(value => value.id === tag.id) !== -1; } - selectValue(tag: AlertTags) { + selectValue( tag: AlertTags) { const index = this.selected.findIndex(value => value.id === tag.id); if (index === -1) { this.selected.push(tag); } else { - this.selected.splice(index, 1); + this.selected = this.selected.filter(value => value.id !== tag.id); } this.formRule.get('tags').setValue(this.selected); } @@ -278,13 +334,6 @@ export class AlertRuleCreateComponent implements OnInit { return this.operators; } - onDataTypeChange(selectedDataTypes: DataType[]) { - this.ruleForm.get('dataTypes').patchValue(selectedDataTypes); - this.dataTypeService.resetTypes(); - this.daTypeRequest.page = -1; - this.loadDataTypes(); - } - onSearch(event: { term: string; items: any[] }) { this.alertRequest = { ...this.alertRequest, @@ -297,14 +346,20 @@ export class AlertRuleCreateComponent implements OnInit { this.getAlerts(); } - loadDataTypes() { - this.daTypeRequest.page = this.daTypeRequest.page + 1; - this.loadingDataTypes = true; + onAlertChange(alert: any){ + this.alert = alert; + this.filters = []; + this.formRule.get('conditions').reset(); + this.createDefaultFilters(); + } - this.dataTypeService.getAll(this.daTypeRequest) - .subscribe(data => { - this.loadingDataTypes = false; - }); + loadMoreAlerts() { + this.alertRequest = { + ...this.alertRequest, + size: this.alertRequest.size + 5 + }; + this.loading = true; + this.alertService.notifyRefresh(true); } @@ -330,4 +385,14 @@ export class AlertRuleCreateComponent implements OnInit { } ); } + + private finalizeRule(): void { + this.ruleAdd.emit(this.formRule.value); + this.activeModal.close(); + } + + ngOnDestroy(): void { + this.destroy$.next(); + this.destroy$.complete(); + } } From a1e13c00f05796ea12aa9e62156d34acbf216988 Mon Sep 17 00:00:00 2001 From: Manuel Abascal Date: Tue, 8 Apr 2025 11:45:04 -0500 Subject: [PATCH 55/70] chore: update changelog --- CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 351842a2c..d699a9c35 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,4 +3,5 @@ ### Bug Fixes -- Improved exception handling in `automaticReview` to prevent the process from stopping due to errors, ensuring the system continues evaluating alerts even if a specific rule fails. --- Improved operator selection for more accurate and consistent filtering. \ No newline at end of file +-- Improved operator selection for more accurate and consistent filtering. +-- Introduced new compliance reports aligned with the PCI DSS standard to expand auditing capabilities. \ No newline at end of file From c4820f0e1a6c31da8b1e687fdb4bae6ba164e4ae Mon Sep 17 00:00:00 2001 From: Manuel Abascal Date: Mon, 7 Apr 2025 17:29:01 -0500 Subject: [PATCH 56/70] feat: add new compliance reports --- .../compliance/config/UtmComplianceReportConfigService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/src/main/java/com/park/utmstack/service/compliance/config/UtmComplianceReportConfigService.java b/backend/src/main/java/com/park/utmstack/service/compliance/config/UtmComplianceReportConfigService.java index 0eba1978a..a95f33247 100644 --- a/backend/src/main/java/com/park/utmstack/service/compliance/config/UtmComplianceReportConfigService.java +++ b/backend/src/main/java/com/park/utmstack/service/compliance/config/UtmComplianceReportConfigService.java @@ -125,7 +125,7 @@ public Page getReportsByFilters(Long standardId, Stri .filter(cp -> !cp.getDashboard().isEmpty() && cp.getDashboard().stream().allMatch(v -> v.getVisualization().getPattern().getActive())) .collect(Collectors.toList()); - return new PageImpl<>(activeCompliance, pageable, activeCompliance.size()); + return new PageImpl<>(activeCompliance, pageable, page.getTotalElements()); } From e9b81e122715f0b129a75fdcf1e8da92065b4b05 Mon Sep 17 00:00:00 2001 From: Manuel Abascal Date: Tue, 8 Apr 2025 09:21:47 -0500 Subject: [PATCH 57/70] feat: add new compliance reports --- .../config/UtmComplianceReportConfigService.java | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/backend/src/main/java/com/park/utmstack/service/compliance/config/UtmComplianceReportConfigService.java b/backend/src/main/java/com/park/utmstack/service/compliance/config/UtmComplianceReportConfigService.java index a95f33247..1b50d0542 100644 --- a/backend/src/main/java/com/park/utmstack/service/compliance/config/UtmComplianceReportConfigService.java +++ b/backend/src/main/java/com/park/utmstack/service/compliance/config/UtmComplianceReportConfigService.java @@ -120,12 +120,7 @@ public Page getReportsByFilters(Long standardId, Stri } } - List activeCompliance = page.getContent() - .stream() - .filter(cp -> !cp.getDashboard().isEmpty() && cp.getDashboard().stream().allMatch(v -> v.getVisualization().getPattern().getActive())) - .collect(Collectors.toList()); - - return new PageImpl<>(activeCompliance, pageable, page.getTotalElements()); + return page; } From 05502c9dfcc1f10d356f683d1b61d6d55c428c4f Mon Sep 17 00:00:00 2001 From: Manuel Abascal Date: Mon, 31 Mar 2025 10:05:59 -0500 Subject: [PATCH 58/70] feat: filter compliance reports based on active integration --- .../config/UtmComplianceReportConfigService.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/backend/src/main/java/com/park/utmstack/service/compliance/config/UtmComplianceReportConfigService.java b/backend/src/main/java/com/park/utmstack/service/compliance/config/UtmComplianceReportConfigService.java index 1b50d0542..0eba1978a 100644 --- a/backend/src/main/java/com/park/utmstack/service/compliance/config/UtmComplianceReportConfigService.java +++ b/backend/src/main/java/com/park/utmstack/service/compliance/config/UtmComplianceReportConfigService.java @@ -120,7 +120,12 @@ public Page getReportsByFilters(Long standardId, Stri } } - return page; + List activeCompliance = page.getContent() + .stream() + .filter(cp -> !cp.getDashboard().isEmpty() && cp.getDashboard().stream().allMatch(v -> v.getVisualization().getPattern().getActive())) + .collect(Collectors.toList()); + + return new PageImpl<>(activeCompliance, pageable, activeCompliance.size()); } From 0067d9c02c6ccb487ab1cdc908d94f2f48bdb251 Mon Sep 17 00:00:00 2001 From: Manuel Abascal Date: Fri, 4 Apr 2025 18:48:33 -0500 Subject: [PATCH 59/70] feat: allow edit and delete for non-owners only in dev mode --- .../utm-cp-reports/utm-cp-reports.component.ts | 6 ++++++ .../utm-cp-standard-section.component.ts | 6 ++++++ .../utm-cp-standard/utm-cp-standard.component.ts | 6 ++++++ .../dashboard-list/dashboard-list.component.ts | 6 ++++++ .../visualization-list/visualization-list.component.ts | 6 ++++++ 5 files changed, 30 insertions(+) diff --git a/frontend/src/app/compliance/compliance-management/utm-cp-reports/utm-cp-reports.component.ts b/frontend/src/app/compliance/compliance-management/utm-cp-reports/utm-cp-reports.component.ts index d8dfbb28d..ca37c645f 100644 --- a/frontend/src/app/compliance/compliance-management/utm-cp-reports/utm-cp-reports.component.ts +++ b/frontend/src/app/compliance/compliance-management/utm-cp-reports/utm-cp-reports.component.ts @@ -7,6 +7,7 @@ import {CpReportsService} from '../../shared/services/cp-reports.service'; import {ComplianceReportType} from '../../shared/type/compliance-report.type'; import {ComplianceStandardSectionType} from '../../shared/type/compliance-standard-section.type'; import {UtmCpReportDeleteComponent} from './utm-cp-report-delete/utm-cp-report-delete.component'; +import {EnvironmentService} from "../../../shared/services/util/enviroment.service"; @Component({ selector: 'app-utm-cp-reports', @@ -28,6 +29,7 @@ export class UtmCpReportsComponent implements OnInit { constructor(private cpReportsService: CpReportsService, public cpStandardSectionBehavior: CpStandardSectionBehavior, private cpReportBehavior: CpReportBehavior, + private environment: EnvironmentService, private modalService: NgbModal) { } @@ -51,6 +53,10 @@ export class UtmCpReportsComponent implements OnInit { } + isDev(){ + return this.environment.isDev(); + } + getReports() { const query = { page: this.page - 1, diff --git a/frontend/src/app/compliance/compliance-management/utm-cp-standard-section/utm-cp-standard-section.component.ts b/frontend/src/app/compliance/compliance-management/utm-cp-standard-section/utm-cp-standard-section.component.ts index 56dc35891..ad827a810 100644 --- a/frontend/src/app/compliance/compliance-management/utm-cp-standard-section/utm-cp-standard-section.component.ts +++ b/frontend/src/app/compliance/compliance-management/utm-cp-standard-section/utm-cp-standard-section.component.ts @@ -8,6 +8,7 @@ import {CpStandardSectionService} from '../../shared/services/cp-standard-sectio import {ComplianceStandardSectionType} from '../../shared/type/compliance-standard-section.type'; import {ComplianceStandardType} from '../../shared/type/compliance-standard.type'; import {UtmCpStandardSectionDeleteComponent} from './utm-cp-standard-section-delete/utm-cp-standard-section-delete.component'; +import {EnvironmentService} from '../../../shared/services/util/enviroment.service'; @Component({ selector: 'app-utm-cp-standard-section', @@ -28,6 +29,7 @@ export class UtmCpStandardSectionComponent implements OnInit { constructor(private cpStandardSectionService: CpStandardSectionService, private cpStandardBehavior: CpStandardBehavior, public cpStandardSectionBehavior: CpStandardSectionBehavior, + private environment: EnvironmentService, private modalService: NgbModal) { } @@ -50,6 +52,10 @@ export class UtmCpStandardSectionComponent implements OnInit { }); } + isDev(){ + return this.environment.isDev(); + } + getSections() { const query = { page: this.page - 1, diff --git a/frontend/src/app/compliance/compliance-management/utm-cp-standard/utm-cp-standard.component.ts b/frontend/src/app/compliance/compliance-management/utm-cp-standard/utm-cp-standard.component.ts index 840534bf3..3ad654104 100644 --- a/frontend/src/app/compliance/compliance-management/utm-cp-standard/utm-cp-standard.component.ts +++ b/frontend/src/app/compliance/compliance-management/utm-cp-standard/utm-cp-standard.component.ts @@ -7,6 +7,7 @@ import {CpStandardService} from '../../shared/services/cp-standard.service'; import {ComplianceStandardType} from '../../shared/type/compliance-standard.type'; import {UtmCpExportComponent} from '../utm-cp-export/utm-cp-export.component'; import {UtmCpStandardDeleteComponent} from './utm-cp-standard-delete/utm-cp-standard-delete.component'; +import {EnvironmentService} from "../../../shared/services/util/enviroment.service"; @Component({ selector: 'app-utm-cp-standard', @@ -23,6 +24,7 @@ export class UtmCpStandardComponent implements OnInit { constructor(private cpStandardService: CpStandardService, private modalService: NgbModal, + private environment: EnvironmentService, private cpStandardBehavior: CpStandardBehavior) { } @@ -95,6 +97,10 @@ export class UtmCpStandardComponent implements OnInit { private onError(body: any) { } + isDev(){ + return this.environment.isDev(); + } + exportStandard(st: ComplianceStandardType) { const modal = this.modalService.open(UtmCpExportComponent, {centered: true}); modal.componentInstance.standardId = st.id; diff --git a/frontend/src/app/graphic-builder/dashboard-builder/dashboard-list/dashboard-list.component.ts b/frontend/src/app/graphic-builder/dashboard-builder/dashboard-list/dashboard-list.component.ts index 22fdcef65..bc21c3858 100644 --- a/frontend/src/app/graphic-builder/dashboard-builder/dashboard-list/dashboard-list.component.ts +++ b/frontend/src/app/graphic-builder/dashboard-builder/dashboard-list/dashboard-list.component.ts @@ -17,6 +17,7 @@ import {DashboardImportComponent} from '../dashboard-import/dashboard-import.com import {UtmDashboardVisualizationService} from '../shared/services/utm-dashboard-visualization.service'; import {UtmDashboardService} from '../shared/services/utm-dashboard.service'; import {buildDashboardUrl} from '../shared/util/get-menu-url'; +import {EnvironmentService} from "../../../shared/services/util/enviroment.service"; @Component({ selector: 'app-dashboard-list', @@ -51,6 +52,7 @@ export class DashboardListComponent implements OnInit { private dashboardService: UtmDashboardService, private utmToastService: UtmToastService, private spinner: NgxSpinnerService, + private environment: EnvironmentService, private dashboardVisualizationService: UtmDashboardVisualizationService, private router: Router) { } @@ -64,6 +66,10 @@ export class DashboardListComponent implements OnInit { this.getDashboardList(); } + isDev(){ + return this.environment.isDev(); + } + onSortBy($event) { } diff --git a/frontend/src/app/graphic-builder/visualization/visualization-list/visualization-list.component.ts b/frontend/src/app/graphic-builder/visualization/visualization-list/visualization-list.component.ts index bd0cd015a..a606fc5ab 100644 --- a/frontend/src/app/graphic-builder/visualization/visualization-list/visualization-list.component.ts +++ b/frontend/src/app/graphic-builder/visualization/visualization-list/visualization-list.component.ts @@ -18,6 +18,7 @@ import {VisualizationService} from '../shared/services/visualization.service'; import {VisualizationCreateComponent} from '../visualization-create/visualization-create.component'; import {VisualizationDeleteComponent} from '../visualization-delete/visualization-delete.component'; import {VisualizationImportComponent} from '../visualization-import/visualization-import.component'; +import {EnvironmentService} from "../../../shared/services/util/enviroment.service"; @Component({ selector: 'app-visualization-list', @@ -53,6 +54,7 @@ export class VisualizationListComponent implements OnInit { private visualizationService: VisualizationService, private spinner: NgxSpinnerService, private router: Router, + private environment: EnvironmentService, private activatedRoute: ActivatedRoute) { } @@ -71,6 +73,10 @@ export class VisualizationListComponent implements OnInit { }); } + isDev(){ + return this.environment.isDev(); + } + editVisualization(vis: VisualizationType) { this.spinner.show('loadingSpinner'); const queryParams = {}; From 9b26eb7e9fd3a4b32458e031dcf0dc1fcfb9c102 Mon Sep 17 00:00:00 2001 From: Manuel Abascal Date: Fri, 4 Apr 2025 19:18:18 -0500 Subject: [PATCH 60/70] feat: allow edit and delete for non-owners only in dev mode --- .../utm-cp-reports/utm-cp-reports.component.ts | 6 ------ .../utm-cp-standard-section.component.ts | 6 ------ .../utm-cp-standard/utm-cp-standard.component.ts | 6 ------ .../dashboard-list/dashboard-list.component.ts | 6 ------ .../visualization-list/visualization-list.component.ts | 6 ------ 5 files changed, 30 deletions(-) diff --git a/frontend/src/app/compliance/compliance-management/utm-cp-reports/utm-cp-reports.component.ts b/frontend/src/app/compliance/compliance-management/utm-cp-reports/utm-cp-reports.component.ts index ca37c645f..d8dfbb28d 100644 --- a/frontend/src/app/compliance/compliance-management/utm-cp-reports/utm-cp-reports.component.ts +++ b/frontend/src/app/compliance/compliance-management/utm-cp-reports/utm-cp-reports.component.ts @@ -7,7 +7,6 @@ import {CpReportsService} from '../../shared/services/cp-reports.service'; import {ComplianceReportType} from '../../shared/type/compliance-report.type'; import {ComplianceStandardSectionType} from '../../shared/type/compliance-standard-section.type'; import {UtmCpReportDeleteComponent} from './utm-cp-report-delete/utm-cp-report-delete.component'; -import {EnvironmentService} from "../../../shared/services/util/enviroment.service"; @Component({ selector: 'app-utm-cp-reports', @@ -29,7 +28,6 @@ export class UtmCpReportsComponent implements OnInit { constructor(private cpReportsService: CpReportsService, public cpStandardSectionBehavior: CpStandardSectionBehavior, private cpReportBehavior: CpReportBehavior, - private environment: EnvironmentService, private modalService: NgbModal) { } @@ -53,10 +51,6 @@ export class UtmCpReportsComponent implements OnInit { } - isDev(){ - return this.environment.isDev(); - } - getReports() { const query = { page: this.page - 1, diff --git a/frontend/src/app/compliance/compliance-management/utm-cp-standard-section/utm-cp-standard-section.component.ts b/frontend/src/app/compliance/compliance-management/utm-cp-standard-section/utm-cp-standard-section.component.ts index ad827a810..56dc35891 100644 --- a/frontend/src/app/compliance/compliance-management/utm-cp-standard-section/utm-cp-standard-section.component.ts +++ b/frontend/src/app/compliance/compliance-management/utm-cp-standard-section/utm-cp-standard-section.component.ts @@ -8,7 +8,6 @@ import {CpStandardSectionService} from '../../shared/services/cp-standard-sectio import {ComplianceStandardSectionType} from '../../shared/type/compliance-standard-section.type'; import {ComplianceStandardType} from '../../shared/type/compliance-standard.type'; import {UtmCpStandardSectionDeleteComponent} from './utm-cp-standard-section-delete/utm-cp-standard-section-delete.component'; -import {EnvironmentService} from '../../../shared/services/util/enviroment.service'; @Component({ selector: 'app-utm-cp-standard-section', @@ -29,7 +28,6 @@ export class UtmCpStandardSectionComponent implements OnInit { constructor(private cpStandardSectionService: CpStandardSectionService, private cpStandardBehavior: CpStandardBehavior, public cpStandardSectionBehavior: CpStandardSectionBehavior, - private environment: EnvironmentService, private modalService: NgbModal) { } @@ -52,10 +50,6 @@ export class UtmCpStandardSectionComponent implements OnInit { }); } - isDev(){ - return this.environment.isDev(); - } - getSections() { const query = { page: this.page - 1, diff --git a/frontend/src/app/compliance/compliance-management/utm-cp-standard/utm-cp-standard.component.ts b/frontend/src/app/compliance/compliance-management/utm-cp-standard/utm-cp-standard.component.ts index 3ad654104..840534bf3 100644 --- a/frontend/src/app/compliance/compliance-management/utm-cp-standard/utm-cp-standard.component.ts +++ b/frontend/src/app/compliance/compliance-management/utm-cp-standard/utm-cp-standard.component.ts @@ -7,7 +7,6 @@ import {CpStandardService} from '../../shared/services/cp-standard.service'; import {ComplianceStandardType} from '../../shared/type/compliance-standard.type'; import {UtmCpExportComponent} from '../utm-cp-export/utm-cp-export.component'; import {UtmCpStandardDeleteComponent} from './utm-cp-standard-delete/utm-cp-standard-delete.component'; -import {EnvironmentService} from "../../../shared/services/util/enviroment.service"; @Component({ selector: 'app-utm-cp-standard', @@ -24,7 +23,6 @@ export class UtmCpStandardComponent implements OnInit { constructor(private cpStandardService: CpStandardService, private modalService: NgbModal, - private environment: EnvironmentService, private cpStandardBehavior: CpStandardBehavior) { } @@ -97,10 +95,6 @@ export class UtmCpStandardComponent implements OnInit { private onError(body: any) { } - isDev(){ - return this.environment.isDev(); - } - exportStandard(st: ComplianceStandardType) { const modal = this.modalService.open(UtmCpExportComponent, {centered: true}); modal.componentInstance.standardId = st.id; diff --git a/frontend/src/app/graphic-builder/dashboard-builder/dashboard-list/dashboard-list.component.ts b/frontend/src/app/graphic-builder/dashboard-builder/dashboard-list/dashboard-list.component.ts index bc21c3858..22fdcef65 100644 --- a/frontend/src/app/graphic-builder/dashboard-builder/dashboard-list/dashboard-list.component.ts +++ b/frontend/src/app/graphic-builder/dashboard-builder/dashboard-list/dashboard-list.component.ts @@ -17,7 +17,6 @@ import {DashboardImportComponent} from '../dashboard-import/dashboard-import.com import {UtmDashboardVisualizationService} from '../shared/services/utm-dashboard-visualization.service'; import {UtmDashboardService} from '../shared/services/utm-dashboard.service'; import {buildDashboardUrl} from '../shared/util/get-menu-url'; -import {EnvironmentService} from "../../../shared/services/util/enviroment.service"; @Component({ selector: 'app-dashboard-list', @@ -52,7 +51,6 @@ export class DashboardListComponent implements OnInit { private dashboardService: UtmDashboardService, private utmToastService: UtmToastService, private spinner: NgxSpinnerService, - private environment: EnvironmentService, private dashboardVisualizationService: UtmDashboardVisualizationService, private router: Router) { } @@ -66,10 +64,6 @@ export class DashboardListComponent implements OnInit { this.getDashboardList(); } - isDev(){ - return this.environment.isDev(); - } - onSortBy($event) { } diff --git a/frontend/src/app/graphic-builder/visualization/visualization-list/visualization-list.component.ts b/frontend/src/app/graphic-builder/visualization/visualization-list/visualization-list.component.ts index a606fc5ab..bd0cd015a 100644 --- a/frontend/src/app/graphic-builder/visualization/visualization-list/visualization-list.component.ts +++ b/frontend/src/app/graphic-builder/visualization/visualization-list/visualization-list.component.ts @@ -18,7 +18,6 @@ import {VisualizationService} from '../shared/services/visualization.service'; import {VisualizationCreateComponent} from '../visualization-create/visualization-create.component'; import {VisualizationDeleteComponent} from '../visualization-delete/visualization-delete.component'; import {VisualizationImportComponent} from '../visualization-import/visualization-import.component'; -import {EnvironmentService} from "../../../shared/services/util/enviroment.service"; @Component({ selector: 'app-visualization-list', @@ -54,7 +53,6 @@ export class VisualizationListComponent implements OnInit { private visualizationService: VisualizationService, private spinner: NgxSpinnerService, private router: Router, - private environment: EnvironmentService, private activatedRoute: ActivatedRoute) { } @@ -73,10 +71,6 @@ export class VisualizationListComponent implements OnInit { }); } - isDev(){ - return this.environment.isDev(); - } - editVisualization(vis: VisualizationType) { this.spinner.show('loadingSpinner'); const queryParams = {}; From f95e77592cff892ff8fdbac297f3b85cd351939e Mon Sep 17 00:00:00 2001 From: Manuel Abascal Date: Sat, 5 Apr 2025 10:10:09 -0500 Subject: [PATCH 61/70] feat: add tag rule --- .../alert-rules/alert-rules.component.ts | 1 - .../alert-rule-create.component.html | 20 +++++++++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/frontend/src/app/data-management/alert-management/alert-rules/alert-rules.component.ts b/frontend/src/app/data-management/alert-management/alert-rules/alert-rules.component.ts index 6e8dfd4bb..2d1e23ba9 100644 --- a/frontend/src/app/data-management/alert-management/alert-rules/alert-rules.component.ts +++ b/frontend/src/app/data-management/alert-management/alert-rules/alert-rules.component.ts @@ -37,7 +37,6 @@ export class AlertRulesComponent implements OnInit { }; viewRule: AlertRuleType; tags: AlertTags[]; - rule: AlertRuleType; constructor(private sourcesService: SourcesService, diff --git a/frontend/src/app/data-management/alert-management/shared/components/alert-rule-create/alert-rule-create.component.html b/frontend/src/app/data-management/alert-management/shared/components/alert-rule-create/alert-rule-create.component.html index 71cc4e550..134b949fc 100644 --- a/frontend/src/app/data-management/alert-management/shared/components/alert-rule-create/alert-rule-create.component.html +++ b/frontend/src/app/data-management/alert-management/shared/components/alert-rule-create/alert-rule-create.component.html @@ -91,6 +91,26 @@
+
+ +
+ + +
+
+
From 4be4604811ac931860824637ef1030a60e12db91 Mon Sep 17 00:00:00 2001 From: Manuel Abascal Date: Sat, 5 Apr 2025 10:59:00 -0500 Subject: [PATCH 62/70] feat: add tag rule --- .../alert-rule-create.component.html | 27 ++++++++++--------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/frontend/src/app/data-management/alert-management/shared/components/alert-rule-create/alert-rule-create.component.html b/frontend/src/app/data-management/alert-management/shared/components/alert-rule-create/alert-rule-create.component.html index 134b949fc..416b7eae7 100644 --- a/frontend/src/app/data-management/alert-management/shared/components/alert-rule-create/alert-rule-create.component.html +++ b/frontend/src/app/data-management/alert-management/shared/components/alert-rule-create/alert-rule-create.component.html @@ -94,19 +94,20 @@
- +
From d8580fce3d72344c529734a5466cdfb0ffa1b560 Mon Sep 17 00:00:00 2001 From: Manuel Abascal Date: Mon, 7 Apr 2025 14:30:23 -0500 Subject: [PATCH 63/70] feat: enable create and update for incident response --- .../alert-rule-create.component.html | 21 ------------------- 1 file changed, 21 deletions(-) diff --git a/frontend/src/app/data-management/alert-management/shared/components/alert-rule-create/alert-rule-create.component.html b/frontend/src/app/data-management/alert-management/shared/components/alert-rule-create/alert-rule-create.component.html index 416b7eae7..71cc4e550 100644 --- a/frontend/src/app/data-management/alert-management/shared/components/alert-rule-create/alert-rule-create.component.html +++ b/frontend/src/app/data-management/alert-management/shared/components/alert-rule-create/alert-rule-create.component.html @@ -91,27 +91,6 @@
-
- -
- - -
-
-
From b48942a1fabbcb028c4c1f523b00bd44005d6520 Mon Sep 17 00:00:00 2001 From: Manuel Abascal Date: Mon, 7 Apr 2025 17:29:01 -0500 Subject: [PATCH 64/70] feat: add new compliance reports --- .../compliance/config/UtmComplianceReportConfigService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/src/main/java/com/park/utmstack/service/compliance/config/UtmComplianceReportConfigService.java b/backend/src/main/java/com/park/utmstack/service/compliance/config/UtmComplianceReportConfigService.java index 0eba1978a..a95f33247 100644 --- a/backend/src/main/java/com/park/utmstack/service/compliance/config/UtmComplianceReportConfigService.java +++ b/backend/src/main/java/com/park/utmstack/service/compliance/config/UtmComplianceReportConfigService.java @@ -125,7 +125,7 @@ public Page getReportsByFilters(Long standardId, Stri .filter(cp -> !cp.getDashboard().isEmpty() && cp.getDashboard().stream().allMatch(v -> v.getVisualization().getPattern().getActive())) .collect(Collectors.toList()); - return new PageImpl<>(activeCompliance, pageable, activeCompliance.size()); + return new PageImpl<>(activeCompliance, pageable, page.getTotalElements()); } From 2938c0ed916fa6495c36aa17f341a1d83caaaeff Mon Sep 17 00:00:00 2001 From: Manuel Abascal Date: Tue, 8 Apr 2025 09:21:47 -0500 Subject: [PATCH 65/70] feat: add new compliance reports --- .../config/UtmComplianceReportConfigService.java | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/backend/src/main/java/com/park/utmstack/service/compliance/config/UtmComplianceReportConfigService.java b/backend/src/main/java/com/park/utmstack/service/compliance/config/UtmComplianceReportConfigService.java index a95f33247..1b50d0542 100644 --- a/backend/src/main/java/com/park/utmstack/service/compliance/config/UtmComplianceReportConfigService.java +++ b/backend/src/main/java/com/park/utmstack/service/compliance/config/UtmComplianceReportConfigService.java @@ -120,12 +120,7 @@ public Page getReportsByFilters(Long standardId, Stri } } - List activeCompliance = page.getContent() - .stream() - .filter(cp -> !cp.getDashboard().isEmpty() && cp.getDashboard().stream().allMatch(v -> v.getVisualization().getPattern().getActive())) - .collect(Collectors.toList()); - - return new PageImpl<>(activeCompliance, pageable, page.getTotalElements()); + return page; } From 4c960a87588e26e1c8a102779309cca5daf8e2e2 Mon Sep 17 00:00:00 2001 From: Manuel Abascal Date: Tue, 8 Apr 2025 11:50:34 -0500 Subject: [PATCH 66/70] chore: update changelog --- .../shared/services/util/enviroment.service.ts | 18 ------------------ 1 file changed, 18 deletions(-) delete mode 100644 frontend/src/app/shared/services/util/enviroment.service.ts diff --git a/frontend/src/app/shared/services/util/enviroment.service.ts b/frontend/src/app/shared/services/util/enviroment.service.ts deleted file mode 100644 index fa469e6d3..000000000 --- a/frontend/src/app/shared/services/util/enviroment.service.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { Injectable } from '@angular/core'; -import {environment} from '../../../../environments/environment'; - -@Injectable({ - providedIn: 'root' -}) -export class EnvironmentService { - - constructor() { } - - isDev(): boolean { - return !environment.production; - } - - isProd(): boolean { - return environment.production; - } -} From 26eb18bbda5a987920f619b82f734fe141543e6c Mon Sep 17 00:00:00 2001 From: Manuel Abascal Date: Wed, 9 Apr 2025 13:07:36 -0500 Subject: [PATCH 67/70] feat: enable create and update of tag-based rules with dynamic conditions --- .../alert-rule-create.component.html | 117 +++++++++++------- .../alert-rule-create.component.ts | 106 +++++++++++++--- 2 files changed, 158 insertions(+), 65 deletions(-) diff --git a/frontend/src/app/data-management/alert-management/shared/components/alert-rule-create/alert-rule-create.component.html b/frontend/src/app/data-management/alert-management/shared/components/alert-rule-create/alert-rule-create.component.html index 71cc4e550..0b4cdbf4d 100644 --- a/frontend/src/app/data-management/alert-management/shared/components/alert-rule-create/alert-rule-create.component.html +++ b/frontend/src/app/data-management/alert-management/shared/components/alert-rule-create/alert-rule-create.component.html @@ -1,4 +1,5 @@ - +
- - -
- - -
-
+
@@ -81,48 +82,70 @@ rows="2">
-
-
-
+
+
By creating a False Positive rule, future alerts where the fields and values match the operator defined will be tagged as False positive. The alerts that match with this rule will be marked as Completed. +
-
-
+
View rule fields    -
-
-
- {{ getFieldName(filter.field) }}:  - - - -
-
- +
+
+
+ {{ getFieldName(condition.get('field').value) }}:  + + + + + + +
+
+ +
+
+
+
diff --git a/frontend/src/app/data-management/alert-management/alert-rules/alert-rules.component.ts b/frontend/src/app/data-management/alert-management/alert-rules/alert-rules.component.ts index 2d1e23ba9..6e8dfd4bb 100644 --- a/frontend/src/app/data-management/alert-management/alert-rules/alert-rules.component.ts +++ b/frontend/src/app/data-management/alert-management/alert-rules/alert-rules.component.ts @@ -37,6 +37,7 @@ export class AlertRulesComponent implements OnInit { }; viewRule: AlertRuleType; tags: AlertTags[]; + rule: AlertRuleType; constructor(private sourcesService: SourcesService, diff --git a/frontend/src/app/data-management/alert-management/shared/components/alert-rule-create/alert-rule-create.component.html b/frontend/src/app/data-management/alert-management/shared/components/alert-rule-create/alert-rule-create.component.html index 0b4cdbf4d..4178566cd 100644 --- a/frontend/src/app/data-management/alert-management/shared/components/alert-rule-create/alert-rule-create.component.html +++ b/frontend/src/app/data-management/alert-management/shared/components/alert-rule-create/alert-rule-create.component.html @@ -155,7 +155,7 @@
diff --git a/frontend/src/app/data-management/alert-management/shared/components/alert-rule-create/alert-rule-create.component.ts b/frontend/src/app/data-management/alert-management/shared/components/alert-rule-create/alert-rule-create.component.ts index c992210de..a2d04f8e2 100644 --- a/frontend/src/app/data-management/alert-management/shared/components/alert-rule-create/alert-rule-create.component.ts +++ b/frontend/src/app/data-management/alert-management/shared/components/alert-rule-create/alert-rule-create.component.ts @@ -201,7 +201,7 @@ export class AlertRuleCreateComponent implements OnInit, OnDestroy { this.ruleConditions.push(this.createConditionGroup(condition)); } else if (this.action === 'update') { this.filters = [...this.rule.conditions]; - this.filters.forEach(condition => { + this.rule.conditions.forEach(condition => { this.ruleConditions.push(this.createConditionGroup(condition)); }); } @@ -427,11 +427,11 @@ export class AlertRuleCreateComponent implements OnInit, OnDestroy { this.ruleConditions.removeAt(index); } - createConditionGroup(condition: { field: any; operator: any; value: any; }): FormGroup { + createConditionGroup(condition: any): FormGroup { return this.fb.group({ field: [condition.field, Validators.required], operator: [condition.operator, Validators.required], - value: [condition.value, Validators.required] + value: [condition.value] }); }