"GetAddrInfoReqWrap.onlookup [as oncomplete] (dns.js:76:26)" - node.js

I am trying to run a lambda function using request library. I tried to look at some other same issues, but couldnt find exactly the one i needed. Following is my code:
var req = require('request');
var headers = { 'X-AUTH-TOKEN': 'xxxx',
'Content-Type': 'application/json',
'Accept': 'application/json'};
var body = {"name" : "omkarEmailTest", "command_type":"SparkCommand", "language":"notebook", "note_id":"56563", "label":"YetAnotherSparkCluster"};
// Configure the request
var options = {
url: 'http://api.quobole.com/api/v1.2/commands',
method: 'POST',
headers: headers,
body: body,
json: true
};
exports.handler = (event, context, callback) => {
req(options, function (error, response, body) {
console.log(body);
callback(error);
});
}
Following is the log i am getting in my aws lambda console:
Response:
{
"errorMessage": "getaddrinfo ENOTFOUND api.quobole.com api.quobole.com:80",
"errorType": "Error",
"stackTrace": [
"errnoException (dns.js:28:10)",
"GetAddrInfoReqWrap.onlookup [as oncomplete] (dns.js:76:26)"
]
}
Request ID:
"2295eee5-ec11-11e7-a9f4-dfa2f9f62b50"
Function Logs:
START RequestId: 2295eee5-ec11-11e7-a9f4-dfa2f9f62b50 Version: $LATEST
2017-12-28T20:53:20.715Z 2295eee5-ec11-11e7-a9f4-dfa2f9f62b50 undefined
2017-12-28T20:53:20.775Z 2295eee5-ec11-11e7-a9f4-dfa2f9f62b50 {"errorMessage":"getaddrinfo ENOTFOUND api.quobole.com api.quobole.com:80","errorType":"Error","stackTrace":["errnoException (dns.js:28:10)","GetAddrInfoReqWrap.onlookup [as oncomplete] (dns.js:76:26)"]}
END RequestId: 2295eee5-ec11-11e7-a9f4-dfa2f9f62b50
REPORT RequestId: 2295eee5-ec11-11e7-a9f4-dfa2f9f62b50 Duration: 655.79 ms Billed Duration: 700 ms Memory Size: 128 MB Max Memory Used: 33 MB
Any help will be appreciated!!!!

Related

Securing Cloud Functions using IAM + NodeJS application running on AppEngine

I need some help with example if possible of code changes to be done on my NodeJS server code running on AppEngine in order to allow it to securely access my cloud fucntions.
I created a cloud function and I have a public URL for it. I then went ahead and removed allUser access in the Permissions' tab of the function. Under Service account I have App Engine Default Service account` selected.
My server on AppEngine was calling the public URL of the CF and when `allUser' permission was there, everything was hunky dory. But when it was removed, I started getting 403 error.
I need help with code changes on NodeJS side to be able to invoke the cloud fucntion again please.
My CF and App engine are in the same project and in the same region.
My server code is as follows using an https library to make the post request.
const checkingData = JSON.stringify({
'check' : 123
})
const checkingOptions = {
hostname: MY_CLOUD_PUBLIC_URL,
port: 443,
timeout: 5000,
path: MY_CLOUD_URL_PATH,
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Content-Length': checkingData.length,
}
}
const checkRequest = https.request(checkingOptions, checkD => {
if (checkD.statusCode==200) { // OK?
checkD.on('data', d => {
// Do something useful with the data
})
})
checkRequest.write(checkingData);
checkRequest.end();
I have been trying to find an answer for this for days now and started having migranes because of this. Any help with example code would be much appreciated. Many thanks!
EDIT
I can see the token now! (Yayyy!)
I changed my checkingOptions to work with request-promise in the following way:
const checkingOptions = {
uri: 'https://'+process.env.CLOUD_URL+process.env.CHECK,
port: 443,
timeout: 5000,
body:checkingData,
json: true,
// path: process.env.CHECK,
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Content-Length': checkingData.length,
}
}
I am getting the following errors:
Unhandled rejection StatusCodeError: 401 - "\n<html><head>\n<meta http-equiv=\"content-type\" content=\"text/html;charset=utf-8\">\n<title>401 Unauthorized</title>\n</head>\n<body text=#000000 bgcolor=#ffffff>\n<h1>Error: Unauthorized</h1>\n<h2>Your client does not have permission to the requested URL <code>/check</code>.</h2>\n<h2></h2>\n</body></html>\n"
2021-02-27 19:38:01 default[20210227t192944] at new StatusCodeError (/workspace/node_modules/request-promise-core/lib/errors.js:32:15)
2021-02-27 19:38:01 default[20210227t192944] at Request.plumbing.callback (/workspace/node_modules/request-promise-core/lib/plumbing.js:104:33)
2021-02-27 19:38:01 default[20210227t192944] at Request.RP$callback [as _callback] (/workspace/node_modules/request-promise-core/lib/plumbing.js:46:31)
2021-02-27 19:38:01 default[20210227t192944] at Request.self.callback (/workspace/node_modules/request/request.js:185:22)
2021-02-27 19:38:01 default[20210227t192944] at Request.emit (events.js:314:20)
2021-02-27 19:38:01 default[20210227t192944] at Request.<anonymous> (/workspace/node_modules/request/request.js:1154:10)
2021-02-27 19:38:01 default[20210227t192944] at Request.emit (events.js:314:20)
2021-02-27 19:38:01 default[20210227t192944] at IncomingMessage.<anonymous> (/workspace/node_modules/request/request.js:1076:12)
2021-02-27 19:38:01 default[20210227t192944] at IncomingMessage.emit (events.js:326:22)
2021-02-27 19:38:01 default[20210227t192944] at endReadableNT (_stream_readable.js:1241:12)
Do I need a middleware in my cloud function as well? My cloud function looks like the follow:
exports.check = functions.https.onRequest((req, res) => {
console.log('----CHECKING----');
res.status(200).send('Hello from checking');
})
IAM ROLES:
CLOUD FUNCTION > PERMISSIONS TAB
You have a great example in the documentation. If you want I adapt it to your code, it could look like to this
// Make sure to `npm install --save request-promise` or add the dependency to your package.json
const request = require('request-promise');
// Set up metadata server request
// See https://cloud.google.com/compute/docs/instances/verifying-instance-identity#request_signature
const metadataServerTokenURL = 'http://metadata/computeMetadata/v1/instance/service-accounts/default/identity?audience=';
const tokenRequestOptions = {
uri: metadataServerTokenURL + MY_CLOUD_PUBLIC_URL,
headers: {
'Metadata-Flavor': 'Google'
}
};
const checkingData = JSON.stringify({
'check' : 123
})
const checkingOptions = {
uri: MY_CLOUD_PUBLIC_URL, //!!!changed here!!!
port: 443,
timeout: 5000,
path: MY_CLOUD_URL_PATH,
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Content-Length': checkingData.length,
}
}
request(tokenRequestOptions).then((token) => {
request(checkingOptions).auth(null, null, true, token).then((response) => { //!!!changed here!!!
checkD.on('data', d => {
// Do something useful with the data
})
})
.catch((error) => {
res.status(400).send(error);
}); => {
})
checkRequest.write(checkingData);
checkRequest.end();
Don't forget to add the role role/cloudfunctions.invoker to the App Engine default service account, either at the project level or at the Cloud Functions level.
EDIT 1
Correct. request-promise has been deprecated for year. What alternative? I absolutely don't know because NodeJS hurts me (as I said in the comment).
As a lazy man, I found an alternative. I found the request-promise in the Cloud Run documentation. But you have to know that Cloud Run and Cloud Functions are very closed (they share the same underlying platform). I take my chance with Cloud Functions authentication documentation and bingo! There is an example with node-fetch
const fetch = require('node-fetch');
const MY_CLOUD_PUBLIC_URL = '....'
const metadataServerTokenURL = 'http://metadata/computeMetadata/v1/instance/service-accounts/default/identity?audience=';
// Fetch the token
const tokenResponse = await fetch(metadataServerTokenURL + MY_CLOUD_PUBLIC_URL, {
headers: {
'Metadata-Flavor': 'Google',
},
});
const token = await tokenResponse.text();
console.log(token)
const checkingData = JSON.stringify({
'check' : 123
})
// Provide the token in the request to the receiving function
try {
const functionResponse = await fetch(MY_CLOUD_PUBLIC_URL, {
method: 'post',
body: checkingData,
headers: {
'Content-Type': 'application/json',
Authorization: `bearer ${token}`},
});
console.log(await functionResponse.text());
} catch (err) {
console.error(err);
}
Add your check functions and it should work now!

Error: getaddrinfo ENOTFOUND Node JS using protractor

I'm using this method to request a tokenDn
this.retornaTokenDnQA = function (Request, tokenAuth) {
return new Promise((resolve, reject) => {
Request.get({
"headers": { "content-type": "application/json", "Authorization": "Bearer " + tokenAuth },
"url": "https://urlqa-api.apps.pd01e.edc1.cf.company.com/transformation/api/jwt/generate",
"body": JSON.stringify({
"dn": "5094",
"claims": {
"country": "BRA",
"division": 1,
"user": "ULSCA301",
"roles": [
"agenda - Distribuidor",
"teste - teste"
],
"locale": {
"language": "pt",
"region": "BR"
}
}
})
}, (error, response, body) => {
if (error) {
return console.dir(error);
}
//console.log("inside: " + response.body);
resolve(response.body);
});
});
};//end function - retornaTokenDn
but this return the following erro message.
Error: getaddrinfo ENOTFOUND urlqa-api.apps.pd01e.edc1.cf.company.com
at GetAddrInfoReqWrap.onlookup [as oncomplete] (dns.js:64:26) {
errno: 'ENOTFOUND',
code: 'ENOTFOUND',
syscall: 'getaddrinfo',
hostname: 'urlqa-api.apps.pd01e.edc1.cf.company.com'
}
**
The real problema is, this error only occur when I'm using a VPN connection to connect the network company. Using my home network this work normally.**
Or when I'm using vpn and send a request by postman using the same options the response is 200 , ok.
I'm using this method in a protractor automated test, I apreciate any help u can do. Thanks!!!
if the ENOTFOUND error is dependent on your network, I'd check if there is a proxy server in one of the networks.

Elastic search gives Bad request for ping

Code in elasticsearch.js file
function es() {
throw new Error('Looks like you are expecting the previous "elasticsearch" module. ' +
'It is now the "es" module. To create a client with this module use ' +
'`new es.Client(params)`.');
}
es.Client = require('./lib/client');
es.ConnectionPool = require('./lib/connection_pool');
es.Transport = require('./lib/transport');
es.errors = require('./lib/errors');
module.exports = es;
var elasticsearch = require('elasticsearch')
var client = new es.Client({
host: 'localhost:9200',
log: 'trace',
})
// Ping the cluster
client.ping({
requestTimeOut: 30000,
},
function(error){
if(error) {
console.log(error)
console.error("elasticsearch cluster is down!")
}
else {
console.log("All is well")
}
})
and I am running elastic search locally with command $bin/elasticsearch
but when I do $node elasticsearch.js it gives the error saying
Elasticsearch INFO: 2018-01-22T11:17:50Z
Adding connection to http://localhost:9200/
Elasticsearch DEBUG: 2018-01-22T11:17:50Z
starting request {
"method": "HEAD",
"requestTimeout": 3000,
"castExists": true,
"path": "/",
"query": {
"requestTimeOut": 30000
}
}
Elasticsearch TRACE: 2018-01-22T11:17:50Z
-> HEAD http://localhost:9200/?requestTimeOut=30000
<- 400
Elasticsearch DEBUG: 2018-01-22T11:17:50Z
Request complete
{ Error: Bad Request
at respond (/Users/ElasticSearchServer/node_modules/elasticsearch/src/lib/transport.js:307:15)
at checkRespForFailure (/Users/ElasticSearchServer/node_modules/elasticsearch/src/lib/transport.js:266:7)
at HttpConnector.<anonymous> (/Users/ElasticSearchServer/node_modules/elasticsearch/src/lib/connectors/http.js:159:7)
at IncomingMessage.bound (/Users/ElasticSearchServer/node_modules/elasticsearch/node_modules/lodash/dist/lodash.js:729:21)
at emitNone (events.js:91:20)
at IncomingMessage.emit (events.js:185:7)
at endReadableNT (_stream_readable.js:974:12)
at _combinedTickCallback (internal/process/next_tick.js:80:11)
at process._tickCallback (internal/process/next_tick.js:104:9)
status: 400,
displayName: 'BadRequest',
message: 'Bad Request',
path: '/',
query: { requestTimeOut: 30000 },
body: undefined,
statusCode: 400,
response: '',
toString: [Function],
toJSON: [Function] }
elasticsearch cluster is down!
If I try adding new index, delete index, check the health or search, it works fine and gives the appropriate result.
Can anyone help me to fix the issue? thanks in advance!
In the new JavaScript client every option that is not intended for Elasticsearch lives in a second object, your code should be updated as follows:
'use strict'
const { Client } = require('#elastic/elasticsearch')
const client = new Client({ node: 'http://localhost:9200' })
client.ping({}, { requestTimeout: 20000 }, (err, response) => {
...
})
In the response object other than body, statusCode, and headers, you will also find a warnings array and a meta object, which should help you debug issues.
In this case, warnings contained the following message: 'Client - Unknown parameter: "requestTimeout", sending it as query parameter'.

AWS Lambda and Redis

I'm trying to write an AWS Lambda function which uses redis(on amazon elasticcache). The problem – I can't connect to redis. I use code like this
'use strict'
function handler (data, context, cb) {
const redis = require("redis")
console.log('before client initialization')
const client = redis.createClient({
url: 'redis://propper-url-cache.some.0001.euw1.cache.amazonaws.com:6379',
retry_strategy: function(options) {
console.log(options)
if (options.total_retry_time > 1000) {
throw new Error('can`t connect to redis')
}
}
})
console.log('after client initialization')
client.on("error", function (err) {
console.log('in error')
cb({error: err})
});
client.get("counter", function (err, counter) {
console.log('counter', counter)
if(_.isNull(counter)) {
counter = 0
}
client.set('counter', counter + 1, function(err) {
console.log(err)
cb(null, {counter: counter})
})
});
}
exports.handler = handler
as a result I see something like this in logs:

15:33:41
START RequestId: d8024ec2-7f36-11e6-996c-1bfcb60572c6 Version: $LATEST

15:33:42
2016-09-20T13:33:42.632Z d8024ec2-7f36-11e6-996c-1bfcb60572c6 before client initialization

15:33:42
2016-09-20T13:33:42.813Z d8024ec2-7f36-11e6-996c-1bfcb60572c6 after client initialization

15:33:44
END RequestId: d8024ec2-7f36-11e6-996c-1bfcb60572c6

15:33:44
REPORT RequestId: d8024ec2-7f36-11e6-996c-1bfcb60572c6 Duration: 3002.67 ms Billed Duration: 3000 ms Memory Size: 128 MB Max Memory Used: 19 MB

15:33:44
2016-09-20T13:33:44.620Z d8024ec2-7f36-11e6-996c-1bfcb60572c6 Task timed out after 3.00 seconds
when I change redis url for something which definitely makes no sense I have an additional row:
2016-09-20T13:29:42.953Z 48fcb071-7f36-11e6-bc52-c5ac58c12843 { attempt: 1, error: { [Error: Redis connection to some-url.euw1.cache.amazonaws.com:6379 failed - getaddrinfo ENOTFOUND some-url.euw1.cache.amazonaws.com some-url.euw1.cache.amazonaws.com:6379] code: 'ENOTFOUND', errno: 'ENOTFOUND', syscall: 'getaddrinfo', hostna
Any ideas?
You need to have Redis in same VPC as Lambda. Check your security group settings. And then if you have EC2 access, install redis-cli and try to connect Redis. If this get connected your Lambda Redis will also get connected. As said earlier, you need to have your lambda in same VPC.
The following is boilerplate code demonstrating connecting to Lambda:
console.log('before client initialization')
const redisOptions = {
host: 'xxxx.xxx.xxx.xxx.xxx.amazonaws.com',
port: 6379,
}
var client = redis.createClient(redisOptions);
console.log('after client initialization');
client.on('connect', function(result) {
console.log('connected');
}

'Error: connect ECONNREFUSED' When calling http.request

I am trying to run the following node code,
function getQuestions() {
var options = {
host: 'mysite.com',
path: '/services/v2/question.json',
headers: {
"Content-Type": "application/json",
"accept": "application/json; charset=UTF-8",
'Authorization': auth
}
};
http.request(options, function(response) {
console.log("Everything worked!");
}).on('error', function(e) {
console.log('problem with request: ' + e.stack);
});
}
But it always errors saying...
problem with request: Error: connect ECONNREFUSED
at errnoException (net.js:905:11)
at Object.afterConnect [as oncomplete] (net.js:896:19)
When I put the same info into Postman it works fine. Is there a way to debug this?
Update
Tried this...
var options = {
host: "google.com"
};
Same result so something must be wrong in my code. Any ideas?
It did end up being a proxy issue this...
var options = {
host: "proxy",
port: 80,
path: 'http://google.com'
};
Notice the proxy in host. I will mark as duplicate of this post

Resources