diff --git a/config/roles.yml b/config/roles.yml index 721349c086..c96e8b27e9 100644 --- a/config/roles.yml +++ b/config/roles.yml @@ -246,3 +246,12 @@ snapshot_management_read_access: - 'cluster:admin/opensearch/snapshot_management/policy/explain' - 'cluster:admin/repository/get' - 'cluster:admin/snapshot/get' + +# Allows user to use point in time functionality +point_in_time_full_access: + reserved: true + index_permissions: + - index_patterns: + - '*' + allowed_actions: + - 'manage_point_in_time' diff --git a/src/main/java/org/opensearch/security/OpenSearchSecurityPlugin.java b/src/main/java/org/opensearch/security/OpenSearchSecurityPlugin.java index 69dce00d41..e70aa01912 100644 --- a/src/main/java/org/opensearch/security/OpenSearchSecurityPlugin.java +++ b/src/main/java/org/opensearch/security/OpenSearchSecurityPlugin.java @@ -66,6 +66,7 @@ import org.opensearch.Version; import org.opensearch.action.ActionRequest; import org.opensearch.action.ActionResponse; +import org.opensearch.action.search.PitService; import org.opensearch.action.search.SearchScrollAction; import org.opensearch.action.support.ActionFilter; import org.opensearch.client.Client; @@ -1161,12 +1162,15 @@ public static class GuiceHolder implements LifecycleComponent { private static RemoteClusterService remoteClusterService; private static IndicesService indicesService; + private static PitService pitService; + @Inject public GuiceHolder(final RepositoriesService repositoriesService, - final TransportService remoteClusterService, IndicesService indicesService) { + final TransportService remoteClusterService, IndicesService indicesService, PitService pitService) { GuiceHolder.repositoriesService = repositoriesService; GuiceHolder.remoteClusterService = remoteClusterService.getRemoteClusterService(); GuiceHolder.indicesService = indicesService; + GuiceHolder.pitService = pitService; } public static RepositoriesService getRepositoriesService() { @@ -1180,6 +1184,8 @@ public static RemoteClusterService getRemoteClusterService() { public static IndicesService getIndicesService() { return indicesService; } + + public static PitService getPitService() { return pitService; } @Override public void close() { diff --git a/src/main/java/org/opensearch/security/privileges/PitPrivilegesEvaluator.java b/src/main/java/org/opensearch/security/privileges/PitPrivilegesEvaluator.java new file mode 100644 index 0000000000..b146365d57 --- /dev/null +++ b/src/main/java/org/opensearch/security/privileges/PitPrivilegesEvaluator.java @@ -0,0 +1,105 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + * + * Modifications Copyright OpenSearch Contributors. See + * GitHub history for details. + */ +package org.opensearch.security.privileges; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.TimeUnit; + +import org.opensearch.action.ActionRequest; +import org.opensearch.action.admin.indices.segments.PitSegmentsRequest; +import org.opensearch.action.search.CreatePitRequest; +import org.opensearch.action.search.DeletePitRequest; +import org.opensearch.cluster.metadata.IndexNameExpressionResolver; +import org.opensearch.cluster.service.ClusterService; +import org.opensearch.common.unit.TimeValue; +import org.opensearch.security.OpenSearchSecurityPlugin; +import org.opensearch.security.resolver.IndexResolverReplacer; +import org.opensearch.security.securityconf.SecurityRoles; +import org.opensearch.security.user.User; + + +/** + * This class evaluates privileges for point in time (Delete and List all) operations. + * For aliases - users must have either alias permission or backing index permissions + * For data streams - users must have access to backing indices permission + data streams permission. + */ +public class PitPrivilegesEvaluator { + + public PrivilegesEvaluatorResponse evaluate(final ActionRequest request, final ClusterService clusterService, + final User user, final SecurityRoles securityRoles, final String action, + final IndexNameExpressionResolver resolver, + final PrivilegesEvaluatorResponse presponse, + final IndexResolverReplacer irr) { + + if(!(request instanceof DeletePitRequest || request instanceof PitSegmentsRequest)) { + return presponse; + } + List pitIds = new ArrayList<>(); + + if (request instanceof DeletePitRequest) { + DeletePitRequest deletePitRequest = (DeletePitRequest) request; + pitIds = deletePitRequest.getPitIds(); + } else if(request instanceof PitSegmentsRequest) { + PitSegmentsRequest pitSegmentsRequest = (PitSegmentsRequest) request; + pitIds = pitSegmentsRequest.getPitIds(); + } + // if request is for all PIT IDs, skip custom pit ids evaluation + if (pitIds.size() == 1 && "_all".equals(pitIds.get(0))) { + return presponse; + } else { + return handlePitsAccess(pitIds, clusterService, user, securityRoles, + action, resolver, presponse, irr); + } + } + + /** + * Handle access for delete operation / pit segments operation where PIT IDs are explicitly passed + */ + private PrivilegesEvaluatorResponse handlePitsAccess(List pitIds, ClusterService clusterService, + User user, SecurityRoles securityRoles, final String action, + IndexNameExpressionResolver resolver, PrivilegesEvaluatorResponse presponse, + final IndexResolverReplacer irr) { + Map pitToIndicesMap = OpenSearchSecurityPlugin. + GuiceHolder.getPitService().getIndicesForPits(pitIds); + Set pitIndices = new HashSet<>(); + // add indices across all PITs to a set and evaluate if user has access to all indices + for(String[] indices: pitToIndicesMap.values()) { + pitIndices.addAll(Arrays.asList(indices)); + } + Set allPermittedIndices = getPermittedIndices(pitIndices, clusterService, user, + securityRoles, action, resolver, irr); + // Only if user has access to all PIT's indices, allow operation, otherwise continue evaluation in PrivilegesEvaluator. + if(allPermittedIndices.containsAll(pitIndices)) { + presponse.allowed = true; + presponse.markComplete(); + } + return presponse; + } + + /** + * This method returns list of permitted indices for the PIT indices passed + */ + private Set getPermittedIndices(Set pitIndices, ClusterService clusterService, + User user, SecurityRoles securityRoles, final String action, + IndexNameExpressionResolver resolver, final IndexResolverReplacer irr) { + String[] indicesArr = new String[pitIndices.size()]; + CreatePitRequest req = new CreatePitRequest(new TimeValue(1, TimeUnit.DAYS), true, + pitIndices.toArray(indicesArr)); + final IndexResolverReplacer.Resolved pitResolved = irr.resolveRequest(req); + return securityRoles.reduce(pitResolved, + user, new String[]{action}, resolver, clusterService); + } +} diff --git a/src/main/java/org/opensearch/security/privileges/PrivilegesEvaluator.java b/src/main/java/org/opensearch/security/privileges/PrivilegesEvaluator.java index fd1b26d388..df9c432827 100644 --- a/src/main/java/org/opensearch/security/privileges/PrivilegesEvaluator.java +++ b/src/main/java/org/opensearch/security/privileges/PrivilegesEvaluator.java @@ -130,6 +130,7 @@ public class PrivilegesEvaluator { private final SecurityIndexAccessEvaluator securityIndexAccessEvaluator; private final ProtectedIndexAccessEvaluator protectedIndexAccessEvaluator; private final TermsAggregationEvaluator termsAggregationEvaluator; + private final PitPrivilegesEvaluator pitPrivilegesEvaluator; private final boolean dlsFlsEnabled; private final boolean dfmEmptyOverwritesAll; private DynamicConfigModel dcm; @@ -158,6 +159,7 @@ public PrivilegesEvaluator(final ClusterService clusterService, final ThreadPool securityIndexAccessEvaluator = new SecurityIndexAccessEvaluator(settings, auditLog, irr); protectedIndexAccessEvaluator = new ProtectedIndexAccessEvaluator(settings, auditLog); termsAggregationEvaluator = new TermsAggregationEvaluator(); + pitPrivilegesEvaluator = new PitPrivilegesEvaluator(); this.namedXContentRegistry = namedXContentRegistry; this.dlsFlsEnabled = dlsFlsEnabled; this.dfmEmptyOverwritesAll = settings.getAsBoolean(ConfigConstants.SECURITY_DFM_EMPTY_OVERRIDES_ALL, false); @@ -282,6 +284,12 @@ public PrivilegesEvaluatorResponse evaluate(final User user, String action0, fin return presponse; } + // check access for point in time requests + if(pitPrivilegesEvaluator.evaluate(request, clusterService, user, securityRoles, + action0, resolver, presponse, irr).isComplete()) { + return presponse; + } + final boolean dnfofEnabled = dcm.isDnfofEnabled(); final boolean isTraceEnabled = log.isTraceEnabled(); diff --git a/src/main/java/org/opensearch/security/resolver/IndexResolverReplacer.java b/src/main/java/org/opensearch/security/resolver/IndexResolverReplacer.java index e0eddf9993..d2d0685860 100644 --- a/src/main/java/org/opensearch/security/resolver/IndexResolverReplacer.java +++ b/src/main/java/org/opensearch/security/resolver/IndexResolverReplacer.java @@ -370,11 +370,11 @@ public final static class Resolved { private final boolean isLocalAll; private final IndicesOptions indicesOptions; - private Resolved(final ImmutableSet aliases, - final ImmutableSet allIndices, - final ImmutableSet originalRequested, - final ImmutableSet remoteIndices, - IndicesOptions indicesOptions) { + public Resolved(final ImmutableSet aliases, + final ImmutableSet allIndices, + final ImmutableSet originalRequested, + final ImmutableSet remoteIndices, + IndicesOptions indicesOptions) { this.aliases = aliases; this.allIndices = allIndices; this.originalRequested = originalRequested; diff --git a/src/main/resources/static_config/static_action_groups.yml b/src/main/resources/static_config/static_action_groups.yml index d0ce7613a2..c7c351d171 100644 --- a/src/main/resources/static_config/static_action_groups.yml +++ b/src/main/resources/static_config/static_action_groups.yml @@ -233,8 +233,9 @@ manage_point_in_time: static: true allowed_actions: - "indices:data/read/point_in_time/create" - - "cluster:admin/point_in_time/delete" - - "cluster:admin/point_in_time/read*" + - "indices:data/read/point_in_time/delete" + - "indices:data/read/point_in_time/readall" + - "indices:data/read/search" - "indices:monitor/point_in_time/segments" - type: "cluster" + type: "index" description: "Manage point in time actions" diff --git a/src/test/java/org/opensearch/security/PitIntegrationTests.java b/src/test/java/org/opensearch/security/PitIntegrationTests.java new file mode 100644 index 0000000000..b31450dcf7 --- /dev/null +++ b/src/test/java/org/opensearch/security/PitIntegrationTests.java @@ -0,0 +1,243 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + * + * Modifications Copyright OpenSearch Contributors. See + * GitHub history for details. + */ +package org.opensearch.security; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.http.HttpStatus; +import org.junit.Assert; +import org.junit.Test; + +import org.opensearch.action.admin.indices.alias.Alias; +import org.opensearch.action.admin.indices.create.CreateIndexRequest; +import org.opensearch.action.index.IndexRequest; +import org.opensearch.action.support.WriteRequest; +import org.opensearch.client.Client; +import org.opensearch.common.xcontent.XContentType; +import org.opensearch.security.test.SingleClusterTest; +import org.opensearch.security.test.helper.rest.RestHelper; + +/** + * Integration tests to test point in time APIs permission model + */ +public class PitIntegrationTests extends SingleClusterTest { + + @Test + public void testPitExplicitAPIAccess() throws Exception { + setup(); + RestHelper rh = nonSslRestHelper(); + try (Client tc = getClient()) { + // create alias + tc.admin().indices().create(new CreateIndexRequest("pit_1") + .alias(new Alias("alias"))) + .actionGet(); + // create index + tc.index(new IndexRequest("pit_2").id("2").setRefreshPolicy(WriteRequest.RefreshPolicy.IMMEDIATE). + source("{\"content\":2}", XContentType.JSON)).actionGet(); + + } + + RestHelper.HttpResponse resc; + + // Create point in time in index should be successful since the user has permission for index + resc = rh.executePostRequest("/alias/_search/point_in_time?keep_alive=100m", "", + encodeBasicHeader("pit-1", "nagilum")); + Assert.assertEquals(HttpStatus.SC_OK, resc.getStatusCode()); + String pitId1 = resc.findValueInJson("pit_id"); + + // Create point in time in index for which the user does not have permission + resc = rh.executePostRequest("/pit_2/_search/point_in_time?keep_alive=100m", "", + encodeBasicHeader("pit-1", "nagilum")); + Assert.assertEquals(HttpStatus.SC_FORBIDDEN, resc.getStatusCode()); + + // Create point in time in index for which the user has permission for + resc = rh.executePostRequest("/pit_2/_search/point_in_time?keep_alive=100m", "", + encodeBasicHeader("pit-2", "nagilum")); + Assert.assertEquals(HttpStatus.SC_OK, resc.getStatusCode()); + + String pitId2 = resc.findValueInJson("pit_id"); + resc = rh.executePostRequest("/pit*/_search/point_in_time?keep_alive=100m", "", + encodeBasicHeader("all-pit", "nagilum")); + Assert.assertEquals(HttpStatus.SC_OK, resc.getStatusCode()); + + // PIT segments should work since there is atleast one PIT for which user has access for + resc = rh.executeGetRequest("/_cat/pit_segments", + "{\"pit_id\":\"" + pitId1 +"\"}", + encodeBasicHeader("pit-1", "nagilum")); + Assert.assertEquals(HttpStatus.SC_OK, resc.getStatusCode()); + + // PIT segments should work since there is atleast one PIT for which user has access for + resc = rh.executeGetRequest("/_cat/pit_segments", + "{\"pit_id\":\"" + pitId1 +"\"}", + encodeBasicHeader("pit-1", "nagilum")); + Assert.assertEquals(HttpStatus.SC_OK, resc.getStatusCode()); + + // Should throw error since user does not have access for pitId2 + resc = rh.executeGetRequest("/_cat/pit_segments", + "{\"pit_id\":\"" + pitId2 +"\"}", + encodeBasicHeader("pit-1", "nagilum")); + Assert.assertEquals(HttpStatus.SC_FORBIDDEN, resc.getStatusCode()); + + // Should throw error since user does not have access for pitId2 + resc = rh.executeGetRequest("/_cat/pit_segments", + "{\"pit_id\":[\"" + pitId1 +"\",\"" + pitId2 + "\"]}", + encodeBasicHeader("pit-1", "nagilum")); + Assert.assertEquals(HttpStatus.SC_FORBIDDEN, resc.getStatusCode()); + + // Delete explicit PITs should work for PIT for which user has access for + resc = rh.executeDeleteRequest("/_search/point_in_time", + "{\"pit_id\":\"" + pitId1 +"\"}", + encodeBasicHeader("pit-1", "nagilum")); + Assert.assertEquals(HttpStatus.SC_OK, resc.getStatusCode()); + Assert.assertEquals(pitId1, resc.findValueInJson("pits[0].pit_id")); + Assert.assertEquals("true", resc.findValueInJson("pits[0].successful")); + + // Should throw error since user does not have access for pitId2 + resc = rh.executeDeleteRequest("/_search/point_in_time", + "{\"pit_id\":\"" + pitId2 +"\"}", + encodeBasicHeader("pit-1", "nagilum")); + Assert.assertEquals(HttpStatus.SC_FORBIDDEN, resc.getStatusCode()); + + // Should throw error since user does not have access for pitId2 + resc = rh.executeDeleteRequest("/_search/point_in_time", + "{\"pit_id\":[\"" + pitId1 +"\",\"" + pitId2 + "\"]}", + encodeBasicHeader("pit-1", "nagilum")); + Assert.assertEquals(HttpStatus.SC_FORBIDDEN, resc.getStatusCode()); + + // Delete explicit PITs should work for PIT for which user has access for + resc = rh.executeDeleteRequest("/_search/point_in_time", + "{\"pit_id\":\"" + pitId2 +"\"}", + encodeBasicHeader("pit-2", "nagilum")); + Assert.assertEquals(HttpStatus.SC_OK, resc.getStatusCode()); + Assert.assertEquals(pitId2, resc.findValueInJson("pits[0].pit_id")); + Assert.assertEquals("true", resc.findValueInJson("pits[0].successful")); + + } + + @Test + public void testPitAllAPIAccess() throws Exception { + setup(); + RestHelper rh = nonSslRestHelper(); + + // Create two indices + try (Client tc = getClient()) { + tc.index(new IndexRequest("pit_1").id("1").setRefreshPolicy(WriteRequest.RefreshPolicy.IMMEDIATE). + source("{\"content\":1}", XContentType.JSON)).actionGet(); + tc.index(new IndexRequest("pit_2").id("2").setRefreshPolicy(WriteRequest.RefreshPolicy.IMMEDIATE). + source("{\"content\":2}", XContentType.JSON)).actionGet(); + } + + RestHelper.HttpResponse resc; + + // Create point in time in index should be successful since the user has permission for index + resc = rh.executePostRequest("/pit_1/_search/point_in_time?keep_alive=100m", "", + encodeBasicHeader("pit-1", "nagilum")); + Assert.assertEquals(HttpStatus.SC_OK, resc.getStatusCode()); + String pitId1 = resc.findValueInJson("pit_id"); + + // Create point in time in index for which the user does not have permission + resc = rh.executePostRequest("/pit_2/_search/point_in_time?keep_alive=100m", "", + encodeBasicHeader("pit-1", "nagilum")); + Assert.assertEquals(HttpStatus.SC_FORBIDDEN, resc.getStatusCode()); + + // Create point in time in index for which the user has permission for + resc = rh.executePostRequest("/pit_2/_search/point_in_time?keep_alive=100m", "", + encodeBasicHeader("pit-2", "nagilum")); + Assert.assertEquals(HttpStatus.SC_OK, resc.getStatusCode()); + + String pitId2 = resc.findValueInJson("pit_id"); + + // Throw security error if user does not have all index permission + resc = rh.executeGetRequest("/_search/point_in_time/_all", + encodeBasicHeader("pit-1", "nagilum")); + Assert.assertEquals(HttpStatus.SC_FORBIDDEN, resc.getStatusCode()); + + // List all PITs should work for user with all index access + resc = rh.executeGetRequest("/_search/point_in_time/_all", + encodeBasicHeader("all-pit", "nagilum")); + Assert.assertEquals(HttpStatus.SC_OK, resc.getStatusCode()); + List pitList = new ArrayList<>(); + pitList.add(pitId1); + pitList.add(pitId2); + pitList.contains(resc.findValueInJson("pits[0].pit_id")); + pitList.contains(resc.findValueInJson("pits[1].pit_id")); + + // Throw security error if user does not have all index permission + resc = rh.executeGetRequest("/_cat/pit_segments/_all", + encodeBasicHeader("pit-1", "nagilum")); + Assert.assertEquals(HttpStatus.SC_FORBIDDEN, resc.getStatusCode()); + + // PIT segments should work for user with all index access + resc = rh.executeGetRequest("/_cat/pit_segments/_all", + encodeBasicHeader("all-pit", "nagilum")); + Assert.assertEquals(HttpStatus.SC_OK, resc.getStatusCode()); + + + // Throw security error if user does not have all index permission + resc = rh.executeDeleteRequest("/_search/point_in_time/_all", + encodeBasicHeader("pit-1", "nagilum")); + Assert.assertEquals(HttpStatus.SC_FORBIDDEN, resc.getStatusCode()); + + // Delete all PITs should work for user with all index access + resc = rh.executeDeleteRequest("/_search/point_in_time/_all", + encodeBasicHeader("all-pit", "nagilum")); + Assert.assertEquals(HttpStatus.SC_OK, resc.getStatusCode()); + pitList.contains(resc.findValueInJson("pits[0].pit_id")); + pitList.contains(resc.findValueInJson("pits[1].pit_id")); + Assert.assertEquals("true", resc.findValueInJson("pits[0].successful")); + Assert.assertEquals("true", resc.findValueInJson("pits[1].successful")); + + } + + @Test + public void testDataStreamWithPits() throws Exception { + setup(); + RestHelper rh = nonSslRestHelper(); + String indexTemplate = "{\"index_patterns\": [ \"my-data-stream*\" ], \"data_stream\": { }, \"priority\": 200, " + + "\"template\": {\"settings\": { } } }"; + + rh.executePutRequest("/_index_template/my-data-stream-template", indexTemplate, encodeBasicHeader("ds1", "nagilum")); + + rh.executePutRequest("/_data_stream/my-data-stream11", indexTemplate, encodeBasicHeader("ds3", "nagilum")); + rh.executePutRequest("/_data_stream/my-data-stream21", indexTemplate, encodeBasicHeader("ds3", "nagilum")); + + RestHelper.HttpResponse resc; + // create pit should work since user has permission on data stream + resc = rh.executePostRequest("/my-data-stream11/_search/point_in_time?keep_alive=100m", "", + encodeBasicHeader("pit-1", "nagilum")); + Assert.assertEquals(HttpStatus.SC_OK, resc.getStatusCode()); + String pitId1 = resc.findValueInJson("pit_id"); + + // PIT segments works since the user has access for backing indices + resc = rh.executeGetRequest("/_cat/pit_segments", + "{\"pit_id\":\"" + pitId1 +"\"}", + encodeBasicHeader("pit-1", "nagilum")); + Assert.assertEquals(HttpStatus.SC_OK, resc.getStatusCode()); + + // create pit should work since user has permission on data stream + resc = rh.executePostRequest("/my-data-stream21/_search/point_in_time?keep_alive=100m", "", + encodeBasicHeader("pit-2", "nagilum")); + Assert.assertEquals(HttpStatus.SC_OK, resc.getStatusCode()); + String pitId2 = resc.findValueInJson("pit_id"); + + // since pit-2 doesn't have permission to backing data stream indices, throw security error + resc = rh.executeGetRequest("/_cat/pit_segments", + "{\"pit_id\":\"" + pitId2 +"\"}", + encodeBasicHeader("pit-2", "nagilum")); + Assert.assertEquals(HttpStatus.SC_FORBIDDEN, resc.getStatusCode()); + + // Delete all PITs should work for user with all index access + resc = rh.executeDeleteRequest("/_search/point_in_time/_all", + encodeBasicHeader("all-pit", "nagilum")); + Assert.assertEquals(HttpStatus.SC_OK, resc.getStatusCode()); + } +} diff --git a/src/test/java/org/opensearch/security/test/helper/rest/RestHelper.java b/src/test/java/org/opensearch/security/test/helper/rest/RestHelper.java index 6bc8a056b8..49d498833e 100644 --- a/src/test/java/org/opensearch/security/test/helper/rest/RestHelper.java +++ b/src/test/java/org/opensearch/security/test/helper/rest/RestHelper.java @@ -47,6 +47,7 @@ import org.apache.commons.io.IOUtils; import org.apache.http.Header; import org.apache.http.HttpEntity; +import org.apache.http.HttpHeaders; import org.apache.http.auth.AuthScope; import org.apache.http.auth.UsernamePasswordCredentials; import org.apache.http.client.CredentialsProvider; @@ -59,6 +60,7 @@ import org.apache.http.client.methods.HttpPost; import org.apache.http.client.methods.HttpPut; import org.apache.http.client.methods.HttpUriRequest; +import org.apache.http.client.methods.RequestBuilder; import org.apache.http.config.SocketConfig; import org.apache.http.conn.ssl.NoopHostnameVerifier; import org.apache.http.conn.ssl.SSLConnectionSocketFactory; @@ -143,6 +145,14 @@ public HttpResponse[] executeMultipleAsyncPutRequest(final int numOfRequests, fi public HttpResponse executeGetRequest(final String request, Header... header) { return executeRequest(new HttpGet(getHttpServerUri() + "/" + request), header); } + + public HttpResponse executeGetRequest(final String request, String body, Header... header) { + HttpUriRequest uriRequest = RequestBuilder.get(getHttpServerUri() + "/" + request) + .setEntity(createStringEntity(body)) + .setHeader(HttpHeaders.CONTENT_TYPE, "application/json") + .build(); + return executeRequest(uriRequest, header); + } public HttpResponse executeHeadRequest(final String request, Header... header) { return executeRequest(new HttpHead(getHttpServerUri() + "/" + request), header); @@ -164,6 +174,15 @@ public HttpResponse executeDeleteRequest(final String request, Header... header) return executeRequest(new HttpDelete(getHttpServerUri() + "/" + request), header); } + public HttpResponse executeDeleteRequest(final String request, String body, Header... header) { + HttpUriRequest uriRequest = RequestBuilder.delete(getHttpServerUri() + "/" + request) + .setEntity(createStringEntity(body)) + .setHeader(HttpHeaders.CONTENT_TYPE, "application/json") + .build(); + return executeRequest(uriRequest, header); + } + + public HttpResponse executePostRequest(final String request, String body, Header... header) { HttpPost uriRequest = new HttpPost(getHttpServerUri() + "/" + request); if (body != null && !body.isEmpty()) { diff --git a/src/test/resources/internal_users.yml b/src/test/resources/internal_users.yml index 99d821ce33..44464c9cf7 100644 --- a/src/test/resources/internal_users.yml +++ b/src/test/resources/internal_users.yml @@ -346,6 +346,15 @@ ds2: ds3: hash: $2a$12$n5nubfWATfQjSYHiWtUyeOxMIxFInUHOAx8VMmGmxFNPGpaBmeB.m #password is: nagilum +pit-1: + hash: $2a$12$n5nubfWATfQjSYHiWtUyeOxMIxFInUHOAx8VMmGmxFNPGpaBmeB.m + #password is: nagilum +pit-2: + hash: $2a$12$n5nubfWATfQjSYHiWtUyeOxMIxFInUHOAx8VMmGmxFNPGpaBmeB.m + #password is: nagilum +all-pit: + hash: $2a$12$n5nubfWATfQjSYHiWtUyeOxMIxFInUHOAx8VMmGmxFNPGpaBmeB.m + #password is: nagilum hidden_test: hash: $2a$12$n5nubfWATfQjSYHiWtUyeOxMIxFInUHOAx8VMmGmxFNPGpaBmeB.m opendistro_security_roles: diff --git a/src/test/resources/roles.yml b/src/test/resources/roles.yml index 20e7c38cdb..4da098e762 100644 --- a/src/test/resources/roles.yml +++ b/src/test/resources/roles.yml @@ -1129,6 +1129,47 @@ data_stream_3: allowed_actions: - "DATASTREAM_ALL" +point_in_time_1: + reserved: true + hidden: false + description: "Migrated from v6 (all types mapped)" + index_permissions: + - index_patterns: + - "pit_1" + - "*my-data-stream11*" + dls: null + fls: null + masked_fields: null + allowed_actions: + - "manage_point_in_time" + +point_in_time_2: + reserved: true + hidden: false + description: "Migrated from v6 (all types mapped)" + index_permissions: + - index_patterns: + - "my-data-stream21" + - "pit_2" + dls: null + fls: null + masked_fields: null + allowed_actions: + - "manage_point_in_time" + +point_in_time_all: + reserved: true + hidden: false + description: "Migrated from v6 (all types mapped)" + index_permissions: + - index_patterns: + - "*" + dls: null + fls: null + masked_fields: null + allowed_actions: + - "manage_point_in_time" + hidden_test: cluster_permissions: - SGS_CLUSTER_COMPOSITE_OPS diff --git a/src/test/resources/roles_mapping.yml b/src/test/resources/roles_mapping.yml index 9253b0c970..bc32c5b403 100644 --- a/src/test/resources/roles_mapping.yml +++ b/src/test/resources/roles_mapping.yml @@ -413,6 +413,21 @@ data_stream_3: hidden: false users: - "ds3" +point_in_time_1: + reserved: false + hidden: false + users: + - "pit-1" +point_in_time_2: + reserved: false + hidden: false + users: + - "pit-2" +point_in_time_all: + reserved: false + hidden: false + users: + - "all-pit" sem-role: reserved: false hidden: false