Lambda function access by RDS trigger creates connection lost - amazon-web-services

I created 2 tables in RDS aurora:
test-table in aurora db with values id(PK), tasknumber, status , contactid(FK)
contact-table in same db with values contactid(PK), email, phone
I created a trigger in 'test-table' that whenever a 'status' changes, the trigger should call AWS-Lambda ARN.
The Lambda function and Aurora has all the permissions, and security cleared, still on testing from Lambda I get below image error and on updating the 'status' field manually in aurora(via Workbench Sql query) it shows:
Operation failed: There was an error while applying the SQL script to the database.
ERROR 2013: 2013: Lost connection to MySQL server during query
I have attached my Lambda Node.Js code too.
var AWS = require('aws-sdk');
AWS.config.update({ region: 'us-east-1' });
const mysql = require('mysql');
var con = mysql.createConnection({
host: 'correct value',
user: 'root',
password: 'correct value',
port: correct value,
database: 'correct value'
});
exports.handler = (event, context, callback) => {
context.callbackWaitsForEmptyEventLoop = false;
var fk = event.contact_id;
console.log('FOREIGN KEY=', fk)
con.connect(function(err) {
if (err) throw err;
var sql = `SELECT * FROM db.contacts where contact_id=${fk}`
con.query(sql, function(err, result) {
if (err) throw err;
var email = result[0].email;
console.log(email);
var sns = new AWS.SNS();
var params = {
Message: email,
Subject: "Test SNS From Lambda",
TopicArn: "arn:correct value"
};
sns.publish(params, function(err, data) {
if (err) console.log(err, err.stack);
else {
console.log(data);
callback(null, 'Success');
}
});
});
});
};
Image1ErrorMySqlWorkbench
Image2ErrorLambdaaws
Also followed for NodeJs package: https://github.com/isaacs

you have to close the connection if you want the instant response otherwise it will take the default time to close the connection, please let me know if makes sense

Related

How to do role based authentication using AWS Cognito and Identity Pool with NodeJS

I am doing role based authentication using AWS cognito and Identity pool using NodeJS
I have 3 role.
Admin ( Full Dynamodb access, AWS SES full access and SNS full access )
Support Executive ( Full Dynamodb access )
Customer ( Read Dynamodb access )
When the user registered I am adding user to their respective group from AWS Cognito.
After login - I am getting accessToken, IdToken and refreshToken.
Now I am calling, below to API, in order to get unique accessKey, secretKey and sessionToken of each user ( which valid for 1 hr ) --- Based on the group ( Admin, Support Executive, Customer ) what user is having what permission ?
cognitoidentity.getId
cognitoidentity.getCredentialsForIdentity
Now I wanted to do, Dynamodb insert operation, How I can verify those accessKey, secretKey and sessionToken whatever I am getting, and how to pass that in the API ?
What I am doing below -
// Dynamodb fetch API
app.get('/dynamodb/fetch', [middleware.bearerTokenPresent, authentication.verifyToken], (req, res) => {
var dynamoDB = new AWS.DynamoDB.DocumentClient({
region: "us-west-1",
});
var params = {
TableName: "test",
};
dynamoDB.scan(params, function(err, data) {
if (err) {
console.log("Error", err);
res.send({
err: err
});
} else {
res.send(data);
}
});
})
// Dynamodb insert API
app.post('/dynamodb/insert', [middleware.bearerTokenPresent, authentication.verifyToken], (req, res) => {
var dynamoDB = new AWS.DynamoDB.DocumentClient({
region: "us-west-1",
});
var params = {
TableName: "test",
Item: {
id: req.body.id,
email: req.body.email,
isverfied: req.body.isverfied,
desc: req.body.desc,
}
};
dynamoDB.put(params, function (err, data) {
if (err) {
res.send({
err: err
});
} else {
res.send({
message: "Inserted data into Dynamodb!"
});
}
});
})
Each and everytime I try to insert record into Dynamodb I can able to insert it. Even I login via Customer role. Why because I am not validating those accessKey, secreatKey, SessionToken and IdToken.
Any idea how to do that ? Any help would be appriciated.

How to get the Agent Email Address from amazon connect logged in

i have build sample amazon connect login to get the agent details from javascript api, but do not have any docs to get agent email address i followed docs
https://github.com/amazon-connect/amazon-connect-streams/blob/master/Documentation.md
Kindly help me how to get the email adddress
You can get the email address of the User by using the describeUser.
var AWS = require('aws-sdk');
var connect = new AWS.Connect();
exports.handler = function (event) {
var params = {
InstanceId: 'STRING_VALUE', /* required */
UserId: 'STRING_VALUE' /* required */
};
connect.describeUser(params, function(err, data) {
if (err) console.log(err, err.stack);
else console.log(data.User.IdentityInfo.Email);
});
}
From the documentation you posted:
https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/Connect.html#describeUser-property
An example of what the User object looks like:
https://docs.aws.amazon.com/connect/latest/APIReference/API_DescribeUser.html

Not able to connect to AWS documentDb from Lambda

I'm trying to connect to AWS documentDB from Lambda function but, not able to connect.
MongoClient.connect never calls the callback function connected.
TLS is off on documentDB Cluster. I'm able to connect via mongo shell.
Lambda & documentDB are in same VPC & Security group.
'use strict';
module.exports.search = async (event, context, callback) => {
const MongoClient = require('mongodb').MongoClient;
const url = "mongodb://xxx:xxxx#xxx-db.cluster-xxx.us-east-2.docdb.amazonaws.com:27017";
console.log("Starting");
MongoClient.connect(url,
{
useNewUrlParser: true
},
function(err, client) {
if(err)
throw err;
console.log("Connected");
db = client.db('mydb');
col = db.collection('mycollection');
col.find({}).toArray().then(result => {
console.log(result);
return { statusCode: 200, body: result };
}).catch(err => {
console.log('=> an error occurred: ', err);
return { statusCode: 500, body: 'error' };
});
});
};
Output only prints starting which was consoled before calling Mongo.Connect.
How to identify or debug the issue ?
Just from looking at the current code I am pretty sure your function exit before it is able to complete. Therefore, your callback is not executed
Because MongoClient.connect runs asynchronously
Try to take a look at some resource around async/await/promise and Lambda
https://medium.com/tensult/async-await-on-aws-lambda-function-for-nodejs-2783febbccd9
How to wait for async actions inside AWS Lambda?

updated : AWS Lambda is not able to connect to MySQL

I was not able to connect to MySQL using AWS Lambda with Node.js.
I had tried configured the security groups for AWS MySQL and Lambda. When I used console.log it shows correct response from the data base as the data from db : rk, but when I tried to test it was not showing the correct response.
Below was the logs and the index.js files and logs. Can anybody please guide me ?
index.js (i had updated my code as below ):
var mysql = require('mysql');
var pool = mysql.createPool({
host : 'mydbinstancelamda.connqa9taxeg.us-east-1.rds.amazonaws.com',
user : 'admin',
password : 'password',
database : 'dbname'
});
exports.handler = (event, context, callback)=> {
pool.getConnection(function(err, connection) {
if (err) throw err;
var queryString = "SELECT emp_name from employee where emp_name='rk'";
connection.query(queryString, function(err, rows, fields) {
if (err) throw err;
console.log("the data from db : " + rows[0].emp_name);
callback(null);
connection.release();
});
});
};
error :
Response:
{
"errorMessage": "2018-06-11T02:34:19.817Z ef864d3d-6d1f-11e8-b6e3-97ac89a0f544 Task timed out after 3.00 seconds"
}
Request ID:
"ef864d3d-6d1f-11e8-b6e3-97ac89a0f544"
Function Logs:
START RequestId: ef864d3d-6d1f-11e8-b6e3-97ac89a0f544 Version: $LATEST
dadf1a33-6d22-11e8-869d-7d7e31ccaf6e the data from db : rk
END
Try changing the lambda execution timeout from lambda console as shown in the below picture:
Make sure that security group of RDS MySQL DB is allowing connections from Lambda's security group, if there are the same then you are good to go.
UPDATE:
You need to call callback after the MySQL returns the response.
// change following line:
exports.handler = (event, context, req,res,callback)=> {
// To this line:
exports.handler = (event, context, callback)=> {
After the work is finished, You need to callback to tell lambda that work is complete:
callback(undefined, result);
Example: https://docs.aws.amazon.com/lambda/latest/dg/nodejs-prog-model-handler.html#nodejs-prog-model-handler-example
i followed my instructions given by #Dilip Kola , were my mistakes are not closing the pool , handler arguments !...
my complete code looks like now :
var mysql = require('mysql');
var pool = mysql.createPool({
host : 'url for mysql ',
user : 'username ',
password : 'paswrod ',
database : 'database-name'
});
exports.handler = (event, context, callback)=> {
pool.getConnection(function(err, connection) {
if (err) throw err;
var queryString = "SELECT emp_name from employee where emp_name='rk'";
connection.query(queryString, function(err, rows, fields) {
if (err) throw err;
console.log("the data from db : " + rows[0].emp_name);
connection.release();
pool.end();
callback(null,rows[0].emp_name);
});
});
};
finally i got my output as :

Issue sending message to SQS when authenticating with cognito

When attempting to send a message to sqs I get a missing config credentials warning. If switch to just displaying my accesskey and password I can send the message to sqs just fine. I've included the code I'm using and the errors I get from the browser below.
Code below:
AWS.config.credentials = new AWS.CognitoIdentityCredentials({
IdentityPoolId: 'xxxxxx',
});
var params = {
MessageBody: 'some random message',
QueueUrl: 'xxxxxx'
};
AWS.config.credentials.get(function(err) {
if (err) console.log(err);
else console.log(AWS.config.credentials);
});
var sqs = new AWS.SQS();
sqs.sendMessage(params, function (err, data) {
if (!err) {
console.log('Message sent.');
} else {
console.log(err);
}
});
Errors from console.log:
Error: Missing region in config
at null. (https://sdk.amazonaws.com/js/aws-sdk-2.1.12.min.js:5:10470)
at r.SequentialExecutor.r.util.inherit.callListeners (https://sdk.amazonaws.com/js/aws-sdk-2.1.12.min.js:6:27635)
at r.SequentialExecutor.r.util.inherit.emit (https://sdk.amazonaws.com/js/aws-sdk-2.1.12.min.js:6:27431)
at n.Request.o.emitEvent (https://sdk.amazonaws.com/js/aws-sdk-2.1.12.min.js:6:15837)
at e (https://sdk.amazonaws.com/js/aws-sdk-2.1.12.min.js:6:12148)
at r.runTo (https://sdk.amazonaws.com/js/aws-sdk-2.1.12.min.js:7:23197)
at n.Request.o.runTo (https://sdk.amazonaws.com/js/aws-sdk-2.1.12.min.js:6:13657)
at n.Request.o.send (https://sdk.amazonaws.com/js/aws-sdk-2.1.12.min.js:6:13550)
at t.Service.i.makeUnauthenticatedRequest (https://sdk.amazonaws.com/js/aws-sdk-2.1.12.min.js:6:30572)
at t.util.update.getId (https://sdk.amazonaws.com/js/aws-sdk-2.1.12.min.js:7:2224)
index.html:57 Error: Missing credentials in config
at null. (https://sdk.amazonaws.com/js/aws-sdk-2.1.12.min.js:5:10470)
at r.SequentialExecutor.r.util.inherit.callListeners (https://sdk.amazonaws.com/js/aws-sdk-2.1.12.min.js:6:27635)
at r.SequentialExecutor.r.util.inherit.emit (https://sdk.amazonaws.com/js/aws-sdk-2.1.12.min.js:6:27431)
at n.Request.o.emitEvent (https://sdk.amazonaws.com/js/aws-sdk-2.1.12.min.js:6:15837)
at e (https://sdk.amazonaws.com/js/aws-sdk-2.1.12.min.js:6:12148)
at r.runTo (https://sdk.amazonaws.com/js/aws-sdk-2.1.12.min.js:7:23197)
at n.Request.o.runTo (https://sdk.amazonaws.com/js/aws-sdk-2.1.12.min.js:6:13657)
at n.Request.o.send (https://sdk.amazonaws.com/js/aws-sdk-2.1.12.min.js:6:13550)
at t.Service.i.makeUnauthenticatedRequest (https://sdk.amazonaws.com/js/aws-sdk-2.1.12.min.js:6:30572)
at t.util.update.getId (https://sdk.amazonaws.com/js/aws-sdk-2.1.12.min.js:7:2224)
Take note that I've tried adding region various different ways.
I don't see anything in your posted code that sets the region.
[Following copied from the Configuring the SDK in Node.js documentation]
The AWS SDK for Node.js doesn't select the region by default. You can choose a region similarly to setting credentials by either loading from disk or using AWS.config.update():
AWS.config.update({region: 'us-west-1'});