From 6aa75d1555551680dc9b11416db6c370bda0fc77 Mon Sep 17 00:00:00 2001 From: Tyler Ohlsen Date: Mon, 12 Feb 2024 18:37:22 +0000 Subject: [PATCH] Onboard search AD and search monitor tools to security IT Signed-off-by: Tyler Ohlsen --- build.gradle | 8 +- .../integTest/BaseAgentToolsIT.java | 17 ++ .../SearchAnomalyDetectorsToolIT.java | 38 ++--- .../integTest/SearchMonitorsToolIT.java | 42 +++-- .../detectors_index_mappings.json | 157 ------------------ 5 files changed, 61 insertions(+), 201 deletions(-) delete mode 100644 src/test/resources/org/opensearch/agent/tools/anomaly-detection/detectors_index_mappings.json diff --git a/build.gradle b/build.gradle index 569452c4..75d3c7df 100644 --- a/build.gradle +++ b/build.gradle @@ -367,12 +367,12 @@ integTest { systemProperty("user", user) systemProperty("password", password) + // Certain integ tests require system index manipulation to properly test. We exclude those + // in the security-enabled scenario since this action is prohibited by security plugin. if (System.getProperty("https") != null && System.getProperty("https") == "true") { filter { excludeTestsMatching "org.opensearch.integTest.SearchAlertsToolIT" - excludeTestsMatching "org.opensearch.integTest.SearchAnomalyDetectorsToolIT" excludeTestsMatching "org.opensearch.integTest.SearchAnomalyResultsToolIT" - excludeTestsMatching "org.opensearch.integTest.SearchMonitorsToolIT" } } @@ -544,12 +544,12 @@ task integTestRemote(type: RestIntegTestTask) { } } + // Certain integ tests require system index manipulation to properly test. We exclude those + // in the security-enabled scenario since this action is prohibited by security plugin. if (System.getProperty("https") != null && System.getProperty("https") == "true") { filter { excludeTestsMatching "org.opensearch.integTest.SearchAlertsToolIT" - excludeTestsMatching "org.opensearch.integTest.SearchAnomalyDetectorsToolIT" excludeTestsMatching "org.opensearch.integTest.SearchAnomalyResultsToolIT" - excludeTestsMatching "org.opensearch.integTest.SearchMonitorsToolIT" } } } diff --git a/src/test/java/org/opensearch/integTest/BaseAgentToolsIT.java b/src/test/java/org/opensearch/integTest/BaseAgentToolsIT.java index f800fe16..33a26338 100644 --- a/src/test/java/org/opensearch/integTest/BaseAgentToolsIT.java +++ b/src/test/java/org/opensearch/integTest/BaseAgentToolsIT.java @@ -126,6 +126,11 @@ protected String indexMonitor(String monitorAsJsonString) { return parseFieldFromResponse(response, "_id").toString(); } + protected void deleteMonitor(String monitorId) { + Response response = makeRequest(client(), "DELETE", "_plugins/_alerting/monitors/" + monitorId, null, (String) null, null); + assertEquals(RestStatus.OK, RestStatus.fromCode(response.getStatusLine().getStatusCode())); + } + protected String indexDetector(String detectorAsJsonString) { Response response = makeRequest(client(), "POST", "_plugins/_anomaly_detection/detectors", null, detectorAsJsonString, null); @@ -133,6 +138,18 @@ protected String indexDetector(String detectorAsJsonString) { return parseFieldFromResponse(response, "_id").toString(); } + protected void deleteDetector(String detectorId) { + Response response = makeRequest( + client(), + "DELETE", + "_plugins/_anomaly_detection/detectors/" + detectorId, + null, + (String) null, + null + ); + assertEquals(RestStatus.OK, RestStatus.fromCode(response.getStatusLine().getStatusCode())); + } + @SneakyThrows protected Map waitResponseMeetingCondition( String method, diff --git a/src/test/java/org/opensearch/integTest/SearchAnomalyDetectorsToolIT.java b/src/test/java/org/opensearch/integTest/SearchAnomalyDetectorsToolIT.java index 336d412a..750b2f48 100644 --- a/src/test/java/org/opensearch/integTest/SearchAnomalyDetectorsToolIT.java +++ b/src/test/java/org/opensearch/integTest/SearchAnomalyDetectorsToolIT.java @@ -11,8 +11,9 @@ import org.junit.After; import org.junit.Before; -import org.junit.jupiter.api.BeforeEach; -import org.opensearch.agent.tools.utils.ToolConstants; +import org.junit.jupiter.api.MethodOrderer.OrderAnnotation; +import org.junit.jupiter.api.Order; +import org.junit.jupiter.api.TestMethodOrder; import com.google.gson.Gson; import com.google.gson.JsonArray; @@ -20,16 +21,14 @@ import lombok.SneakyThrows; +@TestMethodOrder(OrderAnnotation.class) public class SearchAnomalyDetectorsToolIT extends BaseAgentToolsIT { private String registerAgentRequestBody; - private String detectorsIndexMappings; private String sampleDetector; private String sampleIndexMappings; private static final String detectorName = "foo-name"; private static final String registerAgentFilepath = "org/opensearch/agent/tools/anomaly-detection/register_flow_agent_of_search_anomaly_detectors_tool_request_body.json"; - private static final String detectorsIndexMappingsFilepath = - "org/opensearch/agent/tools/anomaly-detection/detectors_index_mappings.json"; private static final String sampleDetectorFilepath = "org/opensearch/agent/tools/anomaly-detection/sample_detector.json"; private static final String sampleIndexMappingsFilepath = "org/opensearch/agent/tools/anomaly-detection/sample_index_mappings.json"; @@ -38,27 +37,19 @@ public class SearchAnomalyDetectorsToolIT extends BaseAgentToolsIT { public void setUp() { super.setUp(); registerAgentRequestBody = Files.readString(Path.of(this.getClass().getClassLoader().getResource(registerAgentFilepath).toURI())); - detectorsIndexMappings = Files - .readString(Path.of(this.getClass().getClassLoader().getResource(detectorsIndexMappingsFilepath).toURI())); sampleDetector = Files.readString(Path.of(this.getClass().getClassLoader().getResource(sampleDetectorFilepath).toURI())); sampleIndexMappings = Files.readString(Path.of(this.getClass().getClassLoader().getResource(sampleIndexMappingsFilepath).toURI())); } - @BeforeEach - @SneakyThrows - public void prepareTest() { - deleteSystemIndices(); - } - @After @SneakyThrows public void tearDown() { super.tearDown(); deleteExternalIndices(); - deleteSystemIndices(); } @SneakyThrows + @Order(1) public void testSearchAnomalyDetectorsToolInFlowAgent_withNoSystemIndex() { String agentId = createAgent(registerAgentRequestBody); String agentInput = "{\"parameters\":{\"detectorName\": \"" + detectorName + "\"}}"; @@ -67,19 +58,20 @@ public void testSearchAnomalyDetectorsToolInFlowAgent_withNoSystemIndex() { } @SneakyThrows + @Order(2) public void testSearchAnomalyDetectorsToolInFlowAgent_noMatching() { - setupADSystemIndices(); setupTestDetectionIndex("test-index"); - ingestSampleDetector(detectorName, "test-index"); + String detectorId = ingestSampleDetector(detectorName, "test-index"); String agentId = createAgent(registerAgentRequestBody); String agentInput = "{\"parameters\":{\"detectorName\": \"" + detectorName + "foo" + "\"}}"; String result = executeAgent(agentId, agentInput); assertEquals("AnomalyDetectors=[]TotalAnomalyDetectors=0", result); + deleteDetector(detectorId); } @SneakyThrows + @Order(3) public void testSearchAnomalyDetectorsToolInFlowAgent_matching() { - setupADSystemIndices(); setupTestDetectionIndex("test-index"); String detectorId = ingestSampleDetector(detectorName, "test-index"); String agentId = createAgent(registerAgentRequestBody); @@ -88,14 +80,15 @@ public void testSearchAnomalyDetectorsToolInFlowAgent_matching() { assertTrue(result.contains(String.format("id=%s", detectorId))); assertTrue(result.contains(String.format("name=%s", detectorName))); assertTrue(result.contains(String.format("TotalAnomalyDetectors=%d", 1))); + deleteDetector(detectorId); } @SneakyThrows + @Order(4) public void testSearchAnomalyDetectorsToolInFlowAgent_complexParams() { - setupADSystemIndices(); setupTestDetectionIndex("test-index"); String detectorId = ingestSampleDetector(detectorName, "test-index"); - ingestSampleDetector(detectorName + "foo", "test-index"); + String detectorIdFoo = ingestSampleDetector(detectorName + "foo", "test-index"); String agentId = createAgent(registerAgentRequestBody); String agentInput = "{\"parameters\":{\"detectorName\": \"" + detectorName @@ -104,11 +97,8 @@ public void testSearchAnomalyDetectorsToolInFlowAgent_complexParams() { assertTrue(result.contains(String.format("id=%s", detectorId))); assertTrue(result.contains(String.format("name=%s", detectorName))); assertTrue(result.contains(String.format("TotalAnomalyDetectors=%d", 1))); - } - - @SneakyThrows - private void setupADSystemIndices() { - createIndexWithConfiguration(ToolConstants.AD_DETECTORS_INDEX, detectorsIndexMappings); + deleteDetector(detectorId); + deleteDetector(detectorIdFoo); } @SneakyThrows diff --git a/src/test/java/org/opensearch/integTest/SearchMonitorsToolIT.java b/src/test/java/org/opensearch/integTest/SearchMonitorsToolIT.java index e14fbca8..cd3eca09 100644 --- a/src/test/java/org/opensearch/integTest/SearchMonitorsToolIT.java +++ b/src/test/java/org/opensearch/integTest/SearchMonitorsToolIT.java @@ -12,7 +12,9 @@ import org.junit.After; import org.junit.Before; -import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.MethodOrderer.OrderAnnotation; +import org.junit.jupiter.api.Order; +import org.junit.jupiter.api.TestMethodOrder; import com.google.gson.Gson; import com.google.gson.JsonObject; @@ -21,6 +23,7 @@ import lombok.extern.log4j.Log4j2; @Log4j2 +@TestMethodOrder(OrderAnnotation.class) public class SearchMonitorsToolIT extends BaseAgentToolsIT { private String registerAgentRequestBody; private String sampleMonitor; @@ -38,21 +41,15 @@ public void setUp() { sampleMonitor = Files.readString(Path.of(this.getClass().getClassLoader().getResource(sampleMonitorFilepath).toURI())); } - @BeforeEach - @SneakyThrows - public void prepareTest() { - deleteSystemIndices(); - } - @After @SneakyThrows public void tearDown() { super.tearDown(); deleteExternalIndices(); - deleteSystemIndices(); } @SneakyThrows + @Order(1) public void testSearchMonitorsToolInFlowAgent_withNoSystemIndex() { String agentId = createAgent(registerAgentRequestBody); String agentInput = "{\"parameters\":{\"monitorName\": \"" + monitorName + "\"}}"; @@ -61,29 +58,33 @@ public void testSearchMonitorsToolInFlowAgent_withNoSystemIndex() { } @SneakyThrows + @Order(2) public void testSearchMonitorsToolInFlowAgent_searchById() { String monitorId = ingestSampleMonitor(monitorName, true); String agentId = createAgent(registerAgentRequestBody); String agentInput = "{\"parameters\":{\"monitorId\": \"" + monitorId + "\"}}"; - String result = executeAgent(agentId, agentInput); assertTrue(result.contains(String.format("name=%s", monitorName))); assertTrue(result.contains("TotalMonitors=1")); + deleteMonitor(monitorId); } @SneakyThrows + @Order(3) public void testSearchMonitorsToolInFlowAgent_singleMonitor_noFilter() { - ingestSampleMonitor(monitorName, true); + String monitorId = ingestSampleMonitor(monitorName, true); String agentId = createAgent(registerAgentRequestBody); String agentInput = "{\"parameters\":{}}"; String result = executeAgent(agentId, agentInput); assertTrue(result.contains(String.format("name=%s", monitorName))); assertTrue(result.contains("TotalMonitors=1")); + deleteMonitor(monitorId); } @SneakyThrows + @Order(4) public void testSearchMonitorsToolInFlowAgent_singleMonitor_filter() { String agentId = createAgent(registerAgentRequestBody); String agentInput = "{\"parameters\":{\"monitorId\": \"" + "foo-id" + "\"}}"; @@ -92,9 +93,10 @@ public void testSearchMonitorsToolInFlowAgent_singleMonitor_filter() { } @SneakyThrows + @Order(5) public void testSearchMonitorsToolInFlowAgent_multipleMonitors_noFilter() { - ingestSampleMonitor(monitorName, true); - ingestSampleMonitor(monitorName2, false); + String monitorId1 = ingestSampleMonitor(monitorName, true); + String monitorId2 = ingestSampleMonitor(monitorName2, false); String agentId = createAgent(registerAgentRequestBody); String agentInput = "{\"parameters\":{}}"; @@ -104,12 +106,15 @@ public void testSearchMonitorsToolInFlowAgent_multipleMonitors_noFilter() { assertTrue(result.contains("enabled=true")); assertTrue(result.contains("enabled=false")); assertTrue(result.contains("TotalMonitors=2")); + deleteMonitor(monitorId1); + deleteMonitor(monitorId2); } @SneakyThrows + @Order(6) public void testSearchMonitorsToolInFlowAgent_multipleMonitors_filter() { - ingestSampleMonitor(monitorName, true); - ingestSampleMonitor(monitorName2, false); + String monitorId1 = ingestSampleMonitor(monitorName, true); + String monitorId2 = ingestSampleMonitor(monitorName2, false); String agentId = createAgent(registerAgentRequestBody); String agentInput = "{\"parameters\":{\"monitorName\": \"" + monitorName + "\"}}"; @@ -118,12 +123,15 @@ public void testSearchMonitorsToolInFlowAgent_multipleMonitors_filter() { assertFalse(result.contains(String.format("name=%s", monitorName2))); assertTrue(result.contains("enabled=true")); assertTrue(result.contains("TotalMonitors=1")); + deleteMonitor(monitorId1); + deleteMonitor(monitorId2); } @SneakyThrows + @Order(7) public void testSearchMonitorsToolInFlowAgent_multipleMonitors_complexParams() { - ingestSampleMonitor(monitorName, true); - ingestSampleMonitor(monitorName2, false); + String monitorId1 = ingestSampleMonitor(monitorName, true); + String monitorId2 = ingestSampleMonitor(monitorName2, false); String agentId = createAgent(registerAgentRequestBody); String agentInput = "{\"parameters\":{\"monitorName\": \"" @@ -131,6 +139,8 @@ public void testSearchMonitorsToolInFlowAgent_multipleMonitors_complexParams() { + "\", \"enabled\": true, \"hasTriggers\": false, \"sortOrder\": \"asc\", \"sortString\": \"monitor.name.keyword\", \"size\": 10, \"startIndex\": 0 }}"; String result = executeAgent(agentId, agentInput); assertTrue(result.contains("TotalMonitors=1")); + deleteMonitor(monitorId1); + deleteMonitor(monitorId2); } private String ingestSampleMonitor(String monitorName, boolean enabled) { diff --git a/src/test/resources/org/opensearch/agent/tools/anomaly-detection/detectors_index_mappings.json b/src/test/resources/org/opensearch/agent/tools/anomaly-detection/detectors_index_mappings.json deleted file mode 100644 index 561f30ce..00000000 --- a/src/test/resources/org/opensearch/agent/tools/anomaly-detection/detectors_index_mappings.json +++ /dev/null @@ -1,157 +0,0 @@ -{ - "mappings": { - "dynamic": "false", - "_meta": { - "schema_version": 5 - }, - "properties": { - "category_field": { - "type": "keyword" - }, - "description": { - "type": "text" - }, - "detection_interval": { - "properties": { - "period": { - "properties": { - "interval": { - "type": "integer" - }, - "unit": { - "type": "keyword" - } - } - } - } - }, - "detector_type": { - "type": "keyword" - }, - "feature_attributes": { - "type": "nested", - "properties": { - "aggregation_query": { - "type": "object", - "enabled": false - }, - "feature_enabled": { - "type": "boolean" - }, - "feature_id": { - "type": "keyword", - "fields": { - "keyword": { - "type": "keyword", - "ignore_above": 256 - } - } - }, - "feature_name": { - "type": "text", - "fields": { - "keyword": { - "type": "keyword", - "ignore_above": 256 - } - } - } - } - }, - "filter_query": { - "type": "object", - "enabled": false - }, - "indices": { - "type": "text", - "fields": { - "keyword": { - "type": "keyword", - "ignore_above": 256 - } - } - }, - "last_update_time": { - "type": "date", - "format": "strict_date_time||epoch_millis" - }, - "name": { - "type": "text", - "fields": { - "keyword": { - "type": "keyword", - "ignore_above": 256 - } - } - }, - "result_index": { - "type": "keyword" - }, - "schema_version": { - "type": "integer" - }, - "shingle_size": { - "type": "integer" - }, - "time_field": { - "type": "keyword" - }, - "ui_metadata": { - "type": "object", - "enabled": false - }, - "user": { - "type": "nested", - "properties": { - "backend_roles": { - "type": "text", - "fields": { - "keyword": { - "type": "keyword" - } - } - }, - "custom_attribute_names": { - "type": "text", - "fields": { - "keyword": { - "type": "keyword" - } - } - }, - "name": { - "type": "text", - "fields": { - "keyword": { - "type": "keyword", - "ignore_above": 256 - } - } - }, - "roles": { - "type": "text", - "fields": { - "keyword": { - "type": "keyword" - } - } - } - } - }, - "window_delay": { - "properties": { - "period": { - "properties": { - "interval": { - "type": "integer" - }, - "unit": { - "type": "keyword" - } - } - } - } - } - } - } -} \ No newline at end of file