From 24c2a91bb3cf27f32fd5d1ca73e746d3b0fce5fe Mon Sep 17 00:00:00 2001 From: Yang Wang Date: Fri, 7 Feb 2020 23:56:23 +1100 Subject: [PATCH 1/4] Initial attempt --- .../xpack/core/rollup/action/RollupSearchAction.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/rollup/action/RollupSearchAction.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/rollup/action/RollupSearchAction.java index 30314dfde818f..ef7ed0291cc93 100644 --- a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/rollup/action/RollupSearchAction.java +++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/rollup/action/RollupSearchAction.java @@ -14,7 +14,7 @@ public class RollupSearchAction extends ActionType { public static final RollupSearchAction INSTANCE = new RollupSearchAction(); - public static final String NAME = "indices:admin/xpack/rollup/search"; + public static final String NAME = "indices:data/read/xpack/rollup/search"; private RollupSearchAction() { super(NAME, SearchResponse::new); From de3dc3bcda1d7861ec128bb91c39fd0ebd3156ec Mon Sep 17 00:00:00 2001 From: Yang Wang Date: Mon, 10 Feb 2020 18:01:48 +1100 Subject: [PATCH 2/4] Fix broken IT tests --- .../test/disruption/NetworkDisruption.java | 2 +- .../ml/integration/DatafeedJobsRestIT.java | 190 ++++++------------ 2 files changed, 68 insertions(+), 124 deletions(-) diff --git a/test/framework/src/main/java/org/elasticsearch/test/disruption/NetworkDisruption.java b/test/framework/src/main/java/org/elasticsearch/test/disruption/NetworkDisruption.java index cce5ed2ee2882..994a2f5f7709b 100644 --- a/test/framework/src/main/java/org/elasticsearch/test/disruption/NetworkDisruption.java +++ b/test/framework/src/main/java/org/elasticsearch/test/disruption/NetworkDisruption.java @@ -45,7 +45,7 @@ * 1) the {@link DisruptedLinks} represents the links in the network that are to be disrupted * 2) the {@link NetworkLinkDisruptionType} represents the failure mode that is to be applied to the links */ -public class NetworkDisruption implements ServiceDisruptionScheme { +public class NetworkDisruption implements ServiceDisruptionScheme { private static final Logger logger = LogManager.getLogger(NetworkDisruption.class); diff --git a/x-pack/plugin/ml/qa/native-multi-node-tests/src/test/java/org/elasticsearch/xpack/ml/integration/DatafeedJobsRestIT.java b/x-pack/plugin/ml/qa/native-multi-node-tests/src/test/java/org/elasticsearch/xpack/ml/integration/DatafeedJobsRestIT.java index 8fc6bdeef55d1..709b39170f042 100644 --- a/x-pack/plugin/ml/qa/native-multi-node-tests/src/test/java/org/elasticsearch/xpack/ml/integration/DatafeedJobsRestIT.java +++ b/x-pack/plugin/ml/qa/native-multi-node-tests/src/test/java/org/elasticsearch/xpack/ml/integration/DatafeedJobsRestIT.java @@ -428,72 +428,15 @@ public void testInsufficientSearchPrivilegesOnPut() throws Exception { containsString("user ml_admin lacks permissions on the indices")); } - public void testInsufficientSearchPrivilegesOnPutWithRollup() throws Exception { + public void testCreationOnPutWithRollup() throws Exception { setupDataAccessRole("airline-data-aggs-rollup"); String jobId = "privs-put-job-rollup"; - Request createJobRequest = new Request("PUT", MachineLearning.BASE_PATH + "anomaly_detectors/" + jobId); - createJobRequest.setJsonEntity("{\n" - + " \"description\": \"Aggs job\",\n" - + " \"analysis_config\": {\n" - + " \"bucket_span\": \"1h\",\n" - + " \"summary_count_field_name\": \"doc_count\",\n" - + " \"detectors\": [\n" - + " {\n" - + " \"function\": \"mean\",\n" - + " \"field_name\": \"responsetime\",\n" - + " \"by_field_name\": \"airline\"\n" - + " }\n" - + " ]\n" - + " },\n" - + " \"data_description\": {\"time_field\": \"time stamp\"}\n" - + "}"); - client().performRequest(createJobRequest); - - String rollupJobId = "rollup-" + jobId; - Request createRollupRequest = new Request("PUT", "/_rollup/job/" + rollupJobId); - createRollupRequest.setJsonEntity("{\n" - + "\"index_pattern\": \"airline-data-aggs\",\n" - + " \"rollup_index\": \"airline-data-aggs-rollup\",\n" - + " \"cron\": \"*/30 * * * * ?\",\n" - + " \"page_size\" :1000,\n" - + " \"groups\" : {\n" - + " \"date_histogram\": {\n" - + " \"field\": \"time stamp\",\n" - + " \"fixed_interval\": \"2m\",\n" - + " \"delay\": \"7d\"\n" - + " },\n" - + " \"terms\": {\n" - + " \"fields\": [\"airline\"]\n" - + " }" - + " },\n" - + " \"metrics\": [\n" - + " {\n" - + " \"field\": \"responsetime\",\n" - + " \"metrics\": [\"avg\",\"min\",\"max\",\"sum\"]\n" - + " },\n" - + " {\n" - + " \"field\": \"time stamp\",\n" - + " \"metrics\": [\"min\",\"max\"]\n" - + " }\n" - + " ]\n" - + "}"); - client().performRequest(createRollupRequest); - String datafeedId = "datafeed-" + jobId; - String aggregations = "{\"buckets\":{\"date_histogram\":{\"field\":\"time stamp\",\"fixed_interval\":\"3600000ms\"}," - + "\"aggregations\":{" - + "\"time stamp\":{\"max\":{\"field\":\"time stamp\"}}," - + "\"responsetime\":{\"avg\":{\"field\":\"responsetime\"}}}}}"; - + final Response response = createJobAndDataFeed(jobId, datafeedId); - ResponseException e = expectThrows(ResponseException.class, () -> - new DatafeedBuilder(datafeedId, jobId, "airline-data-aggs-rollup") - .setAggregations(aggregations) - .setAuthHeader(BASIC_AUTH_VALUE_ML_ADMIN_WITH_SOME_DATA_ACCESS) //want to search, but no admin access - .build()); - assertThat(e.getMessage(), containsString("Cannot create datafeed")); - assertThat(e.getMessage(), - containsString("user ml_admin_plus_data lacks permissions on the indices")); + assertEquals(200, response.getStatusLine().getStatusCode()); + assertThat(EntityUtils.toString(response.getEntity()), containsString("\"datafeed_id\":\"" + datafeedId + + "\",\"job_id\":\"" + jobId + "\"")); } public void testInsufficientSearchPrivilegesOnPreview() throws Exception { @@ -884,67 +827,8 @@ public void testLookbackOnlyGivenAggregationsWithHistogramAndRollupIndex() throw public void testLookbackWithoutPermissionsAndRollup() throws Exception { setupFullAccessRole("airline-data-aggs-rollup"); String jobId = "rollup-permission-test-network-job"; - Request createJobRequest = new Request("PUT", MachineLearning.BASE_PATH + "anomaly_detectors/" + jobId); - createJobRequest.setJsonEntity("{\n" - + " \"description\": \"Aggs job\",\n" - + " \"analysis_config\": {\n" - + " \"bucket_span\": \"1h\",\n" - + " \"summary_count_field_name\": \"doc_count\",\n" - + " \"detectors\": [\n" - + " {\n" - + " \"function\": \"mean\",\n" - + " \"field_name\": \"responsetime\",\n" - + " \"by_field_name\": \"airline\"\n" - + " }\n" - + " ]\n" - + " },\n" - + " \"data_description\": {\"time_field\": \"time stamp\"}\n" - + "}"); - client().performRequest(createJobRequest); - - String rollupJobId = "rollup-" + jobId; - Request createRollupRequest = new Request("PUT", "/_rollup/job/" + rollupJobId); - createRollupRequest.setJsonEntity("{\n" - + "\"index_pattern\": \"airline-data-aggs\",\n" - + " \"rollup_index\": \"airline-data-aggs-rollup\",\n" - + " \"cron\": \"*/30 * * * * ?\",\n" - + " \"page_size\" :1000,\n" - + " \"groups\" : {\n" - + " \"date_histogram\": {\n" - + " \"field\": \"time stamp\",\n" - + " \"fixed_interval\": \"2m\",\n" - + " \"delay\": \"7d\"\n" - + " },\n" - + " \"terms\": {\n" - + " \"fields\": [\"airline\"]\n" - + " }" - + " },\n" - + " \"metrics\": [\n" - + " {\n" - + " \"field\": \"responsetime\",\n" - + " \"metrics\": [\"avg\",\"min\",\"max\",\"sum\"]\n" - + " },\n" - + " {\n" - + " \"field\": \"time stamp\",\n" - + " \"metrics\": [\"min\",\"max\"]\n" - + " }\n" - + " ]\n" - + "}"); - client().performRequest(createRollupRequest); - String datafeedId = "datafeed-" + jobId; - String aggregations = "{\"buckets\":{\"date_histogram\":{\"field\":\"time stamp\",\"fixed_interval\":\"3600000ms\"}," - + "\"aggregations\":{" - + "\"time stamp\":{\"max\":{\"field\":\"time stamp\"}}," - + "\"responsetime\":{\"avg\":{\"field\":\"responsetime\"}}}}}"; - - - // At the time we create the datafeed the user can access the network-data index that we have access to - new DatafeedBuilder(datafeedId, jobId, "airline-data-aggs-rollup") - .setAggregations(aggregations) - .setChunkingTimespan("300s") - .setAuthHeader(BASIC_AUTH_VALUE_ML_ADMIN_WITH_SOME_DATA_ACCESS) - .build(); + createJobAndDataFeed(jobId, datafeedId); // Change the role so that the user can no longer access network-data setupFullAccessRole("some-other-data"); @@ -959,7 +843,7 @@ public void testLookbackWithoutPermissionsAndRollup() throws Exception { new Request("GET", AuditorField.NOTIFICATIONS_INDEX + "/_search?size=1000&q=job_id:" + jobId)); String notificationsResponseAsString = EntityUtils.toString(notificationsResponse.getEntity()); assertThat(notificationsResponseAsString, containsString("\"message\":\"Datafeed is encountering errors extracting data: " + - "action [indices:admin/xpack/rollup/search] is unauthorized for user [ml_admin_plus_data]\"")); + "action [indices:data/read/xpack/rollup/search] is unauthorized for user [ml_admin_plus_data]\"")); } public void testLookbackWithSingleBucketAgg() throws Exception { @@ -1286,4 +1170,64 @@ private void bulkIndex(String bulk) throws IOException { String bulkResponse = EntityUtils.toString(client().performRequest(bulkRequest).getEntity()); assertThat(bulkResponse, not(containsString("\"errors\": false"))); } + + private Response createJobAndDataFeed(String jobId, String datafeedId) throws IOException { + Request createJobRequest = new Request("PUT", MachineLearning.BASE_PATH + "anomaly_detectors/" + jobId); + createJobRequest.setJsonEntity("{\n" + + " \"description\": \"Aggs job\",\n" + + " \"analysis_config\": {\n" + + " \"bucket_span\": \"1h\",\n" + + " \"summary_count_field_name\": \"doc_count\",\n" + + " \"detectors\": [\n" + + " {\n" + + " \"function\": \"mean\",\n" + + " \"field_name\": \"responsetime\",\n" + + " \"by_field_name\": \"airline\"\n" + + " }\n" + + " ]\n" + + " },\n" + + " \"data_description\": {\"time_field\": \"time stamp\"}\n" + + "}"); + client().performRequest(createJobRequest); + + String rollupJobId = "rollup-" + jobId; + Request createRollupRequest = new Request("PUT", "/_rollup/job/" + rollupJobId); + createRollupRequest.setJsonEntity("{\n" + + "\"index_pattern\": \"airline-data-aggs\",\n" + + " \"rollup_index\": \"airline-data-aggs-rollup\",\n" + + " \"cron\": \"*/30 * * * * ?\",\n" + + " \"page_size\" :1000,\n" + + " \"groups\" : {\n" + + " \"date_histogram\": {\n" + + " \"field\": \"time stamp\",\n" + + " \"fixed_interval\": \"2m\",\n" + + " \"delay\": \"7d\"\n" + + " },\n" + + " \"terms\": {\n" + + " \"fields\": [\"airline\"]\n" + + " }" + + " },\n" + + " \"metrics\": [\n" + + " {\n" + + " \"field\": \"responsetime\",\n" + + " \"metrics\": [\"avg\",\"min\",\"max\",\"sum\"]\n" + + " },\n" + + " {\n" + + " \"field\": \"time stamp\",\n" + + " \"metrics\": [\"min\",\"max\"]\n" + + " }\n" + + " ]\n" + + "}"); + client().performRequest(createRollupRequest); + + String aggregations = "{\"buckets\":{\"date_histogram\":{\"field\":\"time stamp\",\"fixed_interval\":\"3600000ms\"}," + + "\"aggregations\":{" + + "\"time stamp\":{\"max\":{\"field\":\"time stamp\"}}," + + "\"responsetime\":{\"avg\":{\"field\":\"responsetime\"}}}}}"; + + return new DatafeedBuilder(datafeedId, jobId, "airline-data-aggs-rollup") + .setAggregations(aggregations) + .setAuthHeader(BASIC_AUTH_VALUE_ML_ADMIN_WITH_SOME_DATA_ACCESS) + .build(); + } } From 64b2cab102b50101dd8ed6b66f7e4d6f34d36489 Mon Sep 17 00:00:00 2001 From: Yang Wang Date: Tue, 11 Feb 2020 12:24:39 +1100 Subject: [PATCH 3/4] Add unit test --- .../action/RollupSearchActionTests.java | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/rollup/action/RollupSearchActionTests.java diff --git a/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/rollup/action/RollupSearchActionTests.java b/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/rollup/action/RollupSearchActionTests.java new file mode 100644 index 0000000000000..ff9586e97d5a3 --- /dev/null +++ b/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/rollup/action/RollupSearchActionTests.java @@ -0,0 +1,20 @@ +/* + * + * * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * * or more contributor license agreements. Licensed under the Elastic License; + * * you may not use this file except in compliance with the Elastic License. + * + */ + +package org.elasticsearch.xpack.core.rollup.action; + +import org.elasticsearch.test.ESTestCase; +import org.elasticsearch.xpack.core.security.authz.privilege.IndexPrivilege; +import org.elasticsearch.xpack.core.security.support.Automatons; + +public class RollupSearchActionTests extends ESTestCase { + + public void testIndexReadPrivilegeCanPerformRollupSearchAction() { + assertTrue(Automatons.predicate(IndexPrivilege.READ.getAutomaton()).test(RollupSearchAction.NAME)); + } +} From 5eacbf7371a8691959766dc66a7d070b11adddc2 Mon Sep 17 00:00:00 2001 From: Yang Wang Date: Tue, 11 Feb 2020 12:27:23 +1100 Subject: [PATCH 4/4] Revert accidental changes --- .../org/elasticsearch/test/disruption/NetworkDisruption.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/framework/src/main/java/org/elasticsearch/test/disruption/NetworkDisruption.java b/test/framework/src/main/java/org/elasticsearch/test/disruption/NetworkDisruption.java index 994a2f5f7709b..cce5ed2ee2882 100644 --- a/test/framework/src/main/java/org/elasticsearch/test/disruption/NetworkDisruption.java +++ b/test/framework/src/main/java/org/elasticsearch/test/disruption/NetworkDisruption.java @@ -45,7 +45,7 @@ * 1) the {@link DisruptedLinks} represents the links in the network that are to be disrupted * 2) the {@link NetworkLinkDisruptionType} represents the failure mode that is to be applied to the links */ -public class NetworkDisruption implements ServiceDisruptionScheme { +public class NetworkDisruption implements ServiceDisruptionScheme { private static final Logger logger = LogManager.getLogger(NetworkDisruption.class);