Lambda Function URL in a public subnet? - amazon-web-services

Note: I am NOT asking why a Lambda in a subnet cannot access the public internet.
I would like to host a Lambda function, with the Function URL enabled, in a public subnet and expose it via CloudFront. This is so that the function can be called from the broader internet but also access private resources.
Is this possible?
I have tried creating a very simple Lambda (the default generated by the serverless.AspNetCoreMinimalAPI template) and uploading to a simple function with Function URL enabled. With just that, I can call the Lambda from (eg) Postman.
The moment I attach it to the public subnet of my VPC I get 502 Bad gateway even with an Internet Gateway attached to the VPC.

I read your question a few times to make sure I understand what you are trying to do. The way you ask the question, the answer is no.
If you take out the CloudFront requirement, then of course it is possible and it works perfectly; you can easily access the lambda URL from anywhere, including the Internet. With the CloudFront requirement, it is still possible to achieve what you're trying to do, but you have to do it in a different manner. The URL to be accessed is not the URL of the lambda function; you have to access the URL of the CloudFront distribution and when you do that it triggers your lambda function to run from the CloudFront distribution edge locations and this is the reason the usage of a lambda function is this case is called Lambda#Edge. Now, don't let that confuse you; it's just a regular lambda function that gets deployed to the CloudFront distribution edge locations. The main steps to implement what you're looking for are:
Create a CloudFront distribution
Create your function [You are limited to NodeJS and Python]
Add a CloudFront trigger to run the function
For detailed instructions, follow the steps outline here. I am sure it will work.

Yes, it is possible. You need to add a NAT Gateway to your VPC and attach it to your public subnet. Then you need to add a route to your route table to route all traffic to the NAT Gateway. You can find more information here: https://docs.aws.amazon.com/lambda/latest/dg/configuration-vpc.html

You can use an API gateway in front of your Lambda, and keep all your ressources in private subnet (to keep them fully secured).
You'll no longer need a public url for your lambda, the api gateway has mapping routes, so you can use them.
You may add a cloudFront to the api gateway, only if you need to expose other static contents or api's. If not, you can use a Route53 - a custom domain name - attached to your api gateway. And it'll be fully enough

You can try creating VPC endpoints for your existing VPC according to aws docs.
Interface VPC endpoints allow communication with AWS services from your VPC without requiring access to the public internet. Traffic to the configured service will be routed through the endpoint directly to the service.
Another approach is to have NAT Gateway to your VPC which enables your lambda to be accessed through your public subnet. You may need to have route specified in route table. Also having Nat gateway would cost you little more compared to VPC endpoints.

Related

Why can an API GW access a lambda that's in a private VPC?

I'm new to AWS and struggling to understand how they've laid out their components, especially around networking & access.
In this case, I'm toying with an API GW and a "hello world" lambda. I made the lambda (no VPC) and hooked it up to an API GW, and now I have a publicly-accessible lambda. I didn't understand why the lambda was callable without being in a VPC, but I finally stumbled upon this explanation in the docs: https://docs.aws.amazon.com/lambda/latest/dg/configuration-vpc.html#vpc-internet
Seems weird to default open, but okay.
So, now I'm trying to close off the API via the networking-related config. So I created a VPC & private subnets (no IGW, NOT publicly accessible), and put the lambda in there. I felt confident it would no longer be accessible, 'cuz that's how VPC & networking works, yet the lambda is still publicly accessible! Why?
The API GW doesn't have access to this VPC, and in any case, this VPC doesn't have internet access. The way these components are interacting doesn't seem to make sense. What's going on here?
API Gateway allows you to create private endpoints as well as public ones. It sounds like you want a private endpoint.
My mistake was thinking lambdas can be put in a VPC. Rather, they can only be given access to a VPC:
Configuring a Lambda function to access resources in a VPC
You can configure a Lambda function to connect to private subnets in a virtual private cloud (VPC) in your AWS account.
https://docs.aws.amazon.com/lambda/latest/dg/configuration-vpc.html
So all my comments about VPC logic don't apply, and that's why my lambda is publicly accessible.
Furthermore, in case this is helpful to others:
I originally had the misconception that all AWS components were basically servers, and they all needed to be put in VPCs. This pattern does not apply to serverless components! (including S3, lambda, dynamoDB, etc) These operate in their own area, and the point of the component is to (mostly) abstract away things like networking details. Instead, they tend to control access via other methods, like IAM policies, security groups, "integrations", etc
Check for Internet Gateway, Nat gateway. Check for the actual VPC the LAMDA is connected to, sometimes having multiple can be confusing and lastly also check the VPC End point

AWS Lambda HTTP accessible from the internet, but not accessible from an EC2 on the same account

I have a lambda function, that has an API Gateway attached to it. It has a publicly accessible IP address and a domain name (Created by the serverless framework). I can access it from the broad internet, from my own browser (and other devices).
The issue is, it seems to be inaccessible from other services on my account, like an EC2 instance. From the mentioned instance, curl google.com works and returns a response, but curl mylink.com times out.
I think this has something to do with VPC setup, but I can't put my finger at it. What might be the issue here?
Update: Using curl --verbose, I found out that while accessed from anywhere else, the IP the API Gateway is leading to is different, than when accessed from within my AWS account. The VPC doesn't seem to matter, I created a new VPC, an EC2 instance inside it, and it still did the same.
Based on the comments.
The issue was caused by the presence of VPC interface endpoint for API Gateway in the default VPC. The VPC interface endpoint for API gateway is used for private API, not public APIs as used be the OP. Subsequently, calls to public API endpoints fail, as explained in AWS blog:
When they’re configured as private, the public networks are not made available to route your API. Instead, your API can only be accessed using the interface endpoints that you have configured.
There are two ways to combat the issue:
disable Private DNS Name option for the endpoint, or
remove the endpoint.
In the OP's case, the second option was used to solve the problem.
The EC2 instance likely lives inside a VPC which doesn't have public internet access (or may but through a load balancer, bastion host, or any myriad of other options).
You'll need to find out which VPC the EC2 instance lives in, and ensure your lambda function has access to it. You can add a function to a VPC by following the documentation

How to configure aws lambda to send api requests with ip address

Recently I am trying to use api for trading without much knowing about the theories. And successfully create a working function and deployed it in aws lambda . Now I am trying some another exchanges and their api creation forms have place for ip address .
I tried searching on internet about this, but did not find anything.
I think the request need to send from the ip address.
Can someone tell me how to tackle this problem. Can I simply change something in lambda and do the thing??
Can I simply change something in lambda and do the thing??
You have to setup a VPC with private subnet and a NAT gateway in a public subnet if you don't have such VPC already. Then you associate your lambda function with the private subnet.
This way your lambda function will access the external api using the NAT. The good thing about NAT is that it has static public IP which you can whitelist at your API provider.

Public IP address for AWS API Gateway & Lambda (no VPC)

I have provisioned an AWS API Gateway and created a Lambda function to connect to an external REST API. The API Gateway & Lambda is not in a VPC so the egress IP address is random. The challenge I have is the external REST API is behind a firewall, which requires the IP address or subnet of the Lambda to be whitelisted.
I have looked at the AWS IP Address page (below), however there is no explicit mention of either API Gateway or Lambda.
https://docs.aws.amazon.com/general/latest/gr/aws-ip-ranges.html#filter-json-file
Has anyone come across this before & found a resolution to it. For the purposes of this solution I cannot put the API Gateway & Lambdas in a VPC.
Any help would be greatly appreciated!
API Gateway seems to be irrelevant to this discussion. If I understand your question, you're trying to make API requests from a Lambda function to a remote API server and you want those requests to originate from a known IP address so that you can whitelist that IP at the remote server.
First thing I would say is don't use IP whitelisting; use authenticated API requests instead.
If that's not possible then use VPC with an Internet Gateway (IGW). Create a NAT and an Elastic IP, launch the Lambda into a private subnet of that VPC, and route the subnet's non-local traffic to the NAT. Then whitelist the NAT's Elastic IP on the remote API server. Examples here and here.
I know that you said you "cannot put [...] Lambdas in a VPC", but if you don't then you have no control over the originating IP address.
It is frustrating that the only way to ensure a Lambda function uses a static ip without a hack is to put the Lambda inside a VPC, create a NAT with an Elastic IP, as many other answers nicely explain.
However, NATs cost around $40 per month in regions that I am familiar with, even with minimal traffic. This may be cost prohibitive for certain use cases, such as if you need multiple dev/test/staging environments.
One possible workaround (which should be used with caution) is to create a micro EC2 instance with an elastic IP (which gives the static IP address), then your choice of proxy/routing so you can make HTTP calls by tunnelling from the Lambda function through the EC2 instance. (e.g. SSH from Lambda function into EC2 instance then CURL from EC2 to the endpoint which is protected by an allowlist)
This is a few extra hoops to jump through and could introduce security vulnerabilities which should be mitigated (e.g. Beware storing SSH keys or passwords inside a Lambda function, ensure Security Groups are tight) but I wanted to post this as a possible workaround for any devs who need a cost effective workaround for a requirement to connect to an endpoint which enforces allowlist rules.

AWS Apigateway does have any static IP address

I have an aws api gateway which has a custom domain.
I have to access one of client's api from AWS api gateway.
Those api's will be accessible based on IP address.
If I want to access those api's from aws, I need to know the Ip address of my AWS apigateway.
But I am not sure where I can get this.
Any possibilities to get the static IP address of AWS apigateway?
Unfortunately the API Gateway doesn't support this scenario of invoking an IP-whitelisted API directly. Basically any AWS instance can be used to make the API call and there's many IPs that AWS is using for this.
There are some ways around this, depending on your situation;
If the server you are reaching is within your own VPC, you could create a VPC link (with NLB) and circumvent the IP-whitelist issue. This solution only works for resources within your control.
If the server is external and is expecting a static IP, your best solution is to make your call from within a VPC. To make sure you have a static public IP you can use an elastic IP and a NAT Gateway in your VPC (more info here).
To invoke the external API triggered from the API Gateway you can use a Lambda but because of the VPC a cold start will be quite slow, >10s. To make sure the API will be responding fast you can use an EC2 instance or ECS service on Fargate.
After you clarified your requirements in the comments above it appears that you need your AWS Lambda function, which is being triggered by API Gateway, to appear to a third party as if it has a static outgoing IP address.
The solution to this is to configure your Lambda function to run in your VPC, in a private subnet of your VPC that has a route to a NAT Gateway. Then all outgoing connections from the Lambda function which access resources outside your VPC will use the NAT Gateway's static IP address.