Skip to content

Instantly share code, notes, and snippets.

@parthdesai93
Last active April 8, 2021 06:18
Show Gist options
  • Save parthdesai93/1bd3a25ad4cf788d49ce4a00a1bb3268 to your computer and use it in GitHub Desktop.
Save parthdesai93/1bd3a25ad4cf788d49ce4a00a1bb3268 to your computer and use it in GitHub Desktop.
http-aws-es compatible with new Elasticsearch client.
/* requires AWS creds to be updated.
* if they aren't, update using AWS.config.update() method before instatiing the client.
*
* import this module where you instantiate the client, and simply pass this module as the connection class.
*
* eg:
* const client = new Client({
* node,
* Connection: AwsConnector
* });
*/
import AWS from 'aws-sdk';
import { Connection } from '@elastic/elasticsearch';
class AwsConnector extends Connection {
async request(params, callback) {
try {
const creds = await this.getAWSCredentials();
const req = this.createRequest(params);
const { request: signedRequest } = this.signRequest(req, creds);
super.request(signedRequest, callback);
} catch (error) {
throw error;
}
}
createRequest(params) {
const endpoint = new AWS.Endpoint(this.url.href);
let req = new AWS.HttpRequest(endpoint);
Object.assign(req, params);
req.region = AWS.config.region;
if (!req.headers) {
req.headers = {};
}
let body = params.body;
if (body) {
let contentLength = Buffer.isBuffer(body)
? body.length
: Buffer.byteLength(body);
req.headers['Content-Length'] = contentLength;
req.body = body;
}
req.headers['Host'] = endpoint.host;
return req;
}
getAWSCredentials() {
return new Promise((resolve, reject) => {
AWS.config.getCredentials((err, creds) => {
if (err) {
if (err && err.message) {
err.message = `AWS Credentials error: ${e.message}`;
}
reject(err);
}
resolve(creds);
});
});
}
signRequest(request, creds) {
const signer = new AWS.Signers.V4(request, 'es');
signer.addAuthorization(creds, new Date());
return signer;
}
}
export { AwsConnector };
import { AwsConnector } from './aws_es_connector';
import { Client } from '@elastic/elasticsearch';
import AWS from 'aws-sdk';
// load aws keys and region, ideally using env variables.
let accessKey = '****';
let secretKey = '****';
let region = '**'; //eg: us-east-1
let node = '***'; //node url
AWS.config.update({
credentials: new AWS.Credentials(accessKey, secretKey),
region
});
const client = new Client({
node,
Connection: AwsConnector
});
//use this client to talk to AWS managed ES service.
export default client;
@mohitkhanna
Copy link

@fewstera Thank you for posting this. Will test it out.

@mohitkhanna
Copy link

@fewstera A question. You have a list of whitelisted function names that you wrap in awsCredsifyAll. How would you keep them always in sync with any new ES release?

@fewstera
Copy link

fewstera commented Sep 11, 2019

@mohitkhanna those whitelisted keys come from the first level of this object: https://github.com/elastic/elasticsearch-js/blob/master/api/index.js#L18. So they could easily be updated using a script, but there is no automatic setup in place to currently do this.

I don't see them changing often, but I will check them occasionally to ensure they don't go out of sync. If a whitelisted key is missed, the client will continue to work, just the AWS credentials will not be refreshed by that method call.

@mohitkhanna
Copy link

mohitkhanna commented Sep 11, 2019 via email

@sabareeshkk
Copy link

Figured it out.
AWSHTTPRequest uses path to send query parameters and there is no key as "querystring" here in docs.
So a small change in aws_es_connector.js solves the problem.
In createRequest() before sending the req object
req.path+='/?'+req.querystring; delete req.querystring;
Now all parameters will work fine.

cool .thanks saved my day

@sboyd
Copy link

sboyd commented Mar 22, 2020

Thank you @parthdesai93! Was very helpful

@niezgoda
Copy link

Hey. I find I spot an issue.
Look at this:
`

const x = 'ߤߤߤߤ';
x.length
4
w = Buffer.from(x)

> w.byteLength 8 `

Content-Length is provided in bytes. So the header is going to have invalid value - 4 bytes instead of 8.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment