2626import org .elasticsearch .test .cluster .ElasticsearchCluster ;
2727import org .elasticsearch .test .cluster .FeatureFlag ;
2828import org .elasticsearch .test .rest .ESRestTestCase ;
29+ import org .elasticsearch .test .rest .ObjectPath ;
2930import org .elasticsearch .xcontent .json .JsonXContent ;
3031import org .elasticsearch .xpack .core .security .user .User ;
3132import org .elasticsearch .xpack .security .SecurityOnTrialLicenseRestTestCase ;
4142import static org .hamcrest .Matchers .containsInAnyOrder ;
4243import static org .hamcrest .Matchers .equalTo ;
4344import static org .hamcrest .Matchers .hasItem ;
45+ import static org .hamcrest .Matchers .is ;
4446
4547public class FailureStoreSecurityRestIT extends ESRestTestCase {
4648
@@ -63,6 +65,8 @@ protected Settings restAdminSettings() {
6365 return Settings .builder ().put (ThreadContext .PREFIX + ".Authorization" , token ).build ();
6466 }
6567
68+ private static final String ASYNC_SEARCH_TIMEOUT = "30s" ;
69+
6670 private static final String DATA_ACCESS_USER = "data_access_user" ;
6771 private static final String STAR_READ_ONLY_USER = "star_read_only_user" ;
6872 private static final String FAILURE_STORE_ACCESS_USER = "failure_store_access_user" ;
@@ -794,7 +798,7 @@ public void testFailureStoreAccess() throws Exception {
794798 }
795799 }
796800 {
797- Search request = new Search ("*::failures,*" );
801+ var request = new Search ("*::failures,*" );
798802 for (var user : users ) {
799803 switch (user ) {
800804 case FAILURE_STORE_ACCESS_USER :
@@ -852,11 +856,28 @@ private void expect(String user, Search search, int statusCode) {
852856 }
853857
854858 private void expect (String user , Search search , String ... docIds ) throws Exception {
855- expect (user , search , response -> expectDocIds (response , docIds ));
859+ expectSearch (user , search .toSearchRequest (), response -> expectDocIds (response , docIds ));
860+ expectAsyncSearch (user , search .toAsyncSearchRequest (), docIds );
861+ }
862+
863+ @ SuppressWarnings ("unchecked" )
864+ private void expectAsyncSearch (String user , Request request , String ... docIds ) throws IOException {
865+ Response response = performRequest (user , request );
866+ assertOK (response );
867+ ObjectPath resp = ObjectPath .createFromResponse (response );
868+ Boolean isRunning = resp .evaluate ("is_running" );
869+ Boolean isPartial = resp .evaluate ("is_partial" );
870+ assertThat (isRunning , is (false ));
871+ assertThat (isPartial , is (false ));
872+
873+ List <Object > hits = resp .evaluate ("response.hits.hits" );
874+ List <String > actual = hits .stream ().map (h -> (String ) ((Map <String , Object >) h ).get ("_id" )).toList ();
875+
876+ assertThat (actual , containsInAnyOrder (docIds ));
856877 }
857878
858- private void expect (String user , Search search , ThrowingConsumer <Response > consumer ) throws Exception {
859- consumer .accept (performRequest (user , search . toSearchRequest () ));
879+ private void expectSearch (String user , Request request , ThrowingConsumer <Response > consumer ) throws Exception {
880+ consumer .accept (performRequest (user , request ));
860881 }
861882
862883 private record Search (String searchTarget , String pathParamString ) {
@@ -869,11 +890,13 @@ Request toSearchRequest() {
869890 }
870891
871892 Request toAsyncSearchRequest () {
872- return new Request ("POST" , Strings .format ("/%s/_async_search%s" , searchTarget , pathParamString ));
893+ var pathParam = pathParamString .isEmpty ()
894+ ? "?wait_for_completion_timeout=" + ASYNC_SEARCH_TIMEOUT
895+ : pathParamString + "&wait_for_completion_timeout=" + ASYNC_SEARCH_TIMEOUT ;
896+ return new Request ("POST" , Strings .format ("/%s/_async_search%s" , searchTarget , pathParam ));
873897 }
874898 }
875899
876- @ SuppressWarnings ("unchecked" )
877900 private static void expectDocIds (Response response , String ... docIds ) throws IOException {
878901 assertOK (response );
879902 final SearchResponse searchResponse = SearchResponseUtils .parseSearchResponse (responseAsParser (response ));
0 commit comments