|
27 | 27 | import org.junit.runner.RunWith;
|
28 | 28 |
|
29 | 29 | import org.opensearch.action.admin.indices.alias.IndicesAliasesRequest;
|
| 30 | +import org.opensearch.action.admin.indices.create.CreateIndexRequest; |
30 | 31 | import org.opensearch.action.fieldcaps.FieldCapabilitiesRequest;
|
31 | 32 | import org.opensearch.action.fieldcaps.FieldCapabilitiesResponse;
|
32 | 33 | import org.opensearch.action.get.GetRequest;
|
|
43 | 44 | import org.opensearch.action.search.SearchScrollRequest;
|
44 | 45 | import org.opensearch.client.Client;
|
45 | 46 | import org.opensearch.client.RestHighLevelClient;
|
| 47 | +import org.opensearch.index.mapper.SourceFieldMapper; |
| 48 | +import org.opensearch.index.mapper.size.SizeFieldMapper; |
| 49 | +import org.opensearch.index.query.MatchAllQueryBuilder; |
46 | 50 | import org.opensearch.index.query.QueryBuilder;
|
47 | 51 | import org.opensearch.index.query.QueryBuilders;
|
| 52 | +import org.opensearch.plugin.mapper.MapperSizePlugin; |
48 | 53 | import org.opensearch.search.aggregations.Aggregation;
|
49 | 54 | import org.opensearch.search.aggregations.metrics.ParsedAvg;
|
| 55 | +import org.opensearch.search.builder.SearchSourceBuilder; |
50 | 56 | import org.opensearch.search.sort.SortOrder;
|
51 | 57 | import org.opensearch.test.framework.TestSecurityConfig;
|
52 | 58 | import org.opensearch.test.framework.cluster.ClusterManager;
|
|
55 | 61 |
|
56 | 62 | import static org.hamcrest.MatcherAssert.assertThat;
|
57 | 63 | import static org.hamcrest.Matchers.allOf;
|
| 64 | +import static org.hamcrest.Matchers.containsString; |
58 | 65 | import static org.hamcrest.Matchers.everyItem;
|
59 | 66 | import static org.hamcrest.Matchers.greaterThan;
|
60 | 67 | import static org.hamcrest.Matchers.instanceOf;
|
|
94 | 101 | import static org.opensearch.test.framework.matcher.SearchResponseMatchers.isSuccessfulSearchResponse;
|
95 | 102 | import static org.opensearch.test.framework.matcher.SearchResponseMatchers.numberOfTotalHitsIsEqualTo;
|
96 | 103 | import static org.opensearch.test.framework.matcher.SearchResponseMatchers.searchHitContainsFieldWithValue;
|
| 104 | +import static org.opensearch.test.framework.matcher.SearchResponseMatchers.searchHitDoesContainField; |
97 | 105 | import static org.opensearch.test.framework.matcher.SearchResponseMatchers.searchHitDoesNotContainField;
|
98 | 106 | import static org.opensearch.test.framework.matcher.SearchResponseMatchers.searchHitsContainDocumentWithId;
|
99 | 107 |
|
@@ -212,6 +220,7 @@ public class FlsAndFieldMaskingTests {
|
212 | 220 | .nodeSettings(
|
213 | 221 | Map.of("plugins.security.restapi.roles_enabled", List.of("user_" + ADMIN_USER.getName() + "__" + ALL_ACCESS.getName()))
|
214 | 222 | )
|
| 223 | + .plugin(MapperSizePlugin.class) |
215 | 224 | .authc(AUTHC_HTTPBASIC_INTERNAL)
|
216 | 225 | .users(
|
217 | 226 | ADMIN_USER,
|
@@ -426,6 +435,10 @@ public void flsEnabledFieldsAreHiddenForNormalUsers() throws IOException {
|
426 | 435 |
|
427 | 436 | private static List<String> createIndexWithDocs(String indexName, Song... songs) {
|
428 | 437 | try (Client client = cluster.getInternalNodeClient()) {
|
| 438 | + client.admin() |
| 439 | + .indices() |
| 440 | + .create(new CreateIndexRequest(indexName).mapping(Map.of("_size", Map.of("enabled", true)))) |
| 441 | + .actionGet(); |
429 | 442 | return Stream.of(songs).map(song -> {
|
430 | 443 | IndexResponse response = client.index(new IndexRequest(indexName).setRefreshPolicy(IMMEDIATE).source(song.asMap()))
|
431 | 444 | .actionGet();
|
@@ -469,6 +482,14 @@ private static void assertSearchHitsDoNotContainField(SearchResponse response, S
|
469 | 482 | .forEach(index -> assertThat(response, searchHitDoesNotContainField(index, excludedField)));
|
470 | 483 | }
|
471 | 484 |
|
| 485 | + private static void assertSearchHitsDoContainField(SearchResponse response, String includedField) { |
| 486 | + assertThat(response, isSuccessfulSearchResponse()); |
| 487 | + assertThat(response.getHits().getHits().length, greaterThan(0)); |
| 488 | + IntStream.range(0, response.getHits().getHits().length) |
| 489 | + .boxed() |
| 490 | + .forEach(index -> assertThat(response, searchHitDoesContainField(index, includedField))); |
| 491 | + } |
| 492 | + |
472 | 493 | @Test
|
473 | 494 | public void searchForDocuments() throws IOException {
|
474 | 495 | // FIELD MASKING
|
@@ -811,4 +832,28 @@ public void getFieldCapabilities() throws IOException {
|
811 | 832 | }
|
812 | 833 | }
|
813 | 834 |
|
| 835 | + @Test |
| 836 | + public void flsWithIncludesRulesIncludesFieldMappersFromPlugins() throws IOException { |
| 837 | + String indexName = "fls_includes_index"; |
| 838 | + TestSecurityConfig.Role userRole = new TestSecurityConfig.Role("fls_include_stars_reader").clusterPermissions( |
| 839 | + "cluster_composite_ops_ro" |
| 840 | + ).indexPermissions("read").fls(FIELD_STARS).on("*"); |
| 841 | + TestSecurityConfig.User user = createUserWithRole("fls_includes_user", userRole); |
| 842 | + List<String> docIds = createIndexWithDocs(indexName, SONGS[0], SONGS[1]); |
| 843 | + |
| 844 | + try (RestHighLevelClient restHighLevelClient = cluster.getRestHighLevelClient(user)) { |
| 845 | + SearchRequest searchRequest = new SearchRequest(indexName); |
| 846 | + SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder(); |
| 847 | + MatchAllQueryBuilder matchAllQueryBuilder = QueryBuilders.matchAllQuery(); |
| 848 | + searchSourceBuilder.storedFields(List.of(SizeFieldMapper.NAME, SourceFieldMapper.NAME)); |
| 849 | + searchSourceBuilder.query(matchAllQueryBuilder); |
| 850 | + searchRequest.source(searchSourceBuilder); |
| 851 | + SearchResponse searchResponse = restHighLevelClient.search(searchRequest, DEFAULT); |
| 852 | + |
| 853 | + assertSearchHitsDoContainField(searchResponse, FIELD_STARS); |
| 854 | + assertThat(searchResponse.toString(), containsString(SizeFieldMapper.NAME)); |
| 855 | + assertSearchHitsDoNotContainField(searchResponse, FIELD_ARTIST); |
| 856 | + } |
| 857 | + } |
| 858 | + |
814 | 859 | }
|
0 commit comments