I am just attempting to call describeEndpoints of mediaconvert SDK but seems like it times out, why could that be. I already gave my Lambda function admin access. I set timeout to 30s which should be more than sufficient but it still fails
const AWS = require('aws-sdk');
const util = require('util');
async function test() {
let mediaconvert = new AWS.MediaConvert();
const describeEndpoints = util
.promisify(mediaconvert.describeEndpoints)
.bind(mediaconvert);
return await describeEndpoints()
}
Have you launched lambda in vpc ? if so, check if it has nat gateway , lambda doesn't work with subnet with route igw.
Use this instead of describing then:
const mediaConvert = new AWS.MediaConvert(
{ endpoint: 'MEDIACONVERT REGIONAL API ENDPOINT', });
Related
According to this documentation in GCP if a cloud function is connected to a VPC through Serverless VPC accessor and all the egress traffic from the function is routed to Serverless VPC accessor, the cloud function should not have access to internet. This is working fine for other APIs but Google APIs are still accessible.
I was connecting BigQuery from Cloud Function(Nodejs) privately using Serverless VPC accessor. So I expect the function to fail when I route all the egress traffic from the function to the Serverless VPC accessor because I haven't added the Cloud NAT. If I try to access any API other than google APIs (using node-fetch) it is failing as expected.
Please note: Default internet gateway is present in the VPC subnet
Cloud function codes:
Cloud function accessing BigQuery - It is expected to fail but working
const {BigQuery} = require('#google-cloud/bigquery');
const bigquery = new BigQuery();
exports.getCountries = async (req, res) => {
const query = "SELECT DISTINCT country_name FROM `bigquery-358204.covid_19_data.covid19_open_data` ORDER BY country_name;";
const options = {
query: query,
location: 'US',
};
// Run the query as a job
const [job] = await bigquery.createQueryJob(options);
console.log(`Job ${job.id} started.`);
// Wait for the query to finish
const [rows] = await job.getQueryResults();
let message = JSON.stringify(rows);
res.status(200).send(message);
};
Cloud function accessing an API other than google APIs - It is failing as expected
const fetch = require('node-fetch')
exports.helloWorld = async (req, res) => {
let resp = await fetch('https://www.7timer.info/bin/astro.php?lon=113.2&lat=23.1&ac=0&unit=metric&output=json&tzshift=0');
let body = await resp.json()
res.status(200).send(body)
};
In our system we have a flow of Lambdas calling other Lambdas based on results they get.
This flow will probably be refactor to use the AWS step function in the future but will probably stay as it is for the next month or two.
Recently a new lambda has been introduced, and we're encountering a problem:
if we test our Lambda function 1 locally, it properly calls function 2 on AWS.
However, after deploying the lambda and running the same test, function doesn't get called (there's no invocation in the monitoring chart)
here's a code example of Function 1:
'use strict';
const AWS = require("aws-sdk");
const lambda = new AWS.Lambda({ region: "eu-west-1" });
const myHandler = async (event, _, callback) => {
console.log(event)
return doSomething()
.then(something)
.then(somethingElse)
.catch(handleError)
function doSomething() {
return fetch('someurl.com');
}
function something(r) {
if(r.status === 204) {
let lambdaRes = callLambda( "LambdaB", { foo: bar } );
console.log(lambdaRes)
}
return r
}
somethingElse(r) {
if(r.status === 500) {
throw new Error(`bar`);
}
return r.json()
}
async function callLambda(fnName, payload ) {
let params = {
FunctionName: fnName,
InvocationType: 'Event',
Payload: JSON.stringify(payload)
}
return await lambda.invoke(params);
}
function handleError(e) {
if(e.message === 'bar') {
let lambdaRes = callLambda( "LambdaC", { bar: 'foo' } );
console.log(lambdaRes)
}
return callback(null, { message: `Completed with error`});
}
exports.handler = myHandler;
We tried to check if the problem was caused by authorization and tested by providing ALL authorization possible to function 1 but with no results.
Any suggestion?
UPDATE:
Both Function use the same
VPC: vpc-hashnumberVpc,
Subnets: [ subnet-hashnumber1 , subnet-hashnumber2 , subnet-hashnumber3 ]
Security Group: sg-hashnumberSg
When the first Lambda function calls lambda.invoke() it is not somehow connecting to the other Lambda function inside the VPC. At that point there is no running instance of the other Lambda function, only the definition of it exists. What is happening is lambda.invoke() makes a call to the AWS API which is on the public Internet, requesting that AWS create a new invocation of the second function.
Lambda functions running inside a VPC do not get public IP addresses assigned to them, even if they are in a public subnet. The only way to give a Lambda function inside a VPC access to the Internet is to place the Lambda function in a private subnet with a route to a NAT Gateway.
Alternatively, you can configure an AWS Lambda VPC Endpoint, which gives resources inside your VPC access to call the AWS Lambda API without going over the Internet.
So in order for a Lambda function running inside a VPC to make AWS API calls to invoke other Lambda functions, your options are to add a NAT Gateway to the VPC, or add an AWS Lambda VPC Endpoint to the VPC.
So if function 1 is able to call function 2 locally, I think the problem is with networking/AWS setup, here are a few things you can do :
Set up Log/Print statements at every level, so you can pinpoint which line is returning an error.
Is the function timing out? If so check the timeout and Memory Allocated to the function, if the function is memory intensive it will not complete.
Last but very important , check your network/Subnets, if you have configured lambda to be running on multiple subnets, choose one of them and try, look at the VPC, perhaps the Lambda is not attached to any VPC or check if the attached vpc is able to connect to the other lambda, have a look at Security Groups as well.
Most of my lambda issues are resolved with this, all the best.
My goal is to send a SMS message through AWS Pinpoint using NodeJS and the AWS Pinpoint Gateway from behind a VPC. The code I am using works well on my local machine and in SAM where there are no VPC restrictions. I added a SNS and SMS VPC endpoint with security groups that give me access to each service individually. I can send an SMS using the aws-sdk SNS service.
I cannot seem to get Lambda to use pinpoint to send an SMS message. Is this possible? I cannot seem to find ports for the Pinpoint service? Is it possible to avoid exposing internet access to the VPN to send messages through AWS Pinpoint?
Role: Assigned All Pinpoint roles, SMS and SNS permissions for testing.
Message Configuration:
const AWS = require("aws-sdk");
AWS.config.update({region: process.env.SMS_REGION});
const PINPOINT = new AWS.Pinpoint({apiVersion: '2016-12-01'});
const PINPOINT_APP_ID = process.env.PINPOINT_APP_ID;
const params = {
ApplicationId: PINPOINT_APP_ID,
MessageRequest: {
Addresses: {
[number]: {
ChannelType: 'SMS'
}
},
MessageConfiguration: {
SMSMessage: {
Body: message,
OriginationNumber: origination_number,
SenderId: "senderId",
MessageType: process.env.SMS_MESSAGE_TYPE
}
}
}
};
await PINPOINT.sendMessages(params, (err, data) => {});
Region: us-west-2
There are no VPC interface endpoints for AWS Pinpoint, as shown in this AWS list. Therefore, you need to go through internet to access the service.
For your lambda, you have to place it in private subnet with NAT gateway in public subnet. Thanks to the NAT, your lambda function will be able to access pinpoint service.
The alternative would be to use private API gateway which integrates with other lambda as a proxy. Not ideal solution, but at the end of the day you have to go through internet, one way or the other.
Trying to call AWS Firehose service's PutRecord using AWS SDK from Lambda Function that located in different region using NodeJS environment. This works when Lambda Function and Firehose are in same region and not working when Function is in other region. Is there a setting of Firehose or IAM role attached to it that could allow these inter region calls?
You just specify the region name in your sdk. For example, the following should be enough in Python:
import boto3
client = boto3.client('firehose', region_name='us-west-2')
client.put_record(...)
No other special settings should be required.
In nodejs, it would be:
var fh = new AWS.Firehose({region: 'us-west-2'});
Problem was that I've set region incorrectly. Instead of specifying region just for Firehose, need to specify region for SDK:
Insted of:
const AWS = require('aws-sdk');
const firehose = new AWS.Firehose({ region: 'us-east-1' });
Using:
const AWS = require('aws-sdk');
AWS.config.update({ region: 'us-east-1' });
const firehose = new AWS.Firehose();
I am running a Node(12.x) Lambda in AWS. The purpose of this lambda is to interact with Cloudformation stacks, and I'm doing that via the aws-sdk. When testing this lambda locally using lambda-local, it executes successfully and the stack can be seen in CREATING state in AWS console.
However, when I push and run this lambda in AWS, it fails after 15 seconds, and I get this error:
{"errorType":"TimeoutError","errorMessage":"Socket timed out without establishing a connection","code":"TimeoutError","message":"Socket timed out without establishing a connection","time":"2020-06-29T03:10:27.668Z","region":"us-east-1","hostname":"cloudformation.us-east-1.amazonaws.com","retryable":true,"stack":["TimeoutError: Socket timed out without establishing a connection"," at Timeout.connectTimeout [as _onTimeout] (/var/task/node_modules/aws-sdk/lib/http/node.js:69:15)"," at listOnTimeout (internal/timers.js:549:17)"," at processTimers (internal/timers.js:492:7)"]}
This lead me to investigate the lambda timeout and the possible configuration changes I could make found in https://aws.amazon.com/premiumsupport/knowledge-center/lambda-function-retry-timeout-sdk/ and https://aws.amazon.com/premiumsupport/knowledge-center/lambda-vpc-troubleshoot-timeout/ but nothing worked.
I found a couple of similar issues such as AWS Lambda: Task timed out which include possible suggestions such as lambda timeout and lambda memory issues, but Ive set mine to 30 seconds and the logs show max memory used is 88MB out of possible 128MB, but I tried with an increase anyway, and no luck.
The curious part is that it fails without establishing a connection to hostname cloudformation.us-east-1.amazonaws.com. How is that possible when the role assigned to the lambda has full Cloudformation privileges? I'm completely out of ideas so any help would be greatly appreciated. Heres my code:
TEST EVENT:
{
"stackName": "mySuccessfulStack",
"app": "test"
}
Function my handler calls (createStack):
const AWS = require('aws-sdk');
const templates = {
"test": {
TemplateURL: "https://<bucket>.s3.amazonaws.com/<path_to_file>/test.template",
Capabilities: ["CAPABILITY_IAM"],
Parameters: {
"HostingBucket": "test-hosting-bucket"
}
}
}
async function createStack(event) {
AWS.config.update({
maxRetries: 2,
httpOptions: {
timeout: 30000,
connectTimeout: 5000
}
});
const cloudformation = new AWS.CloudFormation();
const { app, stackName } = event;
let stackParams = templates[app];
stackParams['StackName'] = app + "-" + stackName;
let formattedTemplateParams = [];
for (let [key, value] of Object.entries(stackParams.Parameters)) {
formattedTemplateParams.push({"ParameterKey":key, "ParameterValue": value})
}
stackParams['Parameters'] = formattedTemplateParams;
const result = await cloudformation.createStack(stackParams).promise();
return result;
}
Lambda function in a VPC does not public IP address nor internet access. From docs:
Connect your function to private subnets to access private resources. If your function needs internet access, use NAT. Connecting a function to a public subnet does not give it internet access or a public IP address.
There are two common solutions for that:
place lambda function in a private subnet and setup NAT gateway in public subnet. Then set route table from private subnet to the NAT device. This will enable the lambda to access the internet and subsequently CloudFormation service.
setup a VPC interface endpoint for CloudFormation. This will allow your lambda function in private subnet to access CloudFormation without the internet.