From 1f3b093bc4b0b061f40f6d66de537df893ae079d Mon Sep 17 00:00:00 2001 From: "opensearch-trigger-bot[bot]" <98922864+opensearch-trigger-bot[bot]@users.noreply.github.com> Date: Thu, 26 Oct 2023 03:39:36 -0700 Subject: [PATCH] return rule fields which do not have aliases (#652) (#694) * return rule fields which do not have aliases Signed-off-by: Subhobrata Dey * return rule fields which do not have aliases Signed-off-by: Subhobrata Dey --------- Signed-off-by: Subhobrata Dey (cherry picked from commit 92a620d158d27d860ad81e5e04c00b54387ea74e) Co-authored-by: Subhobrata Dey --- .../mapper/MapperService.java | 2 + .../securityanalytics/TestHelpers.java | 29 ++++++++++ .../resthandler/RuleRestApiIT.java | 55 +++++++++++++++++-- 3 files changed, 82 insertions(+), 4 deletions(-) diff --git a/src/main/java/org/opensearch/securityanalytics/mapper/MapperService.java b/src/main/java/org/opensearch/securityanalytics/mapper/MapperService.java index 3aedc0c8f..84332cbba 100644 --- a/src/main/java/org/opensearch/securityanalytics/mapper/MapperService.java +++ b/src/main/java/org/opensearch/securityanalytics/mapper/MapperService.java @@ -515,6 +515,8 @@ public void onResponse(GetMappingsResponse getMappingsResponse) { aliasMappingFields.put(mapping.getEcs(), Map.of("type", "alias", "path", mapping.getOcsf())); } else if (mapping.getEcs() != null) { aliasMappingFields.put(mapping.getEcs(), Map.of("type", "alias", "path", mapping.getRawField())); + } else if (mapping.getEcs() == null) { + aliasMappingFields.put(mapping.getRawField(), Map.of("type", "alias", "path", mapping.getRawField())); } } aliasMappingsObj.field("properties", aliasMappingFields); diff --git a/src/test/java/org/opensearch/securityanalytics/TestHelpers.java b/src/test/java/org/opensearch/securityanalytics/TestHelpers.java index 929a2b987..bca37dec6 100644 --- a/src/test/java/org/opensearch/securityanalytics/TestHelpers.java +++ b/src/test/java/org/opensearch/securityanalytics/TestHelpers.java @@ -259,6 +259,35 @@ public static String randomRule() { "level: high"; } + public static String randomRuleForMappingView(String field) { + return "title: Remote Encrypting File System Abuse\n" + + "id: 5f92fff9-82e2-48eb-8fc1-8b133556a551\n" + + "description: Detects remote RPC calls to possibly abuse remote encryption service via MS-EFSR\n" + + "references:\n" + + " - https://attack.mitre.org/tactics/TA0008/\n" + + " - https://msrc.microsoft.com/update-guide/vulnerability/CVE-2021-36942\n" + + " - https://github.com/jsecurity101/MSRPC-to-ATTACK/blob/main/documents/MS-EFSR.md\n" + + " - https://github.com/zeronetworks/rpcfirewall\n" + + " - https://zeronetworks.com/blog/stopping_lateral_movement_via_the_rpc_firewall/\n" + + "tags:\n" + + " - attack.defense_evasion\n" + + "status: experimental\n" + + "author: Sagie Dulce, Dekel Paz\n" + + "date: 2022/01/01\n" + + "modified: 2022/01/01\n" + + "logsource:\n" + + " product: rpc_firewall\n" + + " category: application\n" + + " definition: 'Requirements: install and apply the RPC Firewall to all processes with \"audit:true action:block uuid:df1941c5-fe89-4e79-bf10-463657acf44d or c681d488-d850-11d0-8c52-00c04fd90f7e'\n" + + "detection:\n" + + " selection:\n" + + " "+ field + ": 'ACL'\n" + + " condition: selection\n" + + "falsepositives:\n" + + " - Legitimate usage of remote file encryption\n" + + "level: high"; + } + public static String randomRuleForCustomLogType() { return "title: Remote Encrypting File System Abuse\n" + "id: 5f92fff9-82e2-48eb-8fc1-8b133556a551\n" + diff --git a/src/test/java/org/opensearch/securityanalytics/resthandler/RuleRestApiIT.java b/src/test/java/org/opensearch/securityanalytics/resthandler/RuleRestApiIT.java index ebefa843c..f043469f0 100644 --- a/src/test/java/org/opensearch/securityanalytics/resthandler/RuleRestApiIT.java +++ b/src/test/java/org/opensearch/securityanalytics/resthandler/RuleRestApiIT.java @@ -21,7 +21,6 @@ import org.opensearch.securityanalytics.SecurityAnalyticsPlugin; import org.opensearch.securityanalytics.SecurityAnalyticsRestTestCase; import org.opensearch.securityanalytics.config.monitors.DetectorMonitorConfig; -import org.opensearch.securityanalytics.logtype.BuiltinLogTypeLoader; import org.opensearch.securityanalytics.model.Detector; import org.opensearch.securityanalytics.model.DetectorInput; import org.opensearch.securityanalytics.model.DetectorRule; @@ -29,9 +28,6 @@ import java.io.File; import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; import java.util.Collections; import java.util.List; import java.util.Locale; @@ -46,6 +42,7 @@ import static org.opensearch.securityanalytics.TestHelpers.randomEditedRule; import static org.opensearch.securityanalytics.TestHelpers.randomIndex; import static org.opensearch.securityanalytics.TestHelpers.randomRule; +import static org.opensearch.securityanalytics.TestHelpers.randomRuleForMappingView; import static org.opensearch.securityanalytics.TestHelpers.randomRuleWithErrors; import static org.opensearch.securityanalytics.TestHelpers.windowsIndexMapping; @@ -840,4 +837,54 @@ public void testGetAllRuleCategories() throws IOException { assertTrue(categories.stream().anyMatch(e -> ((Map)e).get("key").equals("linux"))); assertTrue(categories.stream().anyMatch(e -> ((Map)e).get("key").equals("waf"))); } + + @SuppressWarnings("unchecked") + public void testGetMappingsViewApiForFieldAliasesWithSameName() throws IOException { + String index = createTestIndex(randomIndex(), windowsIndexMapping()); + // Execute GetMappingsViewAction to add alias mapping for index + Request request = new Request("GET", SecurityAnalyticsPlugin.MAPPINGS_VIEW_BASE_URI); + // both req params and req body are supported + request.addParameter("index_name", index); + request.addParameter("rule_topic", randomDetectorType()); + Response response = client().performRequest(request); + assertEquals(HttpStatus.SC_OK, response.getStatusLine().getStatusCode()); + Map respMap = responseAsMap(response); + Assert.assertTrue(((List) respMap.get("unmapped_index_fields")).contains("AccessList")); + + String rule = randomRuleForMappingView("AccessList"); + + Response createResponse = makeRequest(client(), "POST", SecurityAnalyticsPlugin.RULE_BASE_URI, Collections.singletonMap("category", randomDetectorType()), + new StringEntity(rule), new BasicHeader("Content-Type", "application/json")); + Assert.assertEquals("Create rule failed", RestStatus.CREATED, restStatus(createResponse)); + Map responseBody = asMap(createResponse); + String createdId = responseBody.get("_id").toString(); + + // Execute GetMappingsViewAction to add alias mapping for index + request = new Request("GET", SecurityAnalyticsPlugin.MAPPINGS_VIEW_BASE_URI); + // both req params and req body are supported + request.addParameter("index_name", index); + request.addParameter("rule_topic", randomDetectorType()); + response = client().performRequest(request); + assertEquals(HttpStatus.SC_OK, response.getStatusLine().getStatusCode()); + respMap = responseAsMap(response); + Assert.assertTrue(((Map) respMap.get("properties")).containsKey("AccessList")); + + rule = randomRuleForMappingView("Access_List"); + + Response updateResponse = makeRequest(client(), "PUT", SecurityAnalyticsPlugin.RULE_BASE_URI + "/" + createdId, + Map.of("category", randomDetectorType()), + new StringEntity(rule), new BasicHeader("Content-Type", "application/json")); + Assert.assertEquals("Update rule failed", RestStatus.OK, restStatus(updateResponse)); + + // Execute GetMappingsViewAction to add alias mapping for index + request = new Request("GET", SecurityAnalyticsPlugin.MAPPINGS_VIEW_BASE_URI); + // both req params and req body are supported + request.addParameter("index_name", index); + request.addParameter("rule_topic", randomDetectorType()); + response = client().performRequest(request); + assertEquals(HttpStatus.SC_OK, response.getStatusLine().getStatusCode()); + respMap = responseAsMap(response); + Assert.assertTrue(((List) respMap.get("unmapped_field_aliases")).contains("Access_List")); + Assert.assertTrue(((Map) respMap.get("properties")).containsKey("AccessList")); + } }