I'm trying to assign a static ip to multiple lambdas so that when a lambda makes a call to a specific service I can whitelist that ip.
I was able to get this working but as far as I can tell, it will randomly start either taking almost exactly 2 minutes to return where before it was 500ms or just start timing out all together.
Below is the cloudformation I used to setup this VPC and in this cloudformation I setup the following:
Public Subnet
Private Subnet
NAT Gateway
Elastic IP
2 Routes (public/private)
Internet Gateway
{
"AWSTemplateFormatVersion": "2010-09-09",
"Description": "AWS CloudFormation for VPC",
"Parameters": {
"env": {
"Type": "String"
}
},
"Resources": {
"VPCStaticIP": {
"Type": "AWS::EC2::VPC",
"Properties": {
"CidrBlock": "11.0.0.0/16",
"Tags": [
{
"Key": "Name",
"Value": {
"Fn::Join": [
"",
["lambavpc", "-", { "Ref": "env" }]
]
}
}
]
}
},
"SubnetPublic": {
"Type": "AWS::EC2::Subnet",
"Properties": {
"CidrBlock": "11.0.0.0/24",
"Tags": [
{
"Key": "Name",
"Value": {
"Fn::Join": [
"",
[
"lambavpc",
"-",
{ "Ref": "env" },
"-",
"public-subnet"
]
]
}
}
],
"VpcId": {
"Ref": "VPCStaticIP"
}
}
},
"SubnetPrivate": {
"Type": "AWS::EC2::Subnet",
"Properties": {
"CidrBlock": "11.0.1.0/24",
"Tags": [
{
"Key": "Name",
"Value": {
"Fn::Join": [
"",
[
"lambavpc",
"-",
{ "Ref": "env" },
"-",
"private-subnet"
]
]
}
}
],
"VpcId": {
"Ref": "VPCStaticIP"
}
}
},
"InternetGateway": {
"Type": "AWS::EC2::InternetGateway",
"Properties": {
"Tags": [
{
"Key": "Name",
"Value": {
"Fn::Join": [
"",
["lambavpc", "-", { "Ref": "env" }, "-", "igw"]
]
}
}
]
}
},
"VPCGatewayAttachment": {
"Type": "AWS::EC2::VPCGatewayAttachment",
"Properties": {
"InternetGatewayId": {
"Ref": "InternetGateway"
},
"VpcId": {
"Ref": "VPCStaticIP"
}
}
},
"RouteTablePublic": {
"Type": "AWS::EC2::RouteTable",
"Properties": {
"VpcId": {
"Ref": "VPCStaticIP"
},
"Tags": [
{
"Key": "Name",
"Value": {
"Fn::Join": [
"",
[
"lambavpc",
"-",
{ "Ref": "env" },
"-",
"public-route"
]
]
}
}
]
}
},
"RoutePublic": {
"Type": "AWS::EC2::Route",
"Properties": {
"DestinationCidrBlock": "0.0.0.0/0",
"GatewayId": {
"Ref": "InternetGateway"
},
"RouteTableId": {
"Ref": "RouteTablePublic"
}
}
},
"SubnetRouteTableAssociationPublic": {
"Type": "AWS::EC2::SubnetRouteTableAssociation",
"Properties": {
"RouteTableId": {
"Ref": "RouteTablePublic"
},
"SubnetId": {
"Ref": "SubnetPublic"
}
}
},
"EIP": {
"Type": "AWS::EC2::EIP",
"Properties": {
"Domain": "vpc",
"Tags": [
{
"Key": "Name",
"Value": {
"Fn::Join": [
"",
["lambavpc", "-", { "Ref": "env" }, "-", "eip"]
]
}
}
]
}
},
"NatGateway": {
"Type": "AWS::EC2::NatGateway",
"Properties": {
"AllocationId": {
"Fn::GetAtt": ["EIP", "AllocationId"]
},
"SubnetId": {
"Ref": "SubnetPublic"
}
}
},
"RouteTablePrivate": {
"Type": "AWS::EC2::RouteTable",
"Properties": {
"VpcId": {
"Ref": "VPCStaticIP"
},
"Tags": [
{
"Key": "Name",
"Value": {
"Fn::Join": [
"",
[
"lambavpc",
"-",
{ "Ref": "env" },
"-",
"private-route"
]
]
}
}
]
}
},
"RoutePrivate": {
"Type": "AWS::EC2::Route",
"Properties": {
"DestinationCidrBlock": "0.0.0.0/0",
"NatGatewayId": {
"Ref": "NatGateway"
},
"RouteTableId": {
"Ref": "RouteTablePrivate"
}
}
},
"SubnetRouteTableMainAssociationPrivate": {
"Type": "AWS::EC2::SubnetRouteTableAssociation",
"Properties": {
"RouteTableId": {
"Ref": "RouteTablePrivate"
},
"SubnetId": {
"Ref": "SubnetPrivate"
}
}
}
},
"Outputs": {}
}
I've done quite a bit of research and turned up these references:
https://gist.github.com/reggi/dc5f2620b7b4f515e68e46255ac042a7
AWS Lambda: How to set up a NAT gateway for a lambda function with VPC access
but I can't seem to reason what the delta is between what I'm doing and what they are suggesting.
Any suggestions would be greatly appreciated it!
The EIP timeouts probably because you do not have DependsOn attribute on your AWS::EC2::VPCGatewayAttachment. This is required in your case:
If you define an Elastic IP address and associate it with a VPC that is defined in the same template, you must declare a dependency on the VPC-gateway attachment by using the DependsOn Attribute on this resource.
Thus, you could try the following which adds the dependency:
"EIP": {
"Type": "AWS::EC2::EIP",
"DependsOn" : "VPCGatewayAttachment",
"Properties": {
"Domain": "vpc",
"Tags": [
{
"Key": "Name",
"Value": {
"Fn::Join": [
"",
["lambavpc", "-", { "Ref": "env" }, "-", "eip"]
]
}
}
]
}
}
Also, if possible, I would consider using a private IP range of 10.0.0.0/16 for your VPC and subnets instead of 11.0.0.0/16. The range is recommended to be used by AWS:
When you create a VPC, we recommend that you specify a CIDR block (of /16 or smaller) from the private IPv4 address ranges as specified in RFC 1918:
10.0.0.0 - 10.255.255.255 (10/8 prefix)
172.16.0.0 - 172.31.255.255 (172.16/12 prefix)
192.168.0.0 - 192.168.255.255 (192.168/16 prefix)
You don't show how you are creating the Lambda function, is that created outside of CloudFormation? It sounds like you have the Lambda function configured to use both VPC subnets, and when it runs inside the public subnet it is getting timeouts. You need to configure the Lambda function to only use the private subnet with a route to the NAT Gateway.
Related
I'm using AWS CDK and it is failing at App-Load-Balancer level and surprisingly it works for Web-Load-balancer. Looking at generated CloudFormation, it is clear that all "Private Subnets" are getting created in separated AZ and associated Auto-Scaling Group too is creating the instance across multiple-AZs. However, when the CDK is executed, it is failing with the error message - A load balancer cannot be attached to multiple subnets in the same Availability Zone (Service: AmazonElasticLoadBalancing; Status Co
de: 400; Error Code: InvalidConfigurationRequest; Request ID: 62c554cb-34ab-43ef-bac0-be2f0d6fc742; Proxy: null)
APP Server characteristics
AUTOSCALING CF Snippet:
"InstaLendaappASGapp1appsvrASG950CF7C4": {
"Type": "AWS::AutoScaling::AutoScalingGroup",
"Properties": {
"MaxSize": "3",
"MinSize": "1",
"DesiredCapacity": "2",
"LaunchConfigurationName": {
"Ref": "InstaLendaappASGapp1appsvrLaunchConfig18DAF6BB"
},
"Tags": [
{
"Key": "Name",
"PropagateAtLaunch": true,
"Value": "webapp-dc-3-tier-ha/InstaLend-a-appASG-app-1-appsvr-"
}
],
"TargetGroupARNs": [
{
"Ref": "InstaLendaapplbInstaLendalstnrPrivate80InstaLendatgtprivateGroup8D2C8D01"
}
],
"VPCZoneIdentifier": [
{
"Ref": "InstaLendavpcInstaLendaprivateSNSubnet1Subnet35AF6769"
},
{
"Ref": "InstaLendavpcInstaLendaprivateSNSubnet2SubnetD8513C5D"
},
{
"Ref": "InstaLendavpcInstaLendaprivateSNSubnet3SubnetB7B2D12C"
}
]
}
LOADBALANCER CF Snippet:
"InstaLendaapplbCC4F6682": {
"Type": "AWS::ElasticLoadBalancingV2::LoadBalancer",
"Properties": {
"LoadBalancerAttributes": [
{
"Key": "deletion_protection.enabled",
"Value": "false"
}
],
"Name": "InstaLend-a-app-lb",
"Scheme": "internal",
"SecurityGroups": [
{
"Fn::GetAtt": [
"InstaLendasginternal8649CE7C",
"GroupId"
]
}
],
"Subnets": [
{
"Ref": "InstaLendavpcInstaLendaprivateSNSubnet1Subnet35AF6769"
},
{
"Ref": "InstaLendavpcInstaLendaprivateSNSubnet2SubnetD8513C5D"
},
{
"Ref": "InstaLendavpcInstaLendaprivateSNSubnet3SubnetB7B2D12C"
},
{
"Ref": "InstaLendavpcInstaLendaprivateSNDBSubnet1Subnet2DD722D8"
},
{
"Ref": "InstaLendavpcInstaLendaprivateSNDBSubnet2Subnet59278CD3"
},
{
"Ref": "InstaLendavpcInstaLendaprivateSNDBSubnet3SubnetCC805230"
}
],
"Type": "application"
},
"UpdateReplacePolicy": "Delete",
"DeletionPolicy": "Delete",
"Metadata": {
"aws:cdk:path": "webapp-dc-3-tier-ha/InstaLend-a-app-lb/Resource"
}
}
While LB is selecting 6 subnets, ASG associated is selecting only 3 subnets. The details of 3 ASG Subnets (i.e. Private Subnets) had been pasted below:
1st SUBNET
"InstaLendavpcInstaLendaprivateSNSubnet1Subnet35AF6769": {
"Type": "AWS::EC2::Subnet",
"Properties": {
"CidrBlock": "10.2.3.0/24",
"VpcId": {
"Ref": "InstaLendavpcE5C8A638"
},
"AvailabilityZone": "us-east-2a",
"MapPublicIpOnLaunch": false,
"Tags": [
{
"Key": "aws-cdk:subnet-name",
"Value": "InstaLend-a-privateSN"
....
2nd SUBNET
"InstaLendavpcInstaLendaprivateSNSubnet2SubnetD8513C5D": {
"Type": "AWS::EC2::Subnet",
"Properties": {
"CidrBlock": "10.2.4.0/24",
"VpcId": {
"Ref": "InstaLendavpcE5C8A638"
},
"AvailabilityZone": "us-east-2b",
"MapPublicIpOnLaunch": false,
"Tags": [
{
"Key": "aws-cdk:subnet-name",
"Value": "InstaLend-a-privateSN"
},
{
"Key": "aws-cdk:subnet-type",
"Value": "Private"
},
....
3rd SUBNET
"Type": "AWS::EC2::Subnet",
"Properties": {
"CidrBlock": "10.2.5.0/24",
"VpcId": {
"Ref": "InstaLendavpcE5C8A638"
},
"AvailabilityZone": "us-east-2c",
"MapPublicIpOnLaunch": false,
"Tags": [
{
"Key": "aws-cdk:subnet-name",
"Value": "InstaLend-a-privateSN"
},
{
"Key": "aws-cdk:subnet-type",
"Value": "Private"
},
I'm trying to implement configuration management that meets the following criteria for an assighment:
https://s3.amazonaws.com/seis615/AnsiblePress.json
Take a quick look at the template in a text editor. Notice how the UserData property for the mgmt1 instance is configured. When CloudFormation launches this stack, it will automatically install and configure Ansible software on the management server. It’s very common to use a small amount of scripting code to bootstrap configuration management software onto a new system. Once Ansible is installed it can be used to install and configure other servers in the environment.
The CloudFormation template is missing a couple resources that you will need to add:
An application load balancer with a logical name of webserverlb which distributes HTTP (port 80) requests to the web1 and web2 instances. The health check endpoint for the load balancer should be the root (/) directory.
A db.t2.micro RDS database instance (not a cluster) running a MariaDB 10.2.21 database called wordpress located in a private VPC subnet. Use the logical name wordpressdb for the CloudFormation RDS resource. RDS and EC2 instances actually pre-date the arrival of VPCs in AWS so confusingly there are two different ways to configure these resources. You need to make sure this database instance is designed to run inside a VPC with the proper database subnet group and security group resources defined.
A security group called WebserverLbSecurityGroup which allows incoming http access from the Internet.
A security group called WordpressDbSecurityGroup which allows incoming access on the standard MySQL port from the WebServerSecurityGroup
An input parameter called DBName which will define the database name to create (default to wordpress)
An input parameter called DBUser which will be used for the database server username.
An input parameter called DBPassword which will be used for the database server password.
A stack output called wordpressDbEndpoint which shows the MariaDB instance endpoint address.
A stack output called wordpressLbEndpoint which shows the application load balancer URL.
The JSON I've configured (below) gives me the following template format error and I don't know why:
Template format error: Unresolved resource dependencies [wordpressVPC] in the Resources block of the template
{"AWSTemplateFormatVersion": "2010-09-09",
"Resources": {
"SSMAccessRole": {
"Type": "AWS::IAM::Role",
"Properties": {
"AssumeRolePolicyDocument": {
"Version" : "2012-10-17",
"Statement": [ {
"Effect": "Allow",
"Principal": {
"Service": [ "ec2.amazonaws.com" ]
},
"Action": [ "sts:AssumeRole" ]
} ]
},
"Path": "/"
}
},
"SSMRolePolicies": {
"Type": "AWS::IAM::Policy",
"Properties": {
"PolicyName": "ssmProperties",
"PolicyDocument": {
"Version" : "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"ssm:DescribeParameters",
"ssm:PutParameter",
"ssm:GetParameters",
"ssm:DeleteParameter"
],
"Resource": {
"Fn::Join" : [
"",
[
"arn:aws:ssm:",
{ "Ref" : "AWS::Region" },
":",
{ "Ref" : "AWS::AccountId"},
{
"Fn::Join" : [
"",
[ ":parameter/", { "Ref": "AWS::StackName" }, ".*" ]
]
}
]
]
}
}
]
},
"Roles": [ { "Ref": "SSMAccessRole" } ]
}
},
"SSMInstanceProfile": {
"Type": "AWS::IAM::InstanceProfile",
"Properties": {
"Path": "/",
"Roles": [ { "Ref": "SSMAccessRole" } ]
}
},
"web1pem" : {
"Type" : "AWS::SSM::Parameter",
"Properties" : {
"Name" : {
"Fn::Join" : [
"",
[ { "Ref": "AWS::StackName" }, ".web1pem" ]
]
},
"Type" : "String",
"Value" : "0",
"Description": "web1 instance private key."
}
},
"web2pem" : {
"Type" : "AWS::SSM::Parameter",
"Properties" : {
"Name" : {
"Fn::Join" : [
"",
[ { "Ref": "AWS::StackName" }, ".web2pem" ]
]
},
"Type" : "String",
"Value" : "0",
"Description": "web2 instance private key."
}
},
"wordpressVpc": {
"Type": "AWS::EC2::VPC",
"Properties": {
"EnableDnsSupport": "true",
"EnableDnsHostnames": "true",
"CidrBlock": "10.0.0.0/16",
"Tags": [
{
"Key": "Environment",
"Value": "Test"
}
]
}
},
"publicSubnet1": {
"Type": "AWS::EC2::Subnet",
"Properties": {
"VpcId": {
"Ref": "wordpressVpc"
},
"CidrBlock": "10.0.0.0/24",
"AvailabilityZone" : {
"Fn::Select" : [ "0", { "Fn::GetAZs" : { "Ref" : "AWS::Region" }}]
}
}
},
"publicSubnet2": {
"Type": "AWS::EC2::Subnet",
"Properties": {
"VpcId": {
"Ref": "wordpressVpc"
},
"CidrBlock": "10.0.1.0/24",
"AvailabilityZone" : {
"Fn::Select" : [ "1", { "Fn::GetAZs" : { "Ref" : "AWS::Region" }}]
}
}
},
"privateSubnet1": {
"Type": "AWS::EC2::Subnet",
"Properties": {
"VpcId": {
"Ref": "wordpressVpc"
},
"CidrBlock": "10.0.2.0/24",
"AvailabilityZone" : {
"Fn::Select" : [ "0", { "Fn::GetAZs" : { "Ref" : "AWS::Region" }}]
}
}
},
"privateSubnet2": {
"Type": "AWS::EC2::Subnet",
"Properties": {
"VpcId": {
"Ref": "wordpressVpc"
},
"CidrBlock": "10.0.3.0/24",
"AvailabilityZone" : {
"Fn::Select" : [ "1", { "Fn::GetAZs" : { "Ref" : "AWS::Region" }}]
}
}
},
"web1": {
"Type": "AWS::EC2::Instance",
"DependsOn": [
"web1pem"
],
"Properties": {
"InstanceType": "t2.micro",
"ImageId": {"Ref": "AMI"},
"IamInstanceProfile": {
"Ref": "SSMInstanceProfile"
},
"KeyName": {
"Ref": "KeyName"
},
"NetworkInterfaces": [
{
"GroupSet": [
{
"Ref": "WebServerSecurityGroup"
}
],
"AssociatePublicIpAddress": "true",
"DeviceIndex": "0",
"DeleteOnTermination": "true",
"SubnetId": {
"Ref": "publicSubnet1"
}
}
],
"Tags": [
{
"Key": "Name",
"Value": "web1"
}
],
"UserData" : {
"Fn::Base64" : {
"Fn::Join" : [
"", [
"#!/bin/bash -xe\n",
"ssh-keygen -f /home/ec2-user/.ssh/web1-key.pem -q -N \"\"\n",
"chown ec2-user:ec2-user /home/ec2-user/.ssh/web1-key.pem\n",
"chown ec2-user:ec2-user /home/ec2-user/.ssh/web1-key.pem.pub\n",
"PEMFILE=`cat /home/ec2-user/.ssh/web1-key.pem`\n",
"aws ssm put-parameter --name ", { "Ref" : "web1pem" }, " --type String --value \"${PEMFILE}\" --overwrite --region ", { "Ref" : "AWS::Region" },"\n",
"cat /home/ec2-user/.ssh/web1-key.pem.pub >> /home/ec2-user/.ssh/authorized_keys\n",
"# Signal the status from cfn-init\n",
"/opt/aws/bin/cfn-signal -e $? ",
" --stack ",
{
"Ref": "AWS::StackName"
},
" --resource web1 ",
" --region ",
{
"Ref": "AWS::Region"
},
"\n"
]
]
}
}
},
"CreationPolicy": {
"ResourceSignal": {
"Timeout": "PT5M"
}
}
},
"web2": {
"Type": "AWS::EC2::Instance",
"DependsOn": [
"web1pem"
],
"Properties": {
"InstanceType": "t2.micro",
"ImageId": {"Ref": "AMI"},
"IamInstanceProfile": {
"Ref": "SSMInstanceProfile"
},
"KeyName": {
"Ref": "KeyName"
},
"NetworkInterfaces": [
{
"GroupSet": [
{
"Ref": "WebServerSecurityGroup"
}
],
"AssociatePublicIpAddress": "true",
"DeviceIndex": "0",
"DeleteOnTermination": "true",
"SubnetId": {
"Ref": "publicSubnet2"
}
}
],
"Tags": [
{
"Key": "Name",
"Value": "web2"
}
],
"UserData" : {
"Fn::Base64" : {
"Fn::Join" : [
"", [
"#!/bin/bash -xe\n",
"ssh-keygen -f /home/ec2-user/.ssh/web2-key.pem -q -N \"\"\n",
"chown ec2-user:ec2-user /home/ec2-user/.ssh/web2-key.pem\n",
"chown ec2-user:ec2-user /home/ec2-user/.ssh/web2-key.pem.pub\n",
"PEMFILE=`cat /home/ec2-user/.ssh/web2-key.pem`\n",
"aws ssm put-parameter --name ", { "Ref" : "web2pem" }, " --type String --value \"${PEMFILE}\" --overwrite --region ", { "Ref" : "AWS::Region" },"\n",
"cat /home/ec2-user/.ssh/web2-key.pem.pub >> /home/ec2-user/.ssh/authorized_keys\n",
"# Signal the status from cfn-init\n",
"/opt/aws/bin/cfn-signal -e $? ",
" --stack ",
{
"Ref": "AWS::StackName"
},
" --resource web2 ",
" --region ",
{
"Ref": "AWS::Region"
},
"\n"
]
]
}
}
},
"CreationPolicy": {
"ResourceSignal": {
"Timeout": "PT5M"
}
}
},
"WebServerSecurityGroup": {
"Type": "AWS::EC2::SecurityGroup",
"Properties": {
"VpcId": {
"Ref": "wordpressVpc"
},
"GroupDescription": "Allow access from HTTP and SSH traffic",
"SecurityGroupIngress": [
{
"IpProtocol": "tcp",
"FromPort": "80",
"ToPort": "80",
"CidrIp": "0.0.0.0/0"
},
{
"IpProtocol": "tcp",
"FromPort": "22",
"ToPort": "22",
"CidrIp": {"Ref": "YourIp"}
}
]
}
},
"WebServerSGIngressTCP22": {
"Type": "AWS::EC2::SecurityGroupIngress",
"Metadata": {
"Comment": "SSH ingress security rule"
},
"Properties" : {
"IpProtocol": "tcp",
"FromPort": "22",
"ToPort": "22",
"SourceSecurityGroupId": { "Ref": "WebServerSecurityGroup" },
"GroupId": { "Fn::GetAtt": ["WebServerSecurityGroup", "GroupId"]}
}
},
"InternetGateway": {
"Type": "AWS::EC2::InternetGateway",
"Properties": {}
},
"AttachGateway": {
"Type": "AWS::EC2::VPCGatewayAttachment",
"Properties": {
"InternetGatewayId": {
"Ref": "InternetGateway"
},
"VpcId": {
"Ref": "wordpressVpc"
}
}
},
"PublicRouteTable": {
"Type": "AWS::EC2::RouteTable",
"Properties": {
"VpcId": {
"Ref": "wordpressVpc"
}
}
},
"PublicRoute": {
"Type": "AWS::EC2::Route",
"Properties": {
"DestinationCidrBlock": "0.0.0.0/0",
"RouteTableId": {
"Ref": "PublicRouteTable"
},
"GatewayId": {
"Ref": "InternetGateway"
}
},
"DependsOn": [
"InternetGateway", "AttachGateway"
]
},
"Public1RouteTableAssociation": {
"Type": "AWS::EC2::SubnetRouteTableAssociation",
"Properties": {
"RouteTableId": {
"Ref": "PublicRouteTable"
},
"SubnetId": {
"Ref": "publicSubnet1"
}
}
},
"Public2RouteTableAssociation": {
"Type": "AWS::EC2::SubnetRouteTableAssociation",
"Properties": {
"RouteTableId": {
"Ref": "PublicRouteTable"
},
"SubnetId": {
"Ref": "publicSubnet2"
}
}
},
"webserverlb": {
"Type": "AWS::ElasticLoadBalancingV2::LoadBalancer",
"Properties": {
"IpAddressType": "ipv4",
"SecurityGroups": [
{
"Ref": "webserverlbSecurityGroup"
}
],
"Subnets": [
{
"Ref": "publicSubnet1"
},
{
"Ref": "publicSubnet2"
}
],
"Tags": [
{
"Key": "Name",
"Value": "webserverlb"
}
]
},
"DependsOn": [
"webserversSecurityGroup"
]
},
"webserverlbSecurityGroup": {
"Type": "AWS::EC2::SecurityGroup",
"Properties": {
"VpcId": {
"Ref": "wordpressVPC"
},
"GroupDescription": "Allows incoming requests from port 80 via HTTP.",
"SecurityGroupIngress": [
{
"IpProtocol": "TCP",
"FromPort": "80",
"ToPort": "80",
"CidrIp": "0.0.0.0/0",
"Description": "Allows 80 from Internet"
}
]
}
},
"wordpressdb": {
"Type": "AWS::RDS::DBInstance",
"Properties": {
"VpcId": {
"Ref": "wordpressVPC"
},
"AvailabilityZone": "us-east-1a",
"DBInstanceClass": "db.t2.micro",
"DBName": "wordpress",
"Engine": "mariadb",
"EngineVersion": "10.2.21",
"MultiAZ": 1,
"Tags": [
{
"Key": "Name",
"Value": "wordpressdb"
}
]
},
"DependsOn": [
"wordpressdbSecurityGroup"
]
},
"wordpressdbSecurityGroup": {
"Type": "AWS::RDS::DBSecurityGroup",
"Properties": {
"VpcId": {
"Ref": "wordpressVPC"
},
"GroupDescription": "Enable access to the db via port 3306.",
"Tags": [
{
"Key": "Name",
"Value": "wordpressdbSecurityGroup"
}
],
"SecurityGroupIngress": [
{
"IpProtocol": "TCP",
"FromPort": "3306",
"ToPort": "3306",
"Description": "Enable HTTP access."
}
]
}
}
},
"Parameters": {
"KeyName": {
"Description": "Name of your EC2 KeyPair to enable SSH access to the instances.",
"Type": "AWS::EC2::KeyPair::KeyName",
"ConstraintDescription": "must be the name of an existing EC2 KeyPair."
},
"YourIp": {
"Description": "The current CIDR IP address of your workstation (x.x.x.x/32). http://checkip.amazonaws.com/",
"Type": "String",
"AllowedPattern": "^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\\/(1[6-9]|2[0-9]|3[0-2]))$",
"ConstraintDescription": "Must be a valid IP CIDR range of the form x.x.x.x/x."
},
"AMI": {
"Description": "The EC2 instance AMI",
"Type": "String",
"Default": "ami-00dc79254d0461090"
},
"DBName": {
"Description": "Name of the database",
"Type" : "String",
"Default": "wordpress"
},
"DBUser": {
"Default": "admin",
"NoEcho": "false",
"Description" : "The WordPress database admin account user name",
"Type": "String",
"MinLength": "1",
"MaxLength": "16",
"AllowedPattern" : "[a-zA-Z][a-zA-Z0-9]*"
},
"DBPassword": {
"NoEcho": "true",
"Description" : "The password of the database.",
"Type": "String",
"MinLength": "1",
"MaxLength": "16",
"AllowedPattern" : "[a-zA-Z][a-zA-Z0-9]*"
}
},
"Outputs": {
"web1PublicIp": {
"Value": {"Fn::GetAtt": ["web1","PublicIp"]},
"Description": "web1 public IP"
},
"we2PublicIp": {
"Value": {"Fn::GetAtt": ["web2","PublicIp"]},
"Description": "web2 public IP"
},
"mgmt1PublicIp": {
"Value": {"Fn::GetAtt": ["mgmt1","PublicIp"]},
"Description": "mgmt1 public IP"
}
}
}
Because CloudFormation is case sensitive. Your vpc resource is called wordpressVpc, but in some places you are using wordpressVPC.
Recommend trying the CloudFormation Linter in VSCode to see some of these errors inline while authoring templates along with autocompletion and documentation links:
E3005 DependsOn should reference other resources at Resources/webserverlb/DependsOn/0
E1012 Ref wordpressVPC not found as a resource or parameter
E1012 Ref wordpressVPC not found as a resource or parameter
E3002 Invalid Property Resources/wordpressdb/Properties/VpcId
E3003 Property DBSecurityGroupIngress missing at Resources/wordpressdbSecurityGroup/Properties
E1012 Ref wordpressVPC not found as a resource or parameter
E3002 Invalid Property Resources/wordpressdbSecurityGroup/Properties/VpcId
E3002 Invalid Property Resources/wordpressdbSecurityGroup/Properties/SecurityGroupIngress
E1010 Invalid GetAtt mgmt1.PublicIp for resource mgmt1PublicIp
I want to replicate the infrastructure from one region(us-east-1) to another(us-east-2). so,I have generated a cloudfromation template of an existing infrastructure with the help of cloudformer tool.
"asgamazonecsclisetupapijoulebugprodEcsInstanceAsg1EIBNOXSXJ7HD": {
"Type": "AWS::AutoScaling::AutoScalingGroup",
"Properties": {
"AvailabilityZones": [
"us-east-2b",
"us-east-2c"
],
"Cooldown": "300",
"DesiredCapacity": "3",
"HealthCheckGracePeriod": "300",
"HealthCheckType": "ELB",
"MaxSize": "16",
"MinSize": "3",
"VPCZoneIdentifier": [
{
"Ref": "subnet81c8ebab"
},
{
"Ref": "subnet5df40214"
}
],
"LaunchConfigurationName": {
"Ref": "lcamazonecsclisetupapijoulebugprodAMI2017d"
},
"LoadBalancerNames": [
{
"Ref": "elbJBAPILiveCleanbit2016"
}
],
"Tags": [
{
"Key": "Name",
"Value": "Live - Cleanbit2016 - joulebug-api",
"PropagateAtLaunch": true
}
],
"TerminationPolicies": [
"Default"
]
}
},
"lcamazonecsclisetupapijoulebugprodAMI2017d": {
"Type": "AWS::AutoScaling::LaunchConfiguration",
"Properties": {
"AssociatePublicIpAddress": true,
"ImageId": "ami-0e6d83442546978bc",
"InstanceType": "c3.large",
"KeyName": "cleanbit2016_vpc",
"IamInstanceProfile": "amazon-ecs-cli-setup-api-joulebug-prod-EcsInstanceProfile-1M4GOHBP3FP5L",
"InstanceMonitoring": "true",
"SecurityGroups": [
{
"Ref": "sgCleanbit2016WebServerSG"
}
],
"BlockDeviceMappings": [
{
"DeviceName": "/dev/xvda",
"Ebs": {
"SnapshotId": "snap-0b2477be9c863d014",
"VolumeSize": 8
}
},
{
"DeviceName": "/dev/xvdcz",
"Ebs": {
"VolumeSize": 22
}
}
]
}
},
"elbJBAPILiveCleanbit2016": {
"Type": "AWS::ElasticLoadBalancing::LoadBalancer",
"Properties": {
"Policies": [
{
"PolicyName": "AWSConsole-SSLNegotiationPolicy-JB-API-Live-Cleanbit2016-1467998170471",
"PolicyType": "SSLNegotiationPolicyType",
}
],
}
}
"subnet81c8ebab": {
"Type": "AWS::EC2::Subnet",
"Properties": {
"CidrBlock": "10.0.3.0/24",
"AvailabilityZone": "us-east-2b",
"VpcId": {
"Ref": "vpcdcbd08bb"
},
"Tags": [
{
"Key": "Name",
"Value": "Cleanbit2016 - Public 1b"
}
]
}
},
"sgCleanbit2016WebServerSG": {
"Type": "AWS::EC2::SecurityGroup",
"Properties": {
"GroupDescription": "Web server security group for public subnet in vpc.",
"VpcId": {
"Ref": "vpcdcbd08bb"
},
"Tags": [
{
"Key": "Name",
"Value": "Cleanbit2016_ WebServerSG"
}
]
}
},
While launching the template in other region(us-east-2), it is throwing following error:
The requested configuration is currently not supported. Please check the documentation for supported configurations. Launching EC2 instance failed.
You don't have details of the regions you're using, but if you are trying to do this outside of us-east-1 the Availablility Zones won't work. It also looks like you have a number of other parts of the stack hard-coded, which may not work in another region.
And if you are trying to do this in us-east-1, there is the possibility that one of the AZs is unavailable to you - see this question for more details.
You have not provided enough information to be able to diagnose the situation.
I took your template, removed the portions that were incomplete (eg removed the Load Balancer because it was missing Listeners), simplified a few things and it works fine:
{
"AWSTemplateFormatVersion": "2010-09-09",
"Resources": {
"VPC": {
"Type": "AWS::EC2::VPC",
"Properties": {
"CidrBlock": "10.0.0.0/16",
"Tags": [
{
"Key": "Name",
"Value": "Lab VPC"
}
]
}
},
"ASG": {
"Type": "AWS::AutoScaling::AutoScalingGroup",
"Properties": {
"AvailabilityZones": [
"us-east-2b",
"us-east-2c"
],
"Cooldown": "300",
"DesiredCapacity": "1",
"HealthCheckGracePeriod": "300",
"MaxSize": "16",
"MinSize": "1",
"VPCZoneIdentifier": [
{
"Ref": "Subnet1"
},
{
"Ref": "Subnet2"
}
],
"LaunchConfigurationName": {
"Ref": "LaunchConfig"
}
}
},
"LaunchConfig": {
"Type": "AWS::AutoScaling::LaunchConfiguration",
"Properties": {
"AssociatePublicIpAddress": true,
"ImageId": "ami-0b59bfac6be064b78",
"InstanceType": "t2.micro",
"InstanceMonitoring": "true",
"SecurityGroups": [
{
"Ref": "WebServerSG"
}
]
}
},
"Subnet1": {
"Type": "AWS::EC2::Subnet",
"Properties": {
"CidrBlock": "10.0.0.0/24",
"AvailabilityZone": "us-east-2b",
"VpcId": {
"Ref": "VPC"
},
"Tags": [
{
"Key": "Name",
"Value": "Public 1"
}
]
}
},
"Subnet2": {
"Type": "AWS::EC2::Subnet",
"Properties": {
"CidrBlock": "10.0.1.0/24",
"AvailabilityZone": "us-east-2c",
"VpcId": {
"Ref": "VPC"
},
"Tags": [
{
"Key": "Name",
"Value": "Public 2"
}
]
}
},
"WebServerSG": {
"Type": "AWS::EC2::SecurityGroup",
"Properties": {
"GroupDescription": "Web server security group for public subnet in vpc.",
"VpcId": {
"Ref": "VPC"
},
"Tags": [
{
"Key": "Name",
"Value": "WebServerSG"
}
]
}
}
}
}
Therefore, your problem lies in part of the template you did not provide.
You could start with this version, then progressively add back parts of your template until you discover what is causing the error.
If you wish to create a CloudFormation template that can run in multiple regions, you should not refer to specific Availability Zones (eg us-east-2b).
You can use Fn::GetAZs - AWS CloudFormation to obtain a list of AZs in region.
After a lot of debugging, when I started launching the things manually, I found the same error and I got to know that c3.large is causing the error. When I launch the template with c4.large it successfully launched the template from us-east-1 to us-east-2.
I know AWS allows this now and has instructions for a manual setup. I'm trying to set this up in a cloudformation though and am running into difficulties. Currently when I try to access my RDS server I am getting connect ETIMEDOUT errors.
I have my VPC, Subnets and security groups setup with the following:
"VPC": {
"Type": "AWS::EC2::VPC",
"Properties": {
"CidrBlock": "10.0.0.0/16",
"EnableDnsSupport": "false",
"EnableDnsHostnames": "false",
"InstanceTenancy": "default",
"Tags" : [{ "Key": "Name", "Value": { "Ref": "DomainName" } }]
}
},
"SubnetA": {
"Type": "AWS::EC2::Subnet",
"Properties": {
"VpcId": { "Ref": "VPC" },
"CidrBlock": "10.0.0.0/24",
"AvailabilityZone": { "Fn::Select": [ "0", { "Fn::GetAZs": { "Ref": "AWS::Region" } }]},
"Tags" : [{ "Key": "Name", "Value": { "Ref": "DomainName" } }]
}
},
"SubnetB": {
"Type": "AWS::EC2::Subnet",
"Properties": {
"VpcId": { "Ref": "VPC" },
"CidrBlock": "10.0.1.0/24",
"AvailabilityZone": { "Fn::Select": [ "1", { "Fn::GetAZs": { "Ref": "AWS::Region" } }]},
"Tags" : [{ "Key": "Name", "Value": { "Ref": "DomainName" } }]
}
},
"SubnetGroup": {
"Type": "AWS::RDS::DBSubnetGroup",
"Properties": {
"DBSubnetGroupDescription": "Database Access",
"SubnetIds" : [{ "Ref": "SubnetA" }, { "Ref": "SubnetB" }],
"Tags" : [{ "Key": "Name", "Value": { "Ref": "DomainName" } }]
}
},
"SecurityGroup": {
"Type": "AWS::EC2::SecurityGroup",
"Properties": {
"GroupDescription": "Database Access",
"VpcId": {"Ref": "VPC"},
"SecurityGroupIngress" : [{
"IpProtocol": "tcp",
"FromPort": "3306",
"ToPort": "3306",
"CidrIp": "10.0.0.0/16"
}],
"Tags" : [{ "Key": "Name", "Value": { "Ref": "DomainName" } }]
}
},
I don't actually use SubnetB but to make AWS::RDS::DBSubnetGroup you need subnets in at least two availability zones.
My RDS database is setup with the VPC and Security group.
"Database": {
"Type": "AWS::RDS::DBInstance",
"Properties": {
"DBName": { "Fn::Join": ["", { "Fn::Split": [".", { "Ref": "DomainName" }]}]},
"AllocatedStorage": "5",
"DBInstanceClass": "db.t2.micro",
"Engine": "MySQL",
"EngineVersion": "5.5",
"MasterUsername": { "Ref": "DBUsername" },
"MasterUserPassword": { "Ref": "DBPassword" },
"DBSubnetGroupName": { "Ref": "SubnetGroup" },
"VPCSecurityGroups" : [{ "Fn::GetAtt": [ "SecurityGroup", "GroupId" ] }],
"Tags" : [{ "Key": "Name", "Value": { "Ref": "DomainName" } }]
},
"DeletionPolicy": "Snapshot"
},
So I think the database side is correctly in the VPC and able to talk both subnets.
My lambda is setup in the security group and in SubnetA.
"LambdaFunctionUpdate": {
"Type": "AWS::Lambda::Function",
"Properties": {
"Code": {
"ZipFile": "exports.handler = function (event, context) { context.succeed(\"Hello, World!\"); };"
},
"Description": "Used to create and or sync database tables to the application models",
"Handler": "index.handler",
"MemorySize": 128,
"Role": { "Fn::GetAtt": ["LambdaExecutionRole", "Arn" ] },
"Runtime": "nodejs4.3",
"Timeout": 30,
"VpcConfig": {
"SecurityGroupIds": [{ "Fn::GetAtt": ["SecurityGroup", "GroupId"] }],
"SubnetIds": [{"Ref": "SubnetA"}]
}
}
},
At the end of everything I'm outputting the database endpoint information.
"Outputs": {
"DatabaseEndpoint": {
"Value": { "Fn::Join" : [":", [{ "Fn::GetAtt": ["Database", "Endpoint.Address" ] }, { "Fn::GetAtt": ["Database", "Endpoint.Port" ] }]]},
"Description": "Database endpoint"
}
}
When I run my lambda and try to connect to the RDS server with the endpoint given I get timeout errors.
{
"errorMessage": "connect ETIMEDOUT",
"errorType": "SequelizeConnectionError",
"stackTrace": [
"Handshake._callback (/var/task/node_modules/sequelize/lib/dialects/mysql/connection-manager.js:95:20)",
"Handshake.Sequence.end (/var/task/node_modules/mysql/lib/protocol/sequences/Sequence.js:86:24)",
"Protocol.handleNetworkError (/var/task/node_modules/mysql/lib/protocol/Protocol.js:364:14)",
"Connection._handleNetworkError (/var/task/node_modules/mysql/lib/Connection.js:428:18)",
"Connection._handleConnectTimeout (/var/task/node_modules/mysql/lib/Connection.js:424:8)",
"Socket.g (events.js:260:16)",
"emitNone (events.js:67:13)",
"Socket.emit (events.js:166:7)",
"Socket._onTimeout (net.js:318:8)",
"_runOnTimeout (timers.js:524:11)",
"_makeTimerTimeout (timers.js:515:3)",
"Timer.unrefTimeout (timers.js:584:5)"
]
}
The VPC configuration was incorrect. DNS services can't be turned off.
"VPC": {
"Type": "AWS::EC2::VPC",
"Properties": {
"CidrBlock": "10.0.0.0/16",
"EnableDnsSupport": "true",
"EnableDnsHostnames": "true",
"InstanceTenancy": "default",
"Tags" : [{ "Key": "Name", "Value": { "Ref": "DomainName" } }]
}
},
My problem is that a Lambda function that I run behind NAT inside a VPC with an IGW doesn't have access to anything on the Internet.
What I'm trying to do is creating a VPC that has:
Internet Gateway;
2 private subnets (PrivateA and PrivateB) in availability zones A and B respectively;
1 public subnet (PublicA) in availability zone A
NAT Gateway in PublicA subnet
PrivateA and PrivateB have a route table that routes 0.0.0.0/0 to the NAT Gateway.
PublicA has a route table that routes 0.0.0.0/0 to the Internet Gateway.
Private subnets, as well as the public subnet have Access Control Lists allowing all Ingress and Egress traffic.
That part kind of works.
Next, I want to create a Lambda function inside the VPC. I put it into PrivateA and PrivateB and assign to it a Security Group that allows all Egress and Ingress traffic.
Below is a self-contained example (the whole template) that reproduces the issue. I've read all the possible docs and articles on the Internet so I would very much appreciate it if anybody could point me in the right direction.
{
"AWSTemplateFormatVersion": "2010-09-09",
"Resources": {
"Vpc": {
"Type": "AWS::EC2::VPC",
"Properties": {
"CidrBlock": "10.0.0.0/16",
"EnableDnsSupport": true,
"EnableDnsHostnames": true,
"InstanceTenancy": "default"
}
},
"InternetGateway": {
"Type": "AWS::EC2::InternetGateway"
},
"VpcGatewayAttachment": {
"Type": "AWS::EC2::VPCGatewayAttachment",
"Properties": {
"VpcId": { "Ref": "Vpc" },
"InternetGatewayId": { "Ref": "InternetGateway" }
}
},
"ElasticIP":{
"Type": "AWS::EC2::EIP",
"Properties": {
"Domain": "vpc"
}
},
"NatGateway": {
"Type": "AWS::EC2::NatGateway",
"DependsOn": [ "VpcGatewayAttachment" ],
"Properties": {
"AllocationId": { "Fn::GetAtt": [ "ElasticIP", "AllocationId" ] },
"SubnetId": { "Ref": "SubnetAPublic" }
}
},
"SubnetAPublic": {
"Type": "AWS::EC2::Subnet",
"Properties": {
"AvailabilityZone": { "Fn::Select" : [ "0", { "Fn::GetAZs" : "" } ] },
"CidrBlock": "10.0.0.0/19",
"MapPublicIpOnLaunch": true,
"VpcId": { "Ref": "Vpc" }
}
},
"SubnetAPrivate": {
"Type": "AWS::EC2::Subnet",
"Properties": {
"AvailabilityZone": { "Fn::Select" : [ "0", { "Fn::GetAZs" : "" } ] },
"CidrBlock": "10.0.64.0/19",
"VpcId": { "Ref": "Vpc" }
}
},
"SubnetBPrivate": {
"Type": "AWS::EC2::Subnet",
"Properties": {
"AvailabilityZone": { "Fn::Select" : [ "1", { "Fn::GetAZs" : "" } ] },
"CidrBlock": "10.0.96.0/19",
"VpcId": { "Ref": "Vpc" }
}
},
"RouteTablePublic": {
"Type": "AWS::EC2::RouteTable",
"Properties": {
"VpcId": { "Ref": "Vpc" }
}
},
"RouteTablePrivate": {
"Type": "AWS::EC2::RouteTable",
"Properties": {
"VpcId": { "Ref": "Vpc" }
}
},
"RouteTableAssociationAPublic": {
"Type": "AWS::EC2::SubnetRouteTableAssociation",
"Properties": {
"SubnetId": { "Ref": "SubnetAPublic" },
"RouteTableId": { "Ref": "RouteTablePublic" }
}
},
"RouteTableAssociationAPrivate": {
"Type": "AWS::EC2::SubnetRouteTableAssociation",
"Properties": {
"SubnetId": { "Ref": "SubnetAPrivate" },
"RouteTableId": { "Ref": "RouteTablePrivate" }
}
},
"RouteTableAssociationBPrivate": {
"Type": "AWS::EC2::SubnetRouteTableAssociation",
"Properties": {
"SubnetId": { "Ref": "SubnetBPrivate" },
"RouteTableId": { "Ref": "RouteTablePrivate" }
}
},
"RouteTablePrivateInternetRoute": {
"Type": "AWS::EC2::Route",
"DependsOn": [ "VpcGatewayAttachment" ],
"Properties": {
"RouteTableId": { "Ref": "RouteTablePrivate" },
"DestinationCidrBlock": "0.0.0.0/0",
"NatGatewayId": { "Ref": "NatGateway" }
}
},
"RouteTablePublicInternetRoute": {
"Type": "AWS::EC2::Route",
"DependsOn": [ "VpcGatewayAttachment" ],
"Properties": {
"RouteTableId": { "Ref": "RouteTablePublic" },
"DestinationCidrBlock": "0.0.0.0/0",
"GatewayId": { "Ref": "InternetGateway" }
}
},
"NetworkAclPublic": {
"Type": "AWS::EC2::NetworkAcl",
"Properties": {
"VpcId": { "Ref": "Vpc" }
}
},
"NetworkAclPrivate": {
"Type": "AWS::EC2::NetworkAcl",
"Properties": {
"VpcId": { "Ref": "Vpc" }
}
},
"SubnetNetworkAclAssociationAPublic": {
"Type": "AWS::EC2::SubnetNetworkAclAssociation",
"Properties":{
"SubnetId": { "Ref": "SubnetAPublic" },
"NetworkAclId": { "Ref": "NetworkAclPublic" }
}
},
"SubnetNetworkAclAssociationAPrivate": {
"Type": "AWS::EC2::SubnetNetworkAclAssociation",
"Properties":{
"SubnetId": { "Ref": "SubnetAPrivate" },
"NetworkAclId": { "Ref": "NetworkAclPrivate" }
}
},
"SubnetNetworkAclAssociationBPrivate": {
"Type": "AWS::EC2::SubnetNetworkAclAssociation",
"Properties": {
"SubnetId": { "Ref": "SubnetBPrivate" },
"NetworkAclId": { "Ref": "NetworkAclPrivate" }
}
},
"NetworkAclEntryInPublicAllowAll": {
"Type": "AWS::EC2::NetworkAclEntry",
"Properties": {
"NetworkAclId": { "Ref": "NetworkAclPublic" },
"RuleNumber": 99,
"Protocol": -1,
"RuleAction": "allow",
"Egress": false,
"CidrBlock": "0.0.0.0/0"
}
},
"NetworkAclEntryOutPublicAllowAll": {
"Type": "AWS::EC2::NetworkAclEntry",
"Properties": {
"NetworkAclId": { "Ref": "NetworkAclPublic" },
"RuleNumber": 99,
"Protocol": -1,
"RuleAction": "allow",
"Egress": true,
"CidrBlock": "0.0.0.0/0"
}
},
"NetworkAclEntryInPrivateAllowVpc": {
"Type": "AWS::EC2::NetworkAclEntry",
"Properties": {
"NetworkAclId": { "Ref": "NetworkAclPrivate" },
"RuleNumber": 99,
"Protocol": -1,
"RuleAction": "allow",
"Egress": false,
"CidrBlock": "0.0.0.0/16"
}
},
"NetworkAclEntryOutPrivateAllowVpc": {
"Type": "AWS::EC2::NetworkAclEntry",
"Properties": {
"NetworkAclId": { "Ref": "NetworkAclPrivate" },
"RuleNumber": 99,
"Protocol": -1,
"RuleAction": "allow",
"Egress": true,
"CidrBlock": "0.0.0.0/0"
}
},
"LambdasSecurityGroup": {
"Type": "AWS::EC2::SecurityGroup",
"Properties": {
"GroupDescription": "Lambdas security group",
"SecurityGroupEgress": [
{ "CidrIp": "0.0.0.0/0", "IpProtocol": "-1" }
],
"SecurityGroupIngress": [
{ "CidrIp": "0.0.0.0/0", "IpProtocol": "-1" }
],
"VpcId": { "Ref": "Vpc" }
}
},
"LambdaFunctionExecutionRole": {
"Type": "AWS::IAM::Role",
"Properties": {
"AssumeRolePolicyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": { "Service": "lambda.amazonaws.com" },
"Action": "sts:AssumeRole"
}
]
},
"ManagedPolicyArns": [
"arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole",
"arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole"
]
}
},
"LambdaFunction": {
"Type": "AWS::Lambda::Function",
"Properties": {
"Handler": "index.lambda_handler",
"Runtime": "python2.7",
"Role": {
"Fn::GetAtt": ["LambdaFunctionExecutionRole", "Arn"]
},
"Code": {
"ZipFile": {
"Fn::Join": ["\n", [
"import urllib2",
"def lambda_handler(event, context):",
"\tresponse = urllib2.urlopen('http://python.org/')",
"\treturn response.read()"
]]
}
},
"VpcConfig": {
"SecurityGroupIds": [
{ "Fn::GetAtt": [ "LambdasSecurityGroup", "GroupId"] }
],
"SubnetIds": [
{ "Ref": "SubnetAPrivate" },
{ "Ref": "SubnetBPrivate" }
]
}
}
}
}
}
The cause of the failed connectivity lies within your ACL config for "NetworkAclEntryInPrivateAllowVpc" and "NetworkAclEntryOutPrivateAllowVpc".
If you open that CIDR block from "0.0.0.0/16" to "0.0.0.0/0", Lambda can access the internet.
I'm not that knowledgeable about NAT, but it seems that the NAT traffic is blocked by that ACL rule.