I am trying to implement fleet provisioning in AWS Lambda function. As a starting point, I have this code:
'use strict';
var AWS = require('aws-sdk');
var iot = new AWS.Iot({
endpoint: 'apiendpoint',
accessKeyId: "AAAABBBBBCCCCDDDDD",
secretAccessKey: "AAAAABBBBCCCDD/1234122311222",
region: 'ap-south-1'
});
exports.handler = async (event, context) => {
var params = {
setAsActive: true
};
return {
statusCode: 200,
body:JSON.stringify(await createCertAndKey(params))
}
}
const createCertAndKey = async (params) => {
return new Promise((resolve, reject) => {
iot.createKeysAndCertificate(params, function(err, data){
if(err){
console.log(err);
reject(err)
}
else{
console.log("success?");
resolve(data)
}
})
})
}
I get a ResourceNotFound exception for calling createKeysAndCertificate. I also tried calling other functions of iot, but it gives the same exception.
What am I doing wrong here?
endpoint passed when intialzing an object should be generic AWS service in format https://{service}.{region}.amazonaws.com. we don't need to pass it, AWS will assume based on region and object we are initializing.
var iot = new AWS.Iot({
endpoint: 'iot.ap-south-1.amazonaws.com',
accessKeyId: "AAAABBBBBCCCCDDDDD",
secretAccessKey: "AAAAABBBBCCCDD/1234122311222",
region: 'ap-south-1'
});
Related
I am trying to access cross-account API in AWS using the assumed role. The roles are configured correctly.
I am able to invoke API for the first and after that till the session duration, I am getting something like the following error. I am not sure how to handle this to make every request success. Please help.
Error: AccessDenied: User: arn:aws:sts::xxxxxxxxxx:assumed-role is not authorized to perform: sts:AssumeRole on resource: arn:aws:iam::xxxxx:role/assume-role
const AWS = require('aws-sdk')
var aws4 = require('aws4');
const REGION = process.env.REGION || 'eu-west-1';
const ASSUME_ROLE_ARN = process.env.ASSUME_ROLE_ARN || '';
const API_ID_PARAMETER = process.env.EXT_API_ID_PARAMETER || '/test/gl/module/dev/testapi';
exports.handler = async(event) => {
console.log('received event')
console.log('ASSUME_ROLE_ARN:' + ASSUME_ROLE_ARN);
console.log('API_ID_PARAMETER:' + EXT_API_ID_PARAMETER);
var sts = new AWS.STS({
region: REGION
});
console.log('sts success')
const getCrossAccountCredentials = async() => {
return new Promise((resolve, reject) => {
const timestamp = (new Date()).getTime();
const params = {
RoleArn: 'arn:aws:iam::XXXXXXXXXXX:role/assume-role',
RoleSessionName: `be-descriptibe-here-${timestamp}`,
DurationSeconds: 3600
};
console.log('RoleSessionName : ' + params.RoleSessionName)
sts.assumeRole(params, (err, data) => {
if (err)
reject(err);
else {
resolve({
accessKeyId: data.Credentials.AccessKeyId,
secretAccessKey: data.Credentials.SecretAccessKey,
sessionToken: data.Credentials.SessionToken,
});
}
});
});
}
try {
const tempdata = await getCrossAccountCredentials();
var data = JSON.parse(JSON.stringify(tempdata));
console.log(data);
console.log(data.accessKeyId);
console.log(data.secretAccessKey);
AWS.config.update({
accessKeyId: data.accessKeyId,
secretAccessKey: data.secretAccessKey,
sessionToken: data.sessionToken
});
const creds = {
accessKeyId: data.accessKeyId,
secretAccessKey: data.secretAccessKey,
sessionToken: data.sessionToken
};
console.log('AWS.SSM start')
var ssm = new AWS.SSM({
apiVersion: '2014-11-06',
region: REGION,
credentials: creds
});
console.log('AWS.SSM end')
const {
Parameter
} = await ssm
.getParameter({
Name: EXT_API_ID_PARAMETER
})
.promise();
console.log(Parameter.Value)
let request = {
host: `${Parameter.Value}.execute-api.eu-west-1.amazonaws.com`,
method: 'GET',
url: `https://${Parameter.Value}.execute-api.eu-west-1.amazonaws.com/dev/test/1`,
path: '/dev/test/1'
};
let signedRequest = aws4.sign(request, creds);
delete signedRequest.headers['Host'];
delete signedRequest.headers['Content-Length'];
const res = await axios(signedRequest);
console.log('Data:', res.data);
} catch (err) {
console.log('Error:', err);
}
};
[EDIT]
I am new to AWS and I've been trying to make a real-time chat application. I saw this code, so I might as well try this. I tried to follow everything but it seems there is a problem.
[END]
I got an error with this code stating, Cannot read "domainName" of undefined which got me confused. Is this because of my API Gateway? I already connected this to another route named "Message" and I already have the integration request of my connect and disconnect.
Below is my code:
const AWS = require('aws-sdk');
const db = new AWS.DynamoDB.DocumentClient({region: 'us-east-1'});
require('./index.js');
let send = undefined;
function init(event) {
console.log(event);
const apigwManagementApi = new AWS.ApiGatewayManagementApi({
apiVersion: '2018-11-29',
endpoint: event.requestContext.domainName + '/' + event.requestContext.stage
});
send = async (connectionId, data) => {
await apigwManagementApi.postToConnection({
ConnectionId: connectionId,
Data: `Echo: ${data}` }).promise();
}}
exports.handler = (event, context, callback) => {
init(event);
let message = JSON.parse(event.body).message;
getConnections().then((data) => {
console.log(data.Items);
callback(null, {
statusCode: 200,
});
data.Items.forEach(function(connection) {
console.log("Connection " +connection.connection_id);
send(connection.connection_id, message);
});
});
return {};
};
function getConnections(){
const params = {
TableName: 'GroupChat',
}
return db.scan(params).promise();
}
I am trying to scan the Dynamodb table form my following code, can anyone please guide me what is wrong here.
const AWS = require("aws-sdk");
const dynamodb = new AWS.DynamoDB({
region: "eu-west-1",
apiVersion: "2012-08-10"
});
exports.handler = async (event, callback) => {
const params = {
TableName: "job_Status"
};
dynamodb.scan(params, (err, data) => {
if (err) {
console.log(err);
callback(err);
} else {
console.log(data);
callback(null, data);
}
});
};
I have given full dynamodb access role to the function but still it gives me the null response. Any idea what can be wrong here?
Response:
I tried with dynaomClient which not working too.
const AWS = require("aws-sdk");
const db = new AWS.DynamoDB.DocumentClient({
region : 'eu-west-1'
});
exports.handler = async (event, callback) => {
const params = {
TableName: "job_Status"
};
db.scan(params, (err, data) => {
if (err) {
console.log(err);
callback(err);
} else {
console.log(data);
callback(null, data);
}
});
};
Your Lambda function is async but your code uses callbacks. By the time the callback is reached, your function has already been terminated because it ran asynchronously. I'd speculate that the null output you see is the return value from the Lambda function, not your console.log.
Replace your call to scan with the following:
try{
let results = await db.scan(params).promise()
console.log(results);
} catch(err){
console.log(err)
}
For more info, check out the AWS documentation about working with promises.
I am trying to do a pretty simple "hello world" in AWS Lambda. I tried a few services that only call the AWS SDK and just try to read. My callback never gets called. I have to be missing something. Any help appreciated!
var AWS = require("aws-sdk");
exports.handler = async (event) => {
// TODO implement
const response = {
statusCode: 200,
body: JSON.stringify('Hello from Lambda!'),
};
var s3 = new AWS.S3(); // confirmed this is not null
s3.listBuckets({}, function(err, data) {
// never reaches here!
if (err) console.log(err, err.stack); // an error occurred
else console.log(data); // successful response
});
return response;
};
I did create a role this lambda is using that has S3 access. :-)
It seems that because I chose the Node 8.x runtime, I needed to use one of those async constructs. This worked...
let AWS = require('aws-sdk');
let s3 = new AWS.S3();
exports.handler = async (event) => {
return await s3.listBuckets().promise() ;
};
This is a synchronization problem.
Your return response code is executed before your callback is invoked.
you'll have to put your return statement inside your callback or use async/await
Returning inside your callback:
var AWS = require("aws-sdk");
exports.handler = async (event) => {
const response = {
statusCode: 200,
body: JSON.stringify('Hello from Lambda!'),
};
var s3 = new AWS.S3();
s3.listBuckets({}, function (err, data) {
if (err) {
console.log(err, err.stack);
return {
statusCode: 500,
message: 'some error'
}
}
return response
});
}
Using async/await:
var AWS = require("aws-sdk");
exports.handler = async (event) => {
const response = {
statusCode: 200
};
var s3 = new AWS.S3();
await s3.listBuckets().promise();
return response;
}
I'd go with the async/await approach as it's much cleaner and more readable. It's also easier to work with promises than with callbacks.
EDIT: The OP claimed it didn't work. So I have decided to test it on my own. The above code works, with a very small change just to add the listed buckets to the response. Here's the final code:
var AWS = require("aws-sdk");
exports.handler = async (event) => {
const response = {
statusCode: 200
};
var s3 = new AWS.S3();
const buckets = await s3.listBuckets().promise();
response.body = JSON.stringify(buckets);
return response;
}
And here's the output in CloudWatch Logs:
I have an AWS Lambda function which is being triggered by AWS DynamoDB. The function checks if the operation in the DB is INSERT, and if it does, then it sends a new push message using AWS SNS:
console.log('Loading function');
var AWS = require('aws-sdk');
AWS.config.region = 'us-east-1';
exports.handler = function(event, context, callback) {
console.log("\n\nLoading handler\n\n");
var sns = new AWS.SNS();
console.log(JSON.stringify(event, null, 2));
event.Records.forEach(function(record) {
if (record.eventName == "INSERT") {
sns.publish({
Subject: 'Test',
Message: 'Test publish to SNS from Lambda',
TopicArn: 'TOPIC-ARN'
}, function(err, data) {
if (err) {
console.log(err.stack);
return;
}
console.log('push sent');
console.log(data);
context.done(null, 'Function Finished!');
});
}
});
callback(null, "message");
};
Is there a way that I could get the attributes of the newly added item?
var id = record.dynamodb.Keys.Id.N;