1414import java .util .ArrayList ;
1515import java .util .Collection ;
1616import java .util .List ;
17+ import java .util .function .Function ;
18+ import java .util .function .Supplier ;
1719
1820import com .google .common .collect .ImmutableList ;
21+ import org .junit .AfterClass ;
1922import org .junit .ClassRule ;
2023import org .junit .Test ;
2124import org .junit .runner .RunWith ;
2730import org .opensearch .test .framework .TestSecurityConfig ;
2831import org .opensearch .test .framework .cluster .LocalCluster ;
2932import org .opensearch .test .framework .cluster .TestRestClient ;
33+ import org .slf4j .Logger ;
34+ import org .slf4j .LoggerFactory ;
3035
3136import static org .hamcrest .MatcherAssert .assertThat ;
3237import static org .hamcrest .Matchers .containsString ;
@@ -204,18 +209,27 @@ public class IndexAuthorizationReadOnlyIntTests {
204209 UNLIMITED_USER ,
205210 SUPER_UNLIMITED_USER
206211 );
212+ private static final Logger log = LoggerFactory .getLogger (IndexAuthorizationReadOnlyIntTests .class );
213+
214+ static LocalCluster .Builder clusterBuilder () {
215+ return new LocalCluster .Builder ().singleNode ()
216+ .anonymousAuth (false )
217+ .authc (AUTHC_HTTPBASIC_INTERNAL )
218+ .users (USERS )//
219+ .indices (index_a1 , index_a2 , index_a3 , index_b1 , index_b2 , index_b3 , index_c1 , index_hidden , index_hidden_dot )//
220+ .aliases (alias_ab1 , alias_c1 );
221+ }
207222
208- @ ClassRule
209- public static LocalCluster cluster = new LocalCluster .Builder ().singleNode ()
210- .anonymousAuth (false )
211- .authc (AUTHC_HTTPBASIC_INTERNAL )
212- .users (USERS )//
213- .indices (index_a1 , index_a2 , index_a3 , index_b1 , index_b2 , index_b3 , index_c1 , index_hidden , index_hidden_dot )//
214- .aliases (alias_ab1 , alias_c1 )//
215- .doNotFailOnForbidden (true )
216- .build ();
223+ @ AfterClass
224+ public static void stopClusters () {
225+ for (ClusterConfig clusterConfig : ClusterConfig .values ()) {
226+ clusterConfig .shutdown ();
227+ }
228+ }
217229
218230 final TestSecurityConfig .User user ;
231+ final LocalCluster cluster ;
232+ final ClusterConfig clusterConfig ;
219233
220234 @ Test
221235 public void search_noPattern () throws Exception {
@@ -234,7 +248,11 @@ public void search_noPattern() throws Exception {
234248 public void search_noPattern_noWildcards () throws Exception {
235249 try (TestRestClient restClient = cluster .getRestClient (user )) {
236250 TestRestClient .HttpResponse httpResponse = restClient .get ("/_search?size=1000&expand_wildcards=none" );
237- assertThat (httpResponse , containsExactly ().at ("hits.hits[*]._index" ).whenEmpty (200 ));
251+ if (user == UNLIMITED_USER || user == SUPER_UNLIMITED_USER ) {
252+ assertThat (httpResponse , isOk ());
253+ } else {
254+ assertThat (httpResponse , isForbidden ("/error/root_cause/0/reason" , "no permissions for [indices:data/read/search]" ));
255+ }
238256 }
239257 }
240258
@@ -268,7 +286,11 @@ public void search_all() throws Exception {
268286 public void search_all_noWildcards () throws Exception {
269287 try (TestRestClient restClient = cluster .getRestClient (user )) {
270288 TestRestClient .HttpResponse httpResponse = restClient .get ("_all/_search?size=1000&expand_wildcards=none" );
271- assertThat (httpResponse , containsExactly ().at ("hits.hits[*]._index" ).whenEmpty (200 ));
289+ if (user == UNLIMITED_USER || user == SUPER_UNLIMITED_USER ) {
290+ assertThat (httpResponse , isOk ());
291+ } else {
292+ assertThat (httpResponse , isForbidden ("/error/root_cause/0/reason" , "no permissions for [indices:data/read/search]" ));
293+ }
272294 }
273295 }
274296
@@ -311,7 +333,11 @@ public void search_wildcard() throws Exception {
311333 public void search_wildcard_noWildcards () throws Exception {
312334 try (TestRestClient restClient = cluster .getRestClient (user )) {
313335 TestRestClient .HttpResponse httpResponse = restClient .get ("*/_search?size=1000&expand_wildcards=none" );
314- assertThat (httpResponse , containsExactly ().at ("hits.hits[*]._index" ).whenEmpty (200 ));
336+ if (user == UNLIMITED_USER || user == SUPER_UNLIMITED_USER ) {
337+ assertThat (httpResponse , isOk ());
338+ } else {
339+ assertThat (httpResponse , isForbidden ("/error/root_cause/0/reason" , "no permissions for [indices:data/read/search]" ));
340+ }
315341 }
316342 }
317343
@@ -439,17 +465,14 @@ public void search_indexPattern_noWildcards() throws Exception {
439465 TestRestClient .HttpResponse httpResponse = restClient .get (
440466 "index_a*,index_b*/_search?size=1000&expand_wildcards=none&ignore_unavailable=true"
441467 );
442- assertThat (httpResponse , containsExactly ().at ("hits.hits[*]._index" ).but (user .indexMatcher ("search" )).whenEmpty (200 ));
443- }
444- }
445-
446- @ Test
447- public void search_indexPatternAndStatic_noWildcards () throws Exception {
448- try (TestRestClient restClient = cluster .getRestClient (user )) {
449- TestRestClient .HttpResponse httpResponse = restClient .get (
450- "index_a*,index_b1/_search?size=1000&expand_wildcards=none&ignore_unavailable=true"
451- );
452- assertThat (httpResponse , containsExactly (index_b1 ).at ("hits.hits[*]._index" ).but (user .indexMatcher ("search" )).whenEmpty (403 ));
468+ // We have to specify the users here explicitly because here we need to check privileges for the
469+ // non-existing (and invalidly named) indices "index_a*" and "index_b*". Only users with privileges for "index_a*"
470+ // and "index_b*" will get a ok response.
471+ if (user == LIMITED_USER_A || user == LIMITED_USER_B || user == LIMITED_USER_A_HIDDEN || user == UNLIMITED_USER || user == SUPER_UNLIMITED_USER ) {
472+ assertThat (httpResponse , isOk ());
473+ } else {
474+ assertThat (httpResponse , isForbidden ("" , "" ));
475+ }
453476 }
454477 }
455478
@@ -510,12 +533,18 @@ public void search_alias_pattern_negation() throws Exception {
510533 public void search_aliasAndIndex () throws Exception {
511534 try (TestRestClient restClient = cluster .getRestClient (user )) {
512535 TestRestClient .HttpResponse httpResponse = restClient .get ("alias_ab1,index_b2/_search?size=1000&ignore_unavailable=true" );
513- assertThat (
514- httpResponse ,
515- containsExactly (index_a1 , index_a2 , index_a3 , index_b1 , index_b2 ).at ("hits.hits[*]._index" )
516- .but (user .indexMatcher ("search" ))
517- .whenEmpty (403 )
518- );
536+ if (clusterConfig == ClusterConfig .LEGACY_PRIVILEGES_EVALUATION ) {
537+ // The legacy privilege evaluation with dnfof enabled can replace aliases by a sub-set of its member indices
538+ assertThat (
539+ httpResponse ,
540+ containsExactly (index_a1 , index_a2 , index_a3 , index_b1 , index_b2 ).at ("hits.hits[*]._index" )
541+ .but (user .indexMatcher ("search" ))
542+ .whenEmpty (403 )
543+ );
544+ } else {
545+ // The new privilege evaluation never replaces aliases
546+ if (user .indexMatcher ("search" ).covers (alias_ab1 ))
547+ }
519548 }
520549 }
521550
@@ -891,15 +920,6 @@ public void getAlias_aliasPattern() throws Exception {
891920 }
892921 }
893922
894- @ Test
895- public void getAlias_aliasPattern_noWildcards () throws Exception {
896- try (TestRestClient restClient = cluster .getRestClient (user )) {
897- TestRestClient .HttpResponse httpResponse = restClient .get ("_alias/alias_ab*?expand_wildcards=none" );
898- assertThat (httpResponse , isOk ());
899- assertThat (httpResponse .bodyAsJsonNode ().isEmpty (), equalTo (true ));
900- }
901- }
902-
903923 @ Test
904924 public void getAlias_mixed () throws Exception {
905925 try (TestRestClient restClient = cluster .getRestClient (user )) {
@@ -1043,7 +1063,7 @@ public void field_caps_indexPattern() throws Exception {
10431063 TestRestClient .HttpResponse httpResponse = restClient .get ("index_b*/_field_caps?fields=*" );
10441064 assertThat (
10451065 httpResponse ,
1046- containsExactly (index_b1 , index_b2 , index_b3 ).at ("indices" ).but (user .indexMatcher ("read" )).whenEmpty (403 )
1066+ containsExactly (index_b1 , index_b2 , index_b3 ).at ("indices" ).but (user .indexMatcher ("read" )).whenEmpty ( clusterConfig == ClusterConfig . NEXT_GEN_PRIVILEGES_EVALUATION ? 200 : 403 )
10471067 );
10481068 }
10491069 }
@@ -1155,19 +1175,60 @@ public void field_caps_indexPattern_minus() throws Exception {
11551175 }
11561176 }
11571177
1158- @ Parameterized .Parameters (name = "{1 }" )
1178+ @ Parameterized .Parameters (name = "{0}, {2 }" )
11591179 public static Collection <Object []> params () {
11601180 List <Object []> result = new ArrayList <>();
11611181
1162- for (TestSecurityConfig .User user : USERS ) {
1163- result .add (new Object [] { user , user .getDescription () });
1182+ for (ClusterConfig clusterConfig : ClusterConfig .values ()) {
1183+ for (TestSecurityConfig .User user : USERS ) {
1184+ result .add (new Object []{clusterConfig , user , user .getDescription ()});
1185+ }
11641186 }
1165-
11661187 return result ;
11671188 }
11681189
1169- public IndexAuthorizationReadOnlyIntTests (TestSecurityConfig .User user , String description ) throws Exception {
1190+ public IndexAuthorizationReadOnlyIntTests (ClusterConfig clusterConfig , TestSecurityConfig .User user , String description ) throws Exception {
11701191 this .user = user ;
1192+ this .cluster = clusterConfig .cluster ();
1193+ this .clusterConfig = clusterConfig ;
1194+ }
1195+
1196+ public enum ClusterConfig {
1197+ LEGACY_PRIVILEGES_EVALUATION ("legacy" , c -> c .doNotFailOnForbidden (true )),
1198+ NEXT_GEN_PRIVILEGES_EVALUATION ("next_gen" , c -> c .privilegesEvaluationType ("next_gen" ));
1199+
1200+ final String name ;
1201+ final Function <LocalCluster .Builder , LocalCluster .Builder > clusterConfiguration ;
1202+ private LocalCluster cluster ;
1203+
1204+ ClusterConfig (String name , Function <LocalCluster .Builder , LocalCluster .Builder > clusterConfiguration ) {
1205+ this .name = name ;
1206+ this .clusterConfiguration = clusterConfiguration ;
1207+ }
1208+
1209+ LocalCluster cluster () {
1210+ if (cluster == null ) {
1211+ cluster = this .clusterConfiguration .apply (clusterBuilder ()).build ();
1212+ cluster .before ();
1213+ }
1214+ return cluster ;
1215+ }
1216+
1217+ void shutdown () {
1218+ if (cluster != null ) {
1219+ try {
1220+ cluster .close ();
1221+ } catch (Exception e ) {
1222+ e .printStackTrace ();
1223+ }
1224+ cluster = null ;
1225+ }
1226+ }
1227+
1228+ @ Override
1229+ public String toString () {
1230+ return name ;
1231+ }
11711232 }
11721233
11731234}
0 commit comments