1616import java .util .StringJoiner ;
1717
1818import org .hamcrest .Matcher ;
19+ import org .junit .Test ;
1920
2021import org .opensearch .common .CheckedSupplier ;
2122import org .opensearch .core .xcontent .ToXContentObject ;
22- import org .opensearch .test .framework .cluster .LocalCluster ;
2323import org .opensearch .test .framework .cluster .TestRestClient ;
2424
2525import com .nimbusds .jose .util .Pair ;
2626
2727import static org .hamcrest .CoreMatchers .is ;
2828import static org .hamcrest .CoreMatchers .not ;
2929import static org .hamcrest .MatcherAssert .assertThat ;
30+ import static org .hamcrest .Matchers .containsString ;
3031import static org .hamcrest .Matchers .equalTo ;
3132import static org .hamcrest .Matchers .oneOf ;
3233import static org .opensearch .security .api .PatchPayloadHelper .addOp ;
3334import static org .opensearch .security .api .PatchPayloadHelper .patch ;
3435import static org .opensearch .security .api .PatchPayloadHelper .removeOp ;
3536import static org .opensearch .security .api .PatchPayloadHelper .replaceOp ;
3637import static org .opensearch .security .support .ConfigConstants .SECURITY_RESTAPI_ADMIN_ENABLED ;
37- import static org .opensearch .test .framework .matcher .RestMatchers .isBadRequest ;
38- import static org .opensearch .test .framework .matcher .RestMatchers .isCreated ;
39- import static org .opensearch .test .framework .matcher .RestMatchers .isForbidden ;
40- import static org .opensearch .test .framework .matcher .RestMatchers .isNotFound ;
41- import static org .opensearch .test .framework .matcher .RestMatchers .isOk ;
4238
4339public abstract class AbstractConfigEntityApiIntegrationTest extends AbstractApiIntegrationTest {
4440
45- protected static LocalCluster .Builder clusterBuilder () {
46- return AbstractApiIntegrationTest .clusterBuilder ().nodeSetting (SECURITY_RESTAPI_ADMIN_ENABLED , true );
41+ static {
42+ testSecurityConfig .withRestAdminUser (REST_ADMIN_USER , allRestAdminPermissions ());
43+ }
44+
45+ @ Override
46+ protected Map <String , Object > getClusterSettings () {
47+ Map <String , Object > clusterSettings = super .getClusterSettings ();
48+ clusterSettings .put (SECURITY_RESTAPI_ADMIN_ENABLED , true );
49+ return clusterSettings ;
4750 }
4851
4952 interface TestDescriptor {
@@ -96,24 +99,26 @@ protected String apiPath(String... paths) {
9699 return fullPath .toString ();
97100 }
98101
99- public void forbiddenForRegularUsers (LocalCluster localCluster ) throws Exception {
100- try (TestRestClient client = localCluster .getRestClient (NEW_USER )) {
101- assertThat (client .putJson (apiPath ("some_entity" ), EMPTY_BODY ), isForbidden ());
102- assertThat (client .get (apiPath ()), isForbidden ());
103- assertThat (client .get (apiPath ("some_entity" )), isForbidden ());
104- assertThat (client .putJson (apiPath ("some_entity" ), EMPTY_BODY ), isForbidden ());
105- assertThat (client .patch (apiPath (), EMPTY_BODY ), isForbidden ());
106- assertThat (client .patch (apiPath ("some_entity" ), EMPTY_BODY ), isForbidden ());
107- assertThat (client .delete (apiPath ("some_entity" )), isForbidden ());
108- }
102+ @ Test
103+ public void forbiddenForRegularUsers () throws Exception {
104+ withUser (NEW_USER , client -> {
105+ forbidden (() -> client .putJson (apiPath ("some_entity" ), EMPTY_BODY ));
106+ forbidden (() -> client .get (apiPath ()));
107+ forbidden (() -> client .get (apiPath ("some_entity" )));
108+ forbidden (() -> client .putJson (apiPath ("some_entity" ), EMPTY_BODY ));
109+ forbidden (() -> client .patch (apiPath (), EMPTY_BODY ));
110+ forbidden (() -> client .patch (apiPath ("some_entity" ), EMPTY_BODY ));
111+ forbidden (() -> client .delete (apiPath ("some_entity" )));
112+ });
109113 }
110114
111- public void availableForAdminUser (LocalCluster localCluster ) throws Exception {
112- final var entitiesNames = predefinedHiddenAndReservedConfigEntities (localCluster );
115+ @ Test
116+ public void availableForAdminUser () throws Exception {
117+ final var entitiesNames = predefinedHiddenAndReservedConfigEntities ();
113118 final var hiddenEntityName = entitiesNames .getLeft ();
114119 final var reservedEntityName = entitiesNames .getRight ();
115120 // can't see hidden resources
116- try ( TestRestClient client = localCluster . getRestClient ( ADMIN_USER )) {
121+ withUser ( ADMIN_USER_NAME , client -> {
117122 verifyNoHiddenEntities (() -> client .get (apiPath ()));
118123 creationOfReadOnlyEntityForbidden (
119124 randomAsciiAlphanumOfLength (10 ),
@@ -126,28 +131,35 @@ public void availableForAdminUser(LocalCluster localCluster) throws Exception {
126131 verifyUpdateAndDeleteReservedConfigEntityForbidden (reservedEntityName , client );
127132 verifyCrudOperations (null , null , client );
128133 verifyBadRequestOperations (client );
129- }
134+ });
130135 }
131136
132- Pair <String , String > predefinedHiddenAndReservedConfigEntities (LocalCluster localCluster ) throws Exception {
137+ Pair <String , String > predefinedHiddenAndReservedConfigEntities () throws Exception {
133138 final var hiddenEntityName = randomAsciiAlphanumOfLength (10 );
134139 final var reservedEntityName = randomAsciiAlphanumOfLength (10 );
135- try (TestRestClient client = localCluster .getAdminCertRestClient ()) {
136- assertThat (client .putJson (apiPath (hiddenEntityName ), testDescriptor .hiddenEntityPayload ()), isCreated ());
137- assertThat (client .putJson (apiPath (reservedEntityName ), testDescriptor .reservedEntityPayload ()), isCreated ());
138- }
140+ withUser (
141+ ADMIN_USER_NAME ,
142+ localCluster .getAdminCertificate (),
143+ client -> created (() -> client .putJson (apiPath (hiddenEntityName ), testDescriptor .hiddenEntityPayload ()))
144+ );
145+ withUser (
146+ ADMIN_USER_NAME ,
147+ localCluster .getAdminCertificate (),
148+ client -> created (() -> client .putJson (apiPath (reservedEntityName ), testDescriptor .reservedEntityPayload ()))
149+ );
139150 return Pair .of (hiddenEntityName , reservedEntityName );
140151 }
141152
142- public void availableForTLSAdminUser (LocalCluster localCluster ) throws Exception {
143- try (TestRestClient client = localCluster .getAdminCertRestClient ()) {
144- availableForSuperAdminUser (client );
145- }
153+ @ Test
154+ public void availableForTLSAdminUser () throws Exception {
155+ withUser (ADMIN_USER_NAME , localCluster .getAdminCertificate (), this ::availableForSuperAdminUser );
146156 }
147157
148- public void availableForRESTAdminUser (LocalCluster localCluster ) throws Exception {
149- try (TestRestClient client = localCluster .getRestClient (REST_ADMIN_USER )) {
150- availableForSuperAdminUser (client );
158+ @ Test
159+ public void availableForRESTAdminUser () throws Exception {
160+ withUser (REST_ADMIN_USER , this ::availableForSuperAdminUser );
161+ if (testDescriptor .restAdminLimitedUser ().isPresent ()) {
162+ withUser (testDescriptor .restAdminLimitedUser ().get (), this ::availableForSuperAdminUser );
151163 }
152164 }
153165
@@ -166,9 +178,7 @@ void availableForSuperAdminUser(final TestRestClient client) throws Exception {
166178 }
167179
168180 void verifyNoHiddenEntities (final CheckedSupplier <TestRestClient .HttpResponse , Exception > endpointCallback ) throws Exception {
169- final var resp = endpointCallback .get ();
170- assertThat (resp , isOk ());
171- final var body = resp .bodyAsJsonNode ();
181+ final var body = ok (endpointCallback ).bodyAsJsonNode ();
172182 final var pretty = body .toPrettyString ();
173183 final var it = body .elements ();
174184 while (it .hasNext ()) {
@@ -180,11 +190,11 @@ void verifyNoHiddenEntities(final CheckedSupplier<TestRestClient.HttpResponse, E
180190 void creationOfReadOnlyEntityForbidden (final String entityName , final TestRestClient client , final ToXContentObject ... entities )
181191 throws Exception {
182192 for (final var configEntity : entities ) {
183- final var resp = client . putJson ( apiPath ( entityName ), configEntity );
184- assertThat ( resp , isBadRequest ());
185- assertInvalidKeys ( resp , is (oneOf ("static" , "hidden" , "reserved" )));
186- final var resp2 = client . patch ( apiPath (), patch ( addOp ( randomAsciiAlphanumOfLength ( 10 ), configEntity )) );
187- assertThat ( resp2 , isBadRequest ( ));
193+ assertInvalidKeys (
194+ badRequest (() -> client . putJson ( apiPath ( entityName ), configEntity )),
195+ is (oneOf ("static" , "hidden" , "reserved" ))
196+ );
197+ badRequest (() -> client . patch ( apiPath (), patch ( addOp ( randomAsciiAlphanumOfLength ( 10 ), configEntity )) ));
188198 }
189199 }
190200
@@ -212,60 +222,54 @@ void assertWrongDataType(final TestRestClient.HttpResponse response, final Map<S
212222 assertThat (response .getBody (), response .getTextFromJsonBody ("/" + p .getKey ()), is (p .getValue ()));
213223 }
214224
225+ void assertSpecifyOneOf (final TestRestClient .HttpResponse response , final String expectedSpecifyOneOfKeys ) {
226+ assertThat (response .getBody (), response .getTextFromJsonBody ("/status" ), is ("error" ));
227+ assertThat (response .getBody (), response .getTextFromJsonBody ("/reason" ), equalTo ("Invalid configuration" ));
228+ assertThat (response .getBody (), response .getTextFromJsonBody ("/specify_one_of/keys" ), containsString (expectedSpecifyOneOfKeys ));
229+ }
230+
231+ void assertMissingMandatoryKeys (final TestRestClient .HttpResponse response , final String expectedKeys ) {
232+ assertThat (response .getBody (), response .getTextFromJsonBody ("/status" ), is ("error" ));
233+ assertThat (response .getBody (), response .getTextFromJsonBody ("/reason" ), equalTo ("Invalid configuration" ));
234+ assertThat (response .getBody (), response .getTextFromJsonBody ("/missing_mandatory_keys/keys" ), containsString (expectedKeys ));
235+ }
236+
215237 void verifyUpdateAndDeleteHiddenConfigEntityForbidden (final String hiddenEntityName , final TestRestClient client ) throws Exception {
216238 final var expectedErrorMessage = "Resource '" + hiddenEntityName + "' is not available." ;
217- assertThat (
218- client .putJson (apiPath (hiddenEntityName ), testDescriptor .entityPayload ()),
219- isNotFound ().withAttribute ("/message" , expectedErrorMessage )
220- );
221- assertThat (
222- client .patch (
239+ notFound (() -> client .putJson (apiPath (hiddenEntityName ), testDescriptor .entityPayload ()), expectedErrorMessage );
240+ notFound (
241+ () -> client .patch (
223242 apiPath (hiddenEntityName ),
224243 patch (replaceOp (testDescriptor .entityJsonProperty (), testDescriptor .jsonPropertyPayload ()))
225244 ),
226- isNotFound (). withAttribute ( "/message" , expectedErrorMessage )
245+ expectedErrorMessage
227246 );
228- assertThat (
229- client .patch (apiPath (), patch (replaceOp (hiddenEntityName , testDescriptor .entityPayload ()))),
230- isNotFound ().withAttribute ("/message" , expectedErrorMessage )
231- );
232- assertThat (
233- client .patch (apiPath (hiddenEntityName ), patch (removeOp (testDescriptor .entityJsonProperty ()))),
234- isNotFound ().withAttribute ("/message" , expectedErrorMessage )
235- );
236- assertThat (
237- client .patch (apiPath (), patch (removeOp (hiddenEntityName ))),
238- isNotFound ().withAttribute ("/message" , expectedErrorMessage )
239- );
240- assertThat (client .delete (apiPath (hiddenEntityName )), isNotFound ().withAttribute ("/message" , expectedErrorMessage ));
247+ notFound (() -> client .patch (apiPath (), patch (replaceOp (hiddenEntityName , testDescriptor .entityPayload ()))), expectedErrorMessage );
248+ notFound (() -> client .patch (apiPath (hiddenEntityName ), patch (removeOp (testDescriptor .entityJsonProperty ()))), expectedErrorMessage );
249+ notFound (() -> client .patch (apiPath (), patch (removeOp (hiddenEntityName ))), expectedErrorMessage );
250+ notFound (() -> client .delete (apiPath (hiddenEntityName )), expectedErrorMessage );
241251 }
242252
243253 void verifyUpdateAndDeleteReservedConfigEntityForbidden (final String reservedEntityName , final TestRestClient client ) throws Exception {
244254 final var expectedErrorMessage = "Resource '" + reservedEntityName + "' is reserved." ;
245- assertThat (
246- client .putJson (apiPath (reservedEntityName ), testDescriptor .entityPayload ()),
247- isForbidden ().withAttribute ("/message" , expectedErrorMessage )
248- );
249- assertThat (
250- client .patch (
255+ forbidden (() -> client .putJson (apiPath (reservedEntityName ), testDescriptor .entityPayload ()), expectedErrorMessage );
256+ forbidden (
257+ () -> client .patch (
251258 apiPath (reservedEntityName ),
252259 patch (replaceOp (testDescriptor .entityJsonProperty (), testDescriptor .entityJsonProperty ()))
253260 ),
254- isForbidden (). withAttribute ( "/message" , expectedErrorMessage )
261+ expectedErrorMessage
255262 );
256- assertThat (
257- client .patch (apiPath (), patch (replaceOp (reservedEntityName , testDescriptor .entityPayload ()))),
258- isForbidden ().withAttribute ("/message" , expectedErrorMessage )
259- );
260- assertThat (
261- client .patch (apiPath (), patch (removeOp (reservedEntityName ))),
262- isForbidden ().withAttribute ("/message" , expectedErrorMessage )
263+ forbidden (
264+ () -> client .patch (apiPath (), patch (replaceOp (reservedEntityName , testDescriptor .entityPayload ()))),
265+ expectedErrorMessage
263266 );
264- assertThat (
265- client .patch (apiPath (reservedEntityName ), patch (removeOp (testDescriptor .entityJsonProperty ()))),
266- isForbidden ().withAttribute ("/message" , expectedErrorMessage )
267+ forbidden (() -> client .patch (apiPath (), patch (removeOp (reservedEntityName ))), expectedErrorMessage );
268+ forbidden (
269+ () -> client .patch (apiPath (reservedEntityName ), patch (removeOp (testDescriptor .entityJsonProperty ()))),
270+ expectedErrorMessage
267271 );
268- assertThat ( client .delete (apiPath (reservedEntityName )), isForbidden (). withAttribute ( "/message" , expectedErrorMessage ) );
272+ forbidden (() -> client .delete (apiPath (reservedEntityName )), expectedErrorMessage );
269273 }
270274
271275 void forbiddenToCreateEntityWithRestAdminPermissions (final TestRestClient client ) throws Exception {}
0 commit comments