diff --git a/app/server/appsmith-plugins/elasticSearchPlugin/pom.xml b/app/server/appsmith-plugins/elasticSearchPlugin/pom.xml
index 05d637a03a..ec752dfe01 100644
--- a/app/server/appsmith-plugins/elasticSearchPlugin/pom.xml
+++ b/app/server/appsmith-plugins/elasticSearchPlugin/pom.xml
@@ -32,7 +32,7 @@
org.elasticsearch.client
elasticsearch-rest-client
- 7.9.2
+ 7.17.5
diff --git a/app/server/appsmith-plugins/elasticSearchPlugin/src/main/java/com/external/plugins/ElasticSearchPlugin.java b/app/server/appsmith-plugins/elasticSearchPlugin/src/main/java/com/external/plugins/ElasticSearchPlugin.java
index 06ccc82594..c1226ac650 100644
--- a/app/server/appsmith-plugins/elasticSearchPlugin/src/main/java/com/external/plugins/ElasticSearchPlugin.java
+++ b/app/server/appsmith-plugins/elasticSearchPlugin/src/main/java/com/external/plugins/ElasticSearchPlugin.java
@@ -23,6 +23,7 @@ import org.apache.http.entity.ContentType;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.message.BasicHeader;
import org.apache.http.nio.entity.NStringEntity;
+import org.eclipse.jgit.util.SystemReader;
import org.elasticsearch.client.Request;
import org.elasticsearch.client.Response;
import org.elasticsearch.client.RestClient;
@@ -45,6 +46,7 @@ import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
+import java.util.regex.Pattern;
import static com.appsmith.external.constants.ActionConstants.ACTION_CONFIGURATION_BODY;
import static com.appsmith.external.constants.ActionConstants.ACTION_CONFIGURATION_PATH;
@@ -61,6 +63,15 @@ public class ElasticSearchPlugin extends BasePlugin {
private final Scheduler scheduler = Schedulers.elastic();
+ public static final String esDatasourceNotFoundMessage = "The Page you are tyring to access does not exist";
+
+ public static final String esDatasourceUnauthorizedMessage = "Your Username or Password is not correct";
+
+ public static final String esDatasourceUnauthorizedPattern = ".*unauthorized.*";
+
+ public static final String esDatasourceNotFoundPattern = ".*(?:not.?found)|(?:refused)|(?:not.?known)|(?:timed?\\s?out).*";
+
+
@Override
public Mono execute(RestClient client,
DatasourceConfiguration datasourceConfiguration,
@@ -251,16 +262,32 @@ public class ElasticSearchPlugin extends BasePlugin {
if (client == null) {
return new DatasourceTestResult("Null client object to ElasticSearch.");
}
-
- // This HEAD request is to check if an index exists. It response with 200 if the index exists,
+ // This HEAD request is to check if the base of datasource exists. It responds with 200 if the index exists,
// 404 if it doesn't. We just check for either of these two.
// Ref: https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-exists.html
- Request request = new Request("HEAD", "/potentially-missing-index?local=true");
+ Request request = new Request("HEAD", "/");
final Response response;
try {
response = client.performRequest(request);
} catch (IOException e) {
+
+ /* since the 401, and 403 are registered as IOException, but for the given connection it
+ * in the current rest-client. We will figure out with matching patterns with regexes.
+ */
+
+ Pattern patternForUnauthorized = Pattern.compile(esDatasourceUnauthorizedPattern, Pattern.CASE_INSENSITIVE);
+ Pattern patterForNotFound = Pattern.compile(esDatasourceNotFoundPattern,Pattern.CASE_INSENSITIVE);
+
+ if (patternForUnauthorized.matcher(e.getMessage()).find()){
+ return new DatasourceTestResult(esDatasourceUnauthorizedMessage);
+ }
+
+ if (patterForNotFound.matcher(e.getMessage()).find()){
+ return new DatasourceTestResult(esDatasourceNotFoundMessage);
+ }
+
+
return new DatasourceTestResult("Error running HEAD request: " + e.getMessage());
}
@@ -271,8 +298,13 @@ public class ElasticSearchPlugin extends BasePlugin {
} catch (IOException e) {
log.warn("Error closing ElasticSearch client that was made for testing.", e);
}
+ // earlier it was 404 and 200, now it has been changed to just expect 200 status code
+ // here it checks if it is anything else than 200, even 404 is not allowed!
+ if (statusLine.getStatusCode() == 404){
+ return new DatasourceTestResult(esDatasourceNotFoundMessage);
+ }
- if (statusLine.getStatusCode() != 404 && statusLine.getStatusCode() != 200) {
+ if (statusLine.getStatusCode() != 200) {
return new DatasourceTestResult(
"Unexpected response from ElasticSearch: " + statusLine);
}
diff --git a/app/server/appsmith-plugins/elasticSearchPlugin/src/test/java/com/external/plugins/ElasticSearchPluginTest.java b/app/server/appsmith-plugins/elasticSearchPlugin/src/test/java/com/external/plugins/ElasticSearchPluginTest.java
index a2dadc3552..f25f711232 100755
--- a/app/server/appsmith-plugins/elasticSearchPlugin/src/test/java/com/external/plugins/ElasticSearchPluginTest.java
+++ b/app/server/appsmith-plugins/elasticSearchPlugin/src/test/java/com/external/plugins/ElasticSearchPluginTest.java
@@ -1,21 +1,28 @@
package com.external.plugins;
-import com.appsmith.external.models.ActionConfiguration;
-import com.appsmith.external.models.ActionExecutionResult;
+import com.appsmith.external.constants.Authentication;
import com.appsmith.external.models.DatasourceConfiguration;
import com.appsmith.external.models.Endpoint;
+import com.appsmith.external.models.DBAuth;
+import com.appsmith.external.models.ActionExecutionResult;
+import com.appsmith.external.models.ActionConfiguration;
import com.appsmith.external.models.RequestParamDTO;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpHost;
+import org.apache.http.auth.AuthScope;
+import org.apache.http.auth.UsernamePasswordCredentials;
+import org.apache.http.client.CredentialsProvider;
+import org.apache.http.impl.client.BasicCredentialsProvider;
+import org.apache.http.impl.nio.client.HttpAsyncClientBuilder;
import org.elasticsearch.client.Request;
import org.elasticsearch.client.RestClient;
+import org.elasticsearch.client.RestClientBuilder;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.ClassRule;
import org.junit.Test;
import org.springframework.http.HttpMethod;
import org.testcontainers.elasticsearch.ElasticsearchContainer;
-import org.testcontainers.utility.DockerImageName;
import reactor.core.publisher.Mono;
import reactor.test.StepVerifier;
@@ -39,20 +46,37 @@ public class ElasticSearchPluginTest {
@ClassRule
public static final ElasticsearchContainer container = new ElasticsearchContainer("docker.elastic.co/elasticsearch/elasticsearch:7.12.1")
- .withEnv("discovery.type", "single-node");
-
+ .withEnv("discovery.type", "single-node")
+ .withPassword("esPassword");
+ private static String username ="elastic";
+ private static String password = "esPassword";
private static final DatasourceConfiguration dsConfig = new DatasourceConfiguration();
+ private static DBAuth elasticInstanceCredentials = new DBAuth(DBAuth.Type.USERNAME_PASSWORD,username,password, null);
private static String host;
private static Integer port;
+
+
@BeforeClass
public static void setUp() throws IOException {
port = container.getMappedPort(9200);
host = "http://" + container.getContainerIpAddress();
- final RestClient client = RestClient.builder(
- new HttpHost(container.getContainerIpAddress(), port, "http")
- ).build();
+ final CredentialsProvider credentialsProvider =
+ new BasicCredentialsProvider();
+ credentialsProvider.setCredentials(AuthScope.ANY,
+ new UsernamePasswordCredentials(username,password));
+
+ RestClient client = RestClient.builder(
+ new HttpHost(container.getContainerIpAddress(),port,"http"))
+ .setHttpClientConfigCallback(new RestClientBuilder.HttpClientConfigCallback() {
+ @Override
+ public HttpAsyncClientBuilder customizeHttpClient(
+ HttpAsyncClientBuilder httpClientBuilder) {
+ return httpClientBuilder
+ .setDefaultCredentialsProvider(credentialsProvider);
+ }
+ }).build();
Request request;
@@ -69,8 +93,11 @@ public class ElasticSearchPluginTest {
client.performRequest(request);
client.close();
-
+ elasticInstanceCredentials.setAuthenticationType(Authentication.BASIC);
+ elasticInstanceCredentials.setUsername(username);
+ elasticInstanceCredentials.setPassword(password);
dsConfig.setEndpoints(List.of(new Endpoint(host, port.longValue())));
+ dsConfig.setAuthentication(elasticInstanceCredentials);
}
private Mono execute(HttpMethod method, String path, String body) {
@@ -230,6 +257,7 @@ public class ElasticSearchPluginTest {
@Test
public void itShouldValidateDatasourceWithNoEndpoints() {
DatasourceConfiguration invalidDatasourceConfiguration = new DatasourceConfiguration();
+ invalidDatasourceConfiguration.setAuthentication(elasticInstanceCredentials);
Assert.assertEquals(Set.of("No endpoint provided. Please provide a host:port where ElasticSearch is reachable."),
pluginExecutor.validateDatasource(invalidDatasourceConfiguration));
@@ -238,6 +266,7 @@ public class ElasticSearchPluginTest {
@Test
public void itShouldValidateDatasourceWithEmptyPort() {
DatasourceConfiguration datasourceConfiguration = new DatasourceConfiguration();
+ datasourceConfiguration.setAuthentication(elasticInstanceCredentials);
Endpoint endpoint = new Endpoint();
endpoint.setHost(host);
datasourceConfiguration.setEndpoints(Collections.singletonList(endpoint));
@@ -249,6 +278,7 @@ public class ElasticSearchPluginTest {
@Test
public void itShouldValidateDatasourceWithEmptyHost() {
DatasourceConfiguration datasourceConfiguration = new DatasourceConfiguration();
+ datasourceConfiguration.setAuthentication(elasticInstanceCredentials);
Endpoint endpoint = new Endpoint();
endpoint.setPort(Long.valueOf(port));
datasourceConfiguration.setEndpoints(Collections.singletonList(endpoint));
@@ -260,7 +290,7 @@ public class ElasticSearchPluginTest {
@Test
public void itShouldValidateDatasourceWithMissingEndpoint() {
DatasourceConfiguration datasourceConfiguration = new DatasourceConfiguration();
-
+ datasourceConfiguration.setAuthentication(elasticInstanceCredentials);
Endpoint endpoint = new Endpoint();
datasourceConfiguration.setEndpoints(Collections.singletonList(endpoint));
@@ -272,6 +302,7 @@ public class ElasticSearchPluginTest {
public void itShouldValidateDatasourceWithEndpointNoProtocol() {
DatasourceConfiguration datasourceConfiguration = new DatasourceConfiguration();
Endpoint endpoint = new Endpoint();
+ datasourceConfiguration.setAuthentication(elasticInstanceCredentials);
endpoint.setHost("localhost");
endpoint.setPort(Long.valueOf(port));
datasourceConfiguration.setEndpoints(Collections.singletonList(endpoint));
@@ -284,6 +315,7 @@ public class ElasticSearchPluginTest {
@Test
public void itShouldTestDatasourceWithInvalidEndpoint() {
DatasourceConfiguration datasourceConfiguration = new DatasourceConfiguration();
+ datasourceConfiguration.setAuthentication(elasticInstanceCredentials);
Endpoint endpoint = new Endpoint();
endpoint.setHost("localhost");
endpoint.setPort(Long.valueOf(port));
@@ -304,4 +336,42 @@ public class ElasticSearchPluginTest {
})
.verifyComplete();
}
+
+ @Test
+ public void shouldVerifyUnauthorized() {
+ final Integer secureHostPort = container.getMappedPort(9200);
+ final String secureHostEndpoint = "http://" + container.getHttpHostAddress();
+ DatasourceConfiguration datasourceConfiguration = new DatasourceConfiguration();
+ Endpoint endpoint = new Endpoint(secureHostEndpoint,Long.valueOf(secureHostPort));
+ datasourceConfiguration.setEndpoints(Collections.singletonList(endpoint));
+
+
+ StepVerifier.create(pluginExecutor.testDatasource(datasourceConfiguration)
+ .map(result -> {
+ return (Set) result.getInvalids();
+ }))
+ .expectNext(Set.of(ElasticSearchPlugin.ElasticSearchPluginExecutor.esDatasourceUnauthorizedMessage))
+ .verifyComplete();
+
+ }
+
+
+ @Test
+ public void shouldVerifyNotFound() {
+ final Integer secureHostPort = container.getMappedPort(9200);
+ final String secureHostEndpoint = "http://esdatabasenotfound.co" ;
+ DatasourceConfiguration datasourceConfiguration = new DatasourceConfiguration();
+ Endpoint endpoint = new Endpoint(secureHostEndpoint,Long.valueOf(secureHostPort));
+ datasourceConfiguration.setEndpoints(Collections.singletonList(endpoint));
+
+ StepVerifier.create(pluginExecutor.testDatasource(datasourceConfiguration)
+ .map(result -> {
+ return (Set) result.getInvalids();
+ }))
+ .expectNext(Set.of(ElasticSearchPlugin.ElasticSearchPluginExecutor.esDatasourceNotFoundMessage))
+ .verifyComplete();
+
+ }
+
+
}