0

I have two servers configured and running om my Debian server. One main server and one Elasticsearch (search engine) server.

The main server is running on a https node server with a NGINX proxy and a purchased SSL certificate. The Elasticsearch server is running on a http server. I've added a new NGINX proxy server to redirect https://localhost:9999 to http://localhost:9200 with a self-signed SSL certificate. There's also a configured authentication on the Elasticsearch server with a username and a password.

Everything seem to be properly configured since I can get a successful response from the server when I'm doing a curl from the servers terminal towards https://localhost:9999 with the -k option to bypass the verication of the self-signed certificate, without it, it does not work.

I cannot do a cross-domain request from my https main server to my http localhost server. Therefore I need to configure https on my localhost server.


Without the -k option:

curl: (60) SSL certificate problem: self signed certificate
More details here: http://curl.haxx.se/docs/sslcerts.html

curl performs SSL certificate verification by default, using a "bundle"
 of Certificate Authority (CA) public keys (CA certs). If the default
 bundle file isn't adequate, you can specify an alternate file
 using the --cacert option.
If this HTTPS server uses a certificate signed by a CA represented in
 the bundle, the certificate verification probably failed due to a
 problem with the certificate (it might be expired, or the name might
 not match the domain name in the URL).
If you'd like to turn off curl's verification of the certificate, use
 the -k (or --insecure) option.

With the -k option:

{
  "name" : "server-name",
  "cluster_name" : "name",
  "cluster_uuid" : "uuid",
  "version" : {
    "number" : "x.x.x",
    "build_hash" : "abc123",
    "build_date" : "Timestamp",
    "build_snapshot" : false,
    "lucene_version" : "x.x.x"
  },
  "tagline" : "You Know, for Search"
}

Which is a successful Elasticsearch server response.


So the full curl request looks something like curl -k https://localhost:9999/ --user username:password.

So, the actual question:

I would like to be able to do a simple jQuery AJAX request towards this server. I'm trying with the following request $.get('https://username:password@localhost:9999/') but I'm getting ERR_CONNECTION_REFUSED.

My guess is that that the AJAX request does not bypass the self-signed certificate verification and therefore it refuses to connect.

Is there any simple way to solve this with request headers or something like that? Or do i need to purchase a CA-certificate to make this work with AJAX?

Jonathan Nielsen
  • 1,442
  • 1
  • 17
  • 31

1 Answers1

1

You are right the problem is the self signed certificate.If you try the same request but as http it will work.

Here is a workaround to make ElasticSearch work with https:

You need to implement your own Http Connector:

var HttpConnector = require('elasticsearch/src/lib/connectors/http');
var inherits = require('util').inherits;
var qs = require('querystring');
var fs = require('fs');

function CustomHttpConnector(host, config) {
  HttpConnector.call(this, host, config);
}

inherits(CustomHttpConnector, HttpConnector);

// This function is copied and modified from elasticsearch-js/src/lib/connectors/http.js
CustomHttpConnector.prototype.makeReqParams = function (params) {
  params = params || {};
  var host = this.host;

  var reqParams = {
    method: params.method || 'GET',
    protocol: host.protocol + ':',
    auth: host.auth,
    hostname: host.host,
    port: host.port,
    path: (host.path || '') + (params.path || ''),
    headers: host.getHeaders(params.headers),
    agent: this.agent,
    rejectUnauthorized: true,
    ca: fs.readFileSync('publicCertificate.crt', 'utf8')
  };

  if (!reqParams.path) {
    reqParams.path = '/';
  }

  var query = host.getQuery(params.query);
  if (query) {
    reqParams.path = reqParams.path + '?' + qs.stringify(query);
  }

  return reqParams;
};

module.exports = CustomHttpConnector;

Then register it like so:

var elasticsearch = require('elasticsearch');
var CustomHttpConnector = require('./customHttpConnector');

    var Elasticsearch = function() {
      this.client = new elasticsearch.Client({
        host: {
          host: 'my.server.com',
          port: '443',
          protocol: 'https',
          auth: 'user:passwd'
        },
        keepAlive: true,
        apiVerison: "1.3",
        connectionClass: CustomHttpConnector
      });
    }

https://gist.github.com/fractalf/d08de3b59c32197ccd65

If you want to make simple ajax calls not using ES the only thing you can do is prompt the user to visit the page and accept the certificate themselves when the request is denied.

Also see: https://stackoverflow.com/a/4566055/5758328

Community
  • 1
  • 1
Mawcel
  • 1,967
  • 15
  • 22
  • Thank you very much for your response. I'll try this and get back to you. – Jonathan Nielsen Mar 06 '17 at 09:27
  • Does this mean i have to make a request to my node backend and make a request to es and send the response back to the frontend? Or can i solve this with pure frontend? I'm not 100% sure what is happening in this example :) I was able to configure Elasticsearch with your example and successfully ping the https-server. – Jonathan Nielsen Mar 06 '17 at 10:40
  • This example tells ElasticSearch to use a custom connection class to perform it's ajax requests.See my edit above – Mawcel Mar 06 '17 at 10:43