Я намагаюся надати приватним підмережам доступ до Інтернету через екземпляр NAT на AWS. Моя хмарна інформація налаштована так:
Мій VPC:
"VPC": {
"Type": "AWS::EC2::VPC",
"Properties": {
"CidrBlock": { "Fn::FindInMap" : [ "SubnetConfig", "VPC", "CIDR" ]},
"EnableDnsSupport": "true",
"EnableDnsHostnames": "true",
"InstanceTenancy": "default"
}
},
"PublicRouteTable" : {
"Type" : "AWS::EC2::RouteTable",
"Properties" : {
"VpcId" : { "Ref" : "VPC" }
}
},
"PrivateRouteTable" : {
"Type" : "AWS::EC2::RouteTable",
"Properties" : {
"VpcId" : { "Ref" : "VPC" }
}
},
Мій Інтернет-шлюз із загальної сторони:
"InternetGateway" : {
"Type" : "AWS::EC2::InternetGateway",
"Properties" : {
"Tags" : [
{"Key": "Name", "Value": { "Fn::Join" : ["_", ["InternetGateway", { "Ref": "AWS::StackName" } ]]}},
{"Key": "Domain", "Value": { "Ref": "DomainName" }}
]
}
},
"AttachGateway": {
"Type" : "AWS::EC2::VPCGatewayAttachment",
"Properties" : {
"VpcId" : { "Ref" : "VPC" },
"InternetGatewayId" : { "Ref" : "InternetGateway" }
}
},
"InternetRoute" : {
"Type" : "AWS::EC2::Route",
"DependsOn" : "InternetGateway",
"Properties" : {
"RouteTableId" : { "Ref" : "PublicRouteTable" },
"DestinationCidrBlock" : "0.0.0.0/0",
"GatewayId" : { "Ref" : "InternetGateway" }
}
},
Мої три підмережі:
"SubnetPrivateA": {
"Type": "AWS::EC2::Subnet",
"DependsOn" : ["VPC"],
"Properties": {
"VpcId": { "Ref": "VPC" },
"CidrBlock": { "Fn::FindInMap" : [ "SubnetConfig", "PrivateA", "CIDR" ]},
"AvailabilityZone": { "Fn::Select": [ "0", { "Fn::GetAZs": { "Ref": "AWS::Region" } }]}
}
},
"SubnetPrivateB": {
"Type": "AWS::EC2::Subnet",
"DependsOn" : ["VPC"],
"Properties": {
"VpcId": { "Ref": "VPC" },
"CidrBlock": { "Fn::FindInMap" : [ "SubnetConfig", "PrivateB", "CIDR" ]},
"AvailabilityZone": { "Fn::Select": [ "1", { "Fn::GetAZs": { "Ref": "AWS::Region" } }]}
}
},
"SubnetPublic": {
"Type": "AWS::EC2::Subnet",
"DependsOn" : ["VPC"],
"Properties": {
"VpcId": { "Ref": "VPC" },
"CidrBlock": { "Fn::FindInMap" : [ "SubnetConfig", "Public", "CIDR" ]},
"AvailabilityZone": { "Fn::Select": [ "1", { "Fn::GetAZs": { "Ref": "AWS::Region" } }]}
}
},
Пов’яжіть підмережі до таблиць маршрутів
"SubnetPrivateARouteTableAssociation" : {
"Type" : "AWS::EC2::SubnetRouteTableAssociation",
"Properties" : {
"SubnetId" : { "Ref" : "SubnetPrivateA" },
"RouteTableId" : { "Ref" : "PrivateRouteTable" }
}
},
"SubnetPrivateBRouteTableAssociation" : {
"Type" : "AWS::EC2::SubnetRouteTableAssociation",
"Properties" : {
"SubnetId" : { "Ref" : "SubnetPrivateB" },
"RouteTableId" : { "Ref" : "PrivateRouteTable" }
}
},
"SubnetPublicRouteTableAssociation" : {
"Type" : "AWS::EC2::SubnetRouteTableAssociation",
"Properties" : {
"SubnetId" : { "Ref" : "SubnetPublic" },
"RouteTableId" : { "Ref" : "PublicRouteTable" }
}
},
Створіть дві мої групи безпеки: одна для лямбда, що сидить у приватних підмережах, і одна для нату, що сидить у публічній підмережі.
"LambdaSecurityGroup": {
"Type": "AWS::EC2::SecurityGroup",
"Properties": {
"GroupDescription": "Security group for Lambda",
"VpcId": {"Ref": "VPC"},
"SecurityGroupEgress" : [
{ "IpProtocol" : "tcp", "FromPort" : "1", "ToPort" : "65535", "CidrIp" : "0.0.0.0/0"}
]
}
},
"NatSecurityGroup" : {
"DependsOn" : ["VPC"],
"Type" : "AWS::EC2::SecurityGroup",
"Properties" : {
"GroupDescription" : "NAT Security Group",
"VpcId" : { "Ref" : "VPC" },
"SecurityGroupIngress" : [
{ "IpProtocol" : "tcp", "FromPort" : "1", "ToPort" : "65535", "SourceSecurityGroupId" : { "Ref" : "LambdaSecurityGroup" } }
],
"SecurityGroupEgress" : [
{ "IpProtocol" : "tcp", "FromPort" : "1", "ToPort" : "65535", "CidrIp" : "0.0.0.0/0"}
]
}
},
Створіть NAT і додайте його маршрут:
"NAT" : {
"DependsOn" : ["SubnetPublic", "NatSecurityGroup"],
"Type" : "AWS::EC2::Instance",
"Properties" : {
"InstanceType" : "t2.nano",
"SourceDestCheck" : "false",
"ImageId" : { "Fn::FindInMap" : [ "NatRegionMap", { "Ref" : "AWS::Region" }, "AMI" ]},
"NetworkInterfaces" : [{
"GroupSet": [{ "Ref" : "NatSecurityGroup" }],
"AssociatePublicIpAddress": "true",
"DeviceIndex": "0",
"DeleteOnTermination": "true",
"SubnetId": { "Ref" : "SubnetPublic" }
}],
"UserData": { "Fn::Base64" : { "Fn::Join" : ["", [
"#!/bin/bash\n",
"yum update -y && yum install -y yum-cron && chkconfig yum-cron on"
]]}}
}
},
Мої функції лямбда все ще не мають доступу до Інтернету. Вони просто таймаут. Що я роблю неправильно?
Оновлення Нижче наведено повну хмарну інформацію мінус body
значення AWS::ApiGateway::RestApi
. Халат був просто великим для публікації.
{
"AWSTemplateFormatVersion": "2010-09-09",
"Description": "Website",
"Parameters": {
"DomainName": {
"Type": "String",
"Description": "The DNS name of an Amazon Route 53 hosted zone e.g. server.com",
"AllowedPattern": "(?!-)[a-zA-Z0-9-.]{1,63}(?<!-)",
"ConstraintDescription": "must be a valid DNS zone name."
},
"DBUsername": {
"Type": "String",
"Description": "Master username",
"AllowedPattern": "[a-zA-Z0-9]{1,20}(?<!-)",
"ConstraintDescription": "must be a valid username."
},
"DBPassword": {
"Type": "String",
"Description": "Master password",
"AllowedPattern": "[a-zA-Z0-9]{1,20}(?<!-)",
"ConstraintDescription": "must be a valid password."
}
},
"Mappings": {
"SubnetConfig" : {
"VPC" : { "CIDR" : "10.0.0.0/16" },
"Public" : { "CIDR" : "10.0.100.0/24" },
"PrivateA" : { "CIDR" : "10.0.10.0/24" },
"PrivateB" : { "CIDR" : "10.0.20.0/24" }
},
"NatRegionMap" : {
"us-east-1" : { "AMI" : "ami-eccf48fa" },
"us-west-1" : { "AMI" : "ami-d9247eb9" },
"us-west-2" : { "AMI" : "ami-8c55c2ec" },
"eu-west-1" : { "AMI" : "ami-ea08368c" },
"eu-central-1" : { "AMI" : "ami-7604d419" },
"sa-east-1" : { "AMI" : "ami-2070134c" },
"ap-southeast-1" : { "AMI" : "ami-21ba0542" },
"ap-southeast-2" : { "AMI" : "ami-5cf4fb3f" },
"ap-northeast-1" : { "AMI" : "ami-d599bdb2" }
},
"S3RegionMap": {
"us-east-1": { "S3HostedZoneId": "Z3AQBSTGFYJSTF", "S3WebsiteEndpoint": "s3-website-us-east-1.amazonaws.com" },
"us-west-1": { "S3HostedZoneId": "Z2F56UZL2M1ACD", "S3WebsiteEndpoint": "s3-website-us-west-1.amazonaws.com" },
"us-west-2": { "S3HostedZoneId": "Z3BJ6K6RIION7M", "S3WebsiteEndpoint": "s3-website-us-west-2.amazonaws.com" },
"eu-west-1": { "S3HostedZoneId": "Z1BKCTXD74EZPE", "S3WebsiteEndpoint": "s3-website-eu-west-1.amazonaws.com" },
"ap-southeast-1": { "S3HostedZoneId": "Z3O0J2DXBE1FTB", "S3WebsiteEndpoint": "s3-website-ap-southeast-1.amazonaws.com" },
"ap-southeast-2": { "S3HostedZoneId": "Z1WCIGYICN2BYD", "S3WebsiteEndpoint": "s3-website-ap-southeast-2.amazonaws.com" },
"ap-northeast-1": { "S3HostedZoneId": "Z2M4EHUR26P7ZW", "S3WebsiteEndpoint": "s3-website-ap-northeast-1.amazonaws.com" },
"sa-east-1": { "S3HostedZoneId": "Z31GFT0UA1I2HV", "S3WebsiteEndpoint": "s3-website-sa-east-1.amazonaws.com" }
}
},
"Resources": {
"LambdaExecutionRole": {
"Type": "AWS::IAM::Role",
"Properties": {
"AssumeRolePolicyDocument": {
"Statement": [{
"Effect": "Allow",
"Principal": {
"Service": "lambda.amazonaws.com"
},
"Action": [ "sts:AssumeRole" ]
}]
},
"Path": "/",
"Policies": [{
"PolicyName": "execution",
"PolicyDocument": {
"Statement": [{
"Effect": "Allow",
"Action": [
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:PutLogEvents"
],
"Resource": "*"
}, {
"Effect": "Allow",
"Action": [
"s3:GetObject",
"s3:PutObject",
"s3:ListBucket"
],
"Resource": "*"
}, {
"Effect": "Allow",
"Action": [
"ec2:DescribeNetworkInterfaces",
"ec2:CreateNetworkInterface",
"ec2:DeleteNetworkInterface"
],
"Resource": "*"
}]
}
}]
}
},
"APIGatewayExecutionRole": {
"Type": "AWS::IAM::Role",
"Properties": {
"AssumeRolePolicyDocument": {
"Statement": [{
"Effect": "Allow",
"Principal": {
"Service": "apigateway.amazonaws.com"
},
"Action": [ "sts:AssumeRole" ]
}]
},
"Path": "/",
"Policies": [{
"PolicyName": "execution",
"PolicyDocument": {
"Statement": [{
"Effect": "Allow",
"Action": [
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:PutLogEvents"
],
"Resource": "*"
}, {
"Effect": "Allow",
"Action": [
"lambda:InvokeFunction"
],
"Resource": "*"
}]
}
}]
}
},
"VPC": {
"Type": "AWS::EC2::VPC",
"Properties": {
"CidrBlock": { "Fn::FindInMap" : [ "SubnetConfig", "VPC", "CIDR" ]},
"EnableDnsSupport": "true",
"EnableDnsHostnames": "true",
"InstanceTenancy": "default",
"Tags" : [
{"Key": "Name", "Value": { "Fn::Join" : ["_", ["VPC", { "Ref": "AWS::StackName" } ]]}},
{"Key": "Domain", "Value": { "Ref": "DomainName" }}
]
}
},
"PublicRouteTable" : {
"Type" : "AWS::EC2::RouteTable",
"Properties" : {
"VpcId" : { "Ref" : "VPC" },
"Tags" : [
{"Key": "Name", "Value": { "Fn::Join" : ["_", ["PublicRouteTable", { "Ref": "AWS::StackName" } ]]}},
{"Key": "Domain", "Value": { "Ref": "DomainName" }}
]
}
},
"PrivateRouteTable" : {
"Type" : "AWS::EC2::RouteTable",
"Properties" : {
"VpcId" : { "Ref" : "VPC" },
"Tags" : [
{"Key": "Name", "Value": { "Fn::Join" : ["_", ["PrivateRouteTable", { "Ref": "AWS::StackName" } ]]}},
{"Key": "Domain", "Value": { "Ref": "DomainName" }}
]
}
},
"InternetGateway" : {
"Type" : "AWS::EC2::InternetGateway",
"Properties" : {
"Tags" : [
{"Key": "Name", "Value": { "Fn::Join" : ["_", ["InternetGateway", { "Ref": "AWS::StackName" } ]]}},
{"Key": "Domain", "Value": { "Ref": "DomainName" }}
]
}
},
"AttachGateway": {
"Type" : "AWS::EC2::VPCGatewayAttachment",
"Properties" : {
"VpcId" : { "Ref" : "VPC" },
"InternetGatewayId" : { "Ref" : "InternetGateway" }
}
},
"InternetRoute" : {
"Type" : "AWS::EC2::Route",
"DependsOn" : "InternetGateway",
"Properties" : {
"RouteTableId" : { "Ref" : "PublicRouteTable" },
"DestinationCidrBlock" : "0.0.0.0/0",
"GatewayId" : { "Ref" : "InternetGateway" }
}
},
"SubnetPrivateA": {
"Type": "AWS::EC2::Subnet",
"DependsOn" : ["VPC"],
"Properties": {
"VpcId": { "Ref": "VPC" },
"CidrBlock": { "Fn::FindInMap" : [ "SubnetConfig", "PrivateA", "CIDR" ]},
"AvailabilityZone": { "Fn::Select": [ "0", { "Fn::GetAZs": { "Ref": "AWS::Region" } }]},
"Tags" : [
{"Key": "Name", "Value": { "Fn::Join" : ["_", ["SubnetPrivateA", { "Ref": "AWS::StackName" } ]]}},
{"Key": "Domain", "Value": { "Ref": "DomainName" }}
]
}
},
"SubnetPrivateB": {
"Type": "AWS::EC2::Subnet",
"DependsOn" : ["VPC"],
"Properties": {
"VpcId": { "Ref": "VPC" },
"CidrBlock": { "Fn::FindInMap" : [ "SubnetConfig", "PrivateB", "CIDR" ]},
"AvailabilityZone": { "Fn::Select": [ "1", { "Fn::GetAZs": { "Ref": "AWS::Region" } }]},
"Tags" : [
{"Key": "Name", "Value": { "Fn::Join" : ["_", ["SubnetPrivateB", { "Ref": "AWS::StackName" } ]]}},
{"Key": "Domain", "Value": { "Ref": "DomainName" }}
]
}
},
"SubnetPublic": {
"Type": "AWS::EC2::Subnet",
"DependsOn" : ["VPC"],
"Properties": {
"VpcId": { "Ref": "VPC" },
"CidrBlock": { "Fn::FindInMap" : [ "SubnetConfig", "Public", "CIDR" ]},
"AvailabilityZone": { "Fn::Select": [ "1", { "Fn::GetAZs": { "Ref": "AWS::Region" } }]},
"Tags" : [
{"Key": "Name", "Value": { "Fn::Join" : ["_", ["SubnetPublic", { "Ref": "AWS::StackName" } ]]}},
{"Key": "Domain", "Value": { "Ref": "DomainName" }}
]
}
},
"SubnetPrivateARouteTableAssociation" : {
"Type" : "AWS::EC2::SubnetRouteTableAssociation",
"Properties" : {
"SubnetId" : { "Ref" : "SubnetPrivateA" },
"RouteTableId" : { "Ref" : "PrivateRouteTable" }
}
},
"SubnetPrivateBRouteTableAssociation" : {
"Type" : "AWS::EC2::SubnetRouteTableAssociation",
"Properties" : {
"SubnetId" : { "Ref" : "SubnetPrivateB" },
"RouteTableId" : { "Ref" : "PrivateRouteTable" }
}
},
"SubnetPublicRouteTableAssociation" : {
"Type" : "AWS::EC2::SubnetRouteTableAssociation",
"Properties" : {
"SubnetId" : { "Ref" : "SubnetPublic" },
"RouteTableId" : { "Ref" : "PublicRouteTable" }
}
},
"DBSubnetGroup": {
"Type": "AWS::RDS::DBSubnetGroup",
"Properties": {
"DBSubnetGroupDescription": "Database Access",
"SubnetIds" : [{ "Ref": "SubnetPrivateA"}, {"Ref": "SubnetPrivateB" }],
"Tags" : [
{"Key": "Name", "Value": { "Fn::Join" : ["_", ["DBSubnetGroup", { "Ref": "AWS::StackName" } ]]}},
{"Key": "Domain", "Value": { "Ref": "DomainName" }}
]
}
},
"DBEC2SecurityGroup": {
"Type": "AWS::EC2::SecurityGroup",
"Properties": {
"GroupDescription": "Security group for RDS DB Instance",
"VpcId": {"Ref": "VPC"},
"SecurityGroupIngress" : [{
"IpProtocol": "tcp",
"FromPort": "3306",
"ToPort": "3306",
"CidrIp": "10.0.0.0/16"
}],
"Tags" : [
{"Key": "Name", "Value": { "Fn::Join" : ["_", ["DBEC2SecurityGroup", { "Ref": "AWS::StackName" } ]]}},
{"Key": "Domain", "Value": { "Ref": "DomainName" }}
]
}
},
"LambdaSecurityGroup": {
"Type": "AWS::EC2::SecurityGroup",
"Properties": {
"GroupDescription": "Security group for Lambda",
"VpcId": {"Ref": "VPC"},
"SecurityGroupEgress" : [
{ "IpProtocol" : "tcp", "FromPort" : "1", "ToPort" : "65535", "CidrIp" : "0.0.0.0/0"}
],
"Tags" : [
{"Key": "Name", "Value": { "Fn::Join" : ["_", ["LambdaSecurityGroup", { "Ref": "AWS::StackName" } ]]}},
{"Key": "Domain", "Value": { "Ref": "DomainName" }}
]
}
},
"NatSecurityGroup" : {
"DependsOn" : ["VPC"],
"Type" : "AWS::EC2::SecurityGroup",
"Properties" : {
"GroupDescription" : "NAT Security Group",
"VpcId" : { "Ref" : "VPC" },
"SecurityGroupIngress" : [
{ "IpProtocol" : "tcp", "FromPort" : "1", "ToPort" : "65535", "SourceSecurityGroupId" : { "Ref" : "LambdaSecurityGroup" } }
],
"SecurityGroupEgress" : [
{ "IpProtocol" : "tcp", "FromPort" : "1", "ToPort" : "65535", "CidrIp" : "0.0.0.0/0"}
],
"Tags" : [
{"Key": "Name", "Value": { "Fn::Join" : ["_", ["NatSecurityGroup", { "Ref": "AWS::StackName" } ]]}},
{"Key": "Domain", "Value": { "Ref": "DomainName" }}
]
}
},
"NAT" : {
"DependsOn" : ["SubnetPublic", "NatSecurityGroup"],
"Type" : "AWS::EC2::Instance",
"Properties" : {
"InstanceType" : "t2.nano",
"SourceDestCheck" : "false",
"ImageId" : { "Fn::FindInMap" : [ "NatRegionMap", { "Ref" : "AWS::Region" }, "AMI" ]},
"NetworkInterfaces" : [{
"GroupSet": [{ "Ref" : "NatSecurityGroup" }],
"AssociatePublicIpAddress": "true",
"DeviceIndex": "0",
"DeleteOnTermination": "true",
"SubnetId": { "Ref" : "SubnetPublic" }
}],
"Tags" : [
{"Key": "Name", "Value": { "Fn::Join" : ["_", ["NAT", { "Ref": "AWS::StackName" } ]]}},
{"Key": "Domain", "Value": { "Ref": "DomainName" }}
],
"UserData": { "Fn::Base64" : { "Fn::Join" : ["", [
"#!/bin/bash\n",
"yum update -y && yum install -y yum-cron && chkconfig yum-cron on"
]]}}
}
},
"PrivateRoute" : {
"DependsOn" : ["PrivateRouteTable", "NAT"],
"Type" : "AWS::EC2::Route",
"Properties" : {
"RouteTableId" : { "Ref" : "PrivateRouteTable" },
"DestinationCidrBlock" : "0.0.0.0/0",
"InstanceId" : { "Ref" : "NAT" }
}
},
"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": "DBSubnetGroup" },
"VPCSecurityGroups" : [{ "Fn::GetAtt": [ "DBEC2SecurityGroup", "GroupId" ] }],
"Tags" : [
{"Key": "Name", "Value": { "Fn::Join" : ["_", ["Database", { "Ref": "AWS::StackName" } ]]}},
{"Key": "Domain", "Value": { "Ref": "DomainName" }}
]
},
"DeletionPolicy": "Snapshot"
},
"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": ["LambdaSecurityGroup", "GroupId"] }],
"SubnetIds": [{"Ref": "SubnetPrivateA"}, {"Ref": "SubnetPrivateB"}]
}
}
},
"LambdaFunctionValidate": {
"Type": "AWS::Lambda::Function",
"Properties": {
"Code": {
"ZipFile": "exports.handler = function (event, context) { context.succeed(\"Hello, World!\"); };"
},
"Description": "Used to validate a users access token",
"Handler": "index.handler",
"MemorySize": 128,
"Role": { "Fn::GetAtt": ["LambdaExecutionRole", "Arn" ] },
"Runtime": "nodejs4.3",
"Timeout": 30,
"VpcConfig": {
"SecurityGroupIds": [{ "Fn::GetAtt": ["LambdaSecurityGroup", "GroupId"] }],
"SubnetIds": [{"Ref": "SubnetPrivateA"}, {"Ref": "SubnetPrivateB"}]
}
}
},
"LambdaFunctionPicture": {
"Type": "AWS::Lambda::Function",
"Properties": {
"Code": {
"ZipFile": "exports.handler = function (event, context) { context.succeed(\"Hello, World!\"); };"
},
"Description": "Picture resource handler.",
"Handler": "index.handler",
"MemorySize": 128,
"Role": { "Fn::GetAtt": ["LambdaExecutionRole", "Arn" ] },
"Runtime": "nodejs4.3",
"Timeout": 30,
"VpcConfig": {
"SecurityGroupIds": [{ "Fn::GetAtt": ["LambdaSecurityGroup", "GroupId"] }],
"SubnetIds": [{"Ref": "SubnetPrivateA"}, {"Ref": "SubnetPrivateB"}]
}
}
},
"LambdaFunctionReputation": {
"Type": "AWS::Lambda::Function",
"Properties": {
"Code": {
"ZipFile": "exports.handler = function (event, context) { context.succeed(\"Hello, World!\"); };"
},
"Description": "Reputation handler.",
"Handler": "index.handler",
"MemorySize": 128,
"Role": { "Fn::GetAtt": ["LambdaExecutionRole", "Arn" ] },
"Runtime": "nodejs4.3",
"Timeout": 30,
"VpcConfig": {
"SecurityGroupIds": [{ "Fn::GetAtt": ["LambdaSecurityGroup", "GroupId"] }],
"SubnetIds": [{"Ref": "SubnetPrivateA"}, {"Ref": "SubnetPrivateB"}]
}
}
},
"LambdaFunctionUser": {
"Type": "AWS::Lambda::Function",
"Properties": {
"Code": {
"ZipFile": "exports.handler = function (event, context) { context.succeed(\"Hello, World!\"); };"
},
"Description": "User handler.",
"Handler": "index.handler",
"MemorySize": 128,
"Role": { "Fn::GetAtt": ["LambdaExecutionRole", "Arn" ] },
"Runtime": "nodejs4.3",
"Timeout": 30,
"VpcConfig": {
"SecurityGroupIds": [{ "Fn::GetAtt": ["LambdaSecurityGroup", "GroupId"] }],
"SubnetIds": [{"Ref": "SubnetPrivateA"}, {"Ref": "SubnetPrivateB"}]
}
}
},
"APIGateway": {
"Type": "AWS::ApiGateway::RestApi",
"Properties": {
"Body": [REMOVED FROM POST, ITS LONG],
"FailOnWarnings": true,
"Name": { "Fn::Join": ["-", { "Fn::Split": [".", { "Fn::Join": ["", ["api.", { "Ref": "DomainName" }]]}]}]}
}
},
"APIDeployment": {
"Type": "AWS::ApiGateway::Deployment",
"Properties": {
"RestApiId": { "Ref": "APIGateway" },
"Description": "Deploy for live",
"StageName": "Live"
}
},
"WebsiteBucket": {
"Type": "AWS::S3::Bucket",
"Properties": {
"BucketName": {"Ref":"DomainName"},
"AccessControl": "PublicRead",
"WebsiteConfiguration": {
"IndexDocument": "index.html",
"ErrorDocument": "404.html"
},
"Tags" : [
{"Key": "Name", "Value": { "Fn::Join" : ["_", ["WebsiteBucket", { "Ref": "AWS::StackName" } ]]}},
{"Key": "Domain", "Value": { "Ref": "DomainName" }}
]
},
"DeletionPolicy": "Retain"
},
"WWWBucket": {
"Type": "AWS::S3::Bucket",
"Properties": {
"BucketName": {
"Fn::Join": ["", ["www.", { "Ref":"DomainName" }]]
},
"AccessControl": "BucketOwnerFullControl",
"WebsiteConfiguration": {
"RedirectAllRequestsTo": {
"HostName": {"Ref": "WebsiteBucket"}
}
},
"Tags" : [
{"Key": "Name", "Value": { "Fn::Join" : ["_", ["WWWBucket", { "Ref": "AWS::StackName" } ]]}},
{"Key": "Domain", "Value": { "Ref": "DomainName" }}
]
}
},
"WebsiteBucketPolicy": {
"Type": "AWS::S3::BucketPolicy",
"Properties": {
"Bucket": {"Ref": "WebsiteBucket"},
"PolicyDocument": {
"Statement": [{
"Action": [ "s3:GetObject" ],
"Effect": "Allow",
"Resource": { "Fn::Join" : ["", ["arn:aws:s3:::", { "Ref": "WebsiteBucket" } , "/*" ]]},
"Principal": "*"
}]
}
}
},
"WWWBucketPolicy": {
"Type": "AWS::S3::BucketPolicy",
"Properties": {
"Bucket": {"Ref": "WWWBucket"},
"PolicyDocument": {
"Statement": [{
"Action": [ "s3:GetObject" ],
"Effect": "Allow",
"Resource": { "Fn::Join" : ["", ["arn:aws:s3:::", { "Ref": "WWWBucket" } , "/*" ]]},
"Principal": "*"
}]
}
}
},
"DNS": {
"Type": "AWS::Route53::HostedZone",
"Properties": {
"HostedZoneConfig": {
"Comment": { "Fn::Join" : ["", ["Hosted zone for ", { "Ref": "DomainName" }]]}
},
"Name": { "Ref": "DomainName" },
"HostedZoneTags" : [{
"Key": "Application",
"Value": "Blog"
}]
}
},
"DNSRecord": {
"Type": "AWS::Route53::RecordSetGroup",
"Properties": {
"HostedZoneName": {
"Fn::Join": [ "", [{ "Ref": "DomainName" }, "." ]]
},
"Comment": "Zone records.",
"RecordSets": [
{
"Name": { "Ref": "DomainName" },
"Type": "A",
"AliasTarget": {
"HostedZoneId": { "Fn::FindInMap" : [ "S3RegionMap", { "Ref": "AWS::Region" }, "S3HostedZoneId" ]},
"DNSName": { "Fn::FindInMap" : [ "S3RegionMap", { "Ref": "AWS::Region" }, "S3WebsiteEndpoint" ]}
}
}, {
"Name": { "Fn::Join" : ["", ["www.", { "Ref": "DomainName" }]]},
"Type": "A",
"AliasTarget": {
"HostedZoneId": { "Fn::FindInMap" : [ "S3RegionMap", { "Ref": "AWS::Region" }, "S3HostedZoneId" ]},
"DNSName": { "Fn::FindInMap" : [ "S3RegionMap", { "Ref": "AWS::Region" }, "S3WebsiteEndpoint" ]}
}
}
]
}
}
},
"Outputs": {
"S3WebsiteURL": {
"Value": { "Fn::GetAtt": ["WebsiteBucket", "WebsiteURL" ] },
"Description": "URL for website hosted on S3"
},
"DatabaseEndpoint": {
"Value": { "Fn::Join" : [":", [{ "Fn::GetAtt": ["Database", "Endpoint.Address" ] }, { "Fn::GetAtt": ["Database", "Endpoint.Port" ] }]]},
"Description": "Database endpoint"
},
"NATIP" : {
"Description" : "NAT IP address",
"Value" : { "Fn::GetAtt" : [ "NAT", "PublicIp" ] }
}
}
}