diff --git a/CHANGELOG.md b/CHANGELOG.md index e4572068b8..c80d1a5252 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -128,6 +128,7 @@ Inspired from [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) - Fix AwsSdk2TransportOptions.responseCompression ([#322](https://github.com/opensearch-project/opensearch-java/pull/322)) - Fix missing Highlight and SourceConfig in the MultisearchBody ([#442](https://github.com/opensearch-project/opensearch-java/pull/442)) - Fix parsing /_alias error response for not existing alias ([#476](https://github.com/opensearch-project/opensearch-java/pull/476)) +- Fix catching JsonParsingException ([#494](https://github.com/opensearch-project/opensearch-java/issues/494)) - Fix StoryStats numeric value out of range of int ([#489](https://github.com/opensearch-project/opensearch-java/pull/489)) ### Security diff --git a/java-client/src/main/java/org/opensearch/client/transport/rest_client/RestClientTransport.java b/java-client/src/main/java/org/opensearch/client/transport/rest_client/RestClientTransport.java index 336392be3f..c70845cf83 100644 --- a/java-client/src/main/java/org/opensearch/client/transport/rest_client/RestClientTransport.java +++ b/java-client/src/main/java/org/opensearch/client/transport/rest_client/RestClientTransport.java @@ -32,6 +32,7 @@ package org.opensearch.client.transport.rest_client; +import org.apache.hc.core5.http.HttpStatus; import org.opensearch.client.opensearch._types.OpenSearchException; import org.opensearch.client.opensearch._types.ErrorResponse; import org.opensearch.client.json.JsonpDeserializer; @@ -246,7 +247,11 @@ private ResponseT getHighLevelResponse( try { int statusCode = clientResp.getStatusLine().getStatusCode(); - if (endpoint.isError(statusCode)) { + if (statusCode == HttpStatus.SC_FORBIDDEN) { + throw new TransportException("Forbidden access", new ResponseException(clientResp)); + } else if (statusCode == HttpStatus.SC_UNAUTHORIZED) { + throw new TransportException("Unauthorized access", new ResponseException(clientResp)); + } else if (endpoint.isError(statusCode)) { JsonpDeserializer errorDeserializer = endpoint.errorDeserializer(statusCode); if (errorDeserializer == null) { throw new TransportException( diff --git a/java-client/src/test/java/org/opensearch/client/opensearch/integTest/restclient/RequestIT.java b/java-client/src/test/java/org/opensearch/client/opensearch/integTest/restclient/RequestIT.java index 4c987b740d..8fa2675aab 100644 --- a/java-client/src/test/java/org/opensearch/client/opensearch/integTest/restclient/RequestIT.java +++ b/java-client/src/test/java/org/opensearch/client/opensearch/integTest/restclient/RequestIT.java @@ -9,17 +9,104 @@ package org.opensearch.client.opensearch.integTest.restclient; import java.io.IOException; +import java.util.Optional; +import org.apache.hc.client5.http.auth.AuthScope; +import org.apache.hc.client5.http.auth.UsernamePasswordCredentials; +import org.apache.hc.client5.http.impl.auth.BasicCredentialsProvider; +import org.apache.hc.client5.http.impl.nio.PoolingAsyncClientConnectionManager; +import org.apache.hc.client5.http.impl.nio.PoolingAsyncClientConnectionManagerBuilder; +import org.apache.hc.client5.http.ssl.ClientTlsStrategyBuilder; +import org.apache.hc.client5.http.ssl.NoopHostnameVerifier; import org.apache.hc.core5.http.HttpHost; +import org.apache.hc.core5.http.nio.ssl.TlsStrategy; +import org.apache.hc.core5.reactor.ssl.TlsDetails; +import org.apache.hc.core5.ssl.SSLContextBuilder; +import org.junit.Assume; +import org.junit.Test; +import org.opensearch.client.RestClient; +import org.opensearch.client.json.JsonData; import org.opensearch.client.json.jackson.JacksonJsonpMapper; +import org.opensearch.client.opensearch.OpenSearchClient; +import org.opensearch.client.opensearch.core.SearchRequest; +import org.opensearch.client.opensearch.indices.CreateIndexRequest; +import org.opensearch.client.opensearch.indices.IndexSettings; import org.opensearch.client.opensearch.integTest.AbstractRequestIT; import org.opensearch.client.transport.OpenSearchTransport; +import org.opensearch.client.transport.TransportException; import org.opensearch.client.transport.rest_client.RestClientTransport; import org.opensearch.common.settings.Settings; +import static org.hamcrest.CoreMatchers.equalTo; + public class RequestIT extends AbstractRequestIT { @Override public OpenSearchTransport buildTransport(Settings settings, HttpHost[] hosts) throws IOException { return new RestClientTransport(buildClient(settings, hosts), new JacksonJsonpMapper()); } + + @Test + public void testUnauthorized() throws Exception { + // The security plugin is required + Assume.assumeThat(isHttps(), equalTo(true)); + + final String userName = Optional.ofNullable(System.getProperty("user")).orElse("admin"); + final String wrongPassword = Optional.ofNullable(System.getProperty("password")).orElse("admin") + + "wrong"; + + final BasicCredentialsProvider credentialsProvider = new BasicCredentialsProvider(); + credentialsProvider.setCredentials(new AuthScope(getClusterHosts().get(0)), + new UsernamePasswordCredentials(userName, wrongPassword.toCharArray())); + + final RestClient restClient = RestClient + .builder(getClusterHosts().toArray(new HttpHost[0])) + .setHttpClientConfigCallback(httpClientBuilder -> { + try { + final TlsStrategy tlsStrategy = ClientTlsStrategyBuilder + .create() + .setSslContext( + SSLContextBuilder.create().loadTrustMaterial( + null, (chains, authType) -> true).build()) + .setHostnameVerifier(NoopHostnameVerifier.INSTANCE) + .setTlsDetailsFactory( + sslEngine -> new TlsDetails( + sslEngine.getSession(), sslEngine.getApplicationProtocol())) + .build(); + + final PoolingAsyncClientConnectionManager connectionManager = + PoolingAsyncClientConnectionManagerBuilder.create() + .setTlsStrategy(tlsStrategy) + .build(); + + return httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider) + .setConnectionManager(connectionManager); + } catch (Exception e) { + throw new RuntimeException(e); + } + }) + .build(); + + final RestClientTransport transport = new RestClientTransport(restClient, new JacksonJsonpMapper()); + final OpenSearchClient client = new OpenSearchClient(transport); + final TransportException transportException = assertThrows(TransportException.class, + () -> client.cluster().getSettings()); + assertEquals("Unauthorized access", transportException.getMessage()); + restClient.close(); + } + + @Test + public void testForbidden() throws Exception { + final OpenSearchClient openSearchClient = javaClient(); + final String testIndex = "test-index"; + final CreateIndexRequest createIndexRequest = new CreateIndexRequest.Builder() + .index(testIndex) + .settings(new IndexSettings.Builder() + .blocksRead(true).build()) + .build(); + openSearchClient.indices().create(createIndexRequest); + final SearchRequest searchRequest = new SearchRequest.Builder().index(testIndex).build(); + final TransportException transportException = assertThrows(TransportException.class, + () -> openSearchClient.search(searchRequest, JsonData.class)); + assertEquals("Forbidden access", transportException.getMessage()); + } }