setup-ipsec-vpn/aws/cloudformation-template-ipsec
S. X. Liang 08c6ab2135
Update cloudformation-template-ipsec (#850)
* Update cloudformation-template-ipsec

- Add "CreationPolicy" to notify the user when the setup script succeeds on the virtual machine. The stack fails if the script fails.
- The timeout is 10 minutes.
- This feature is to be tested on Debian(s). I have personally tested it on Ubuntu20.

* Update README.md

- Remove the notice no longer needed. (The stack will be flagged as CREATE_COMPLETE only when the script succeeds on the VM.)

* Update README-zh.md

- 移除没用的贴士。堆栈将会自动检查脚本是否成功执行。
2020-11-07 14:41:22 -06:00

822 lines
28 KiB
Plaintext

{
"AWSTemplateFormatVersion": "2010-09-09",
"Metadata": {
"AWS::CloudFormation::Designer": {
"0a162613-8f2e-4864-be99-75d946934a4a": {
"size": {
"width": 350,
"height": 440
},
"position": {
"x": 290,
"y": 70
},
"z": 1,
"embeds": [
"5198eb6d-da4f-43e2-8a4b-b9bff02b26a2"
]
},
"5198eb6d-da4f-43e2-8a4b-b9bff02b26a2": {
"size": {
"width": 290,
"height": 360
},
"position": {
"x": 310,
"y": 110
},
"z": 2,
"parent": "0a162613-8f2e-4864-be99-75d946934a4a",
"embeds": [
"9d4cbbc2-f521-436d-bb4a-85b82cf22a2a",
"464ea4ae-199c-4917-9404-aed674a8615a",
"ec256f27-66c3-423c-9d98-b9f0f634e7b8",
"4731d93c-f3fc-420a-b535-f0b99840f356",
"40c2d4e7-f01a-45b2-8878-a06680aa2216"
],
"dependson": [
"0a162613-8f2e-4864-be99-75d946934a4a",
"464ea4ae-199c-4917-9404-aed674a8615a"
]
},
"4731d93c-f3fc-420a-b535-f0b99840f356": {
"size": {
"width": 230,
"height": 130
},
"position": {
"x": 350,
"y": 320
},
"z": 3,
"parent": "5198eb6d-da4f-43e2-8a4b-b9bff02b26a2",
"embeds": [
"5262ea47-2337-4be8-a4d1-1f0af38a1731"
],
"iscontainedinside": [
"0a162613-8f2e-4864-be99-75d946934a4a"
],
"dependson": [
"5198eb6d-da4f-43e2-8a4b-b9bff02b26a2"
]
},
"5262ea47-2337-4be8-a4d1-1f0af38a1731": {
"size": {
"width": 60,
"height": 60
},
"position": {
"x": 440,
"y": 350
},
"z": 4,
"parent": "4731d93c-f3fc-420a-b535-f0b99840f356",
"embeds": [],
"isassociatedwith": [
"db7c3441-9f9a-4677-a14d-bccfc06714d1"
],
"dependson": [
"4731d93c-f3fc-420a-b535-f0b99840f356",
"9d3d19ab-d561-4f59-89de-73498eeeebda",
"464ea4ae-199c-4917-9404-aed674a8615a"
]
},
"464ea4ae-199c-4917-9404-aed674a8615a": {
"size": {
"width": 60,
"height": 60
},
"position": {
"x": 510,
"y": 220
},
"z": 3,
"parent": "5198eb6d-da4f-43e2-8a4b-b9bff02b26a2",
"embeds": [],
"dependson": [
"0a162613-8f2e-4864-be99-75d946934a4a"
]
},
"40c2d4e7-f01a-45b2-8878-a06680aa2216": {
"size": {
"width": 60,
"height": 60
},
"position": {
"x": 430,
"y": 140
},
"z": 3,
"parent": "5198eb6d-da4f-43e2-8a4b-b9bff02b26a2",
"embeds": [],
"iscontainedinside": [
"5198eb6d-da4f-43e2-8a4b-b9bff02b26a2",
"5198eb6d-da4f-43e2-8a4b-b9bff02b26a2",
"5198eb6d-da4f-43e2-8a4b-b9bff02b26a2",
"5198eb6d-da4f-43e2-8a4b-b9bff02b26a2",
"5198eb6d-da4f-43e2-8a4b-b9bff02b26a2",
"5198eb6d-da4f-43e2-8a4b-b9bff02b26a2",
"5198eb6d-da4f-43e2-8a4b-b9bff02b26a2",
"5198eb6d-da4f-43e2-8a4b-b9bff02b26a2",
"5198eb6d-da4f-43e2-8a4b-b9bff02b26a2"
],
"dependson": [
"4731d93c-f3fc-420a-b535-f0b99840f356",
"9d4cbbc2-f521-436d-bb4a-85b82cf22a2a",
"99fce86e-18b8-4b1b-a572-7bef3c5cece7",
"58a1ab6f-49ac-4ffa-93c7-3f708bf65871",
"ec256f27-66c3-423c-9d98-b9f0f634e7b8"
]
},
"9d4cbbc2-f521-436d-bb4a-85b82cf22a2a": {
"size": {
"width": 60,
"height": 60
},
"position": {
"x": 350,
"y": 140
},
"z": 3,
"parent": "5198eb6d-da4f-43e2-8a4b-b9bff02b26a2",
"embeds": []
},
"ec256f27-66c3-423c-9d98-b9f0f634e7b8": {
"size": {
"width": 60,
"height": 60
},
"position": {
"x": 430,
"y": 220
},
"z": 3,
"parent": "5198eb6d-da4f-43e2-8a4b-b9bff02b26a2",
"embeds": [],
"iscontainedinside": [
"0a162613-8f2e-4864-be99-75d946934a4a"
]
},
"5bb16646-dc1e-4661-9164-6ecc6848dc83": {
"source": {
"id": "4731d93c-f3fc-420a-b535-f0b99840f356"
},
"target": {
"id": "5198eb6d-da4f-43e2-8a4b-b9bff02b26a2"
},
"z": 3
},
"99fce86e-18b8-4b1b-a572-7bef3c5cece7": {
"size": {
"width": 60,
"height": 60
},
"position": {
"x": 150,
"y": 250
},
"z": 1,
"embeds": []
},
"58a1ab6f-49ac-4ffa-93c7-3f708bf65871": {
"size": {
"width": 60,
"height": 60
},
"position": {
"x": 150,
"y": 170
},
"z": 1,
"embeds": []
},
"d3fab7a7-d694-435e-930d-ff7693dffbbc": {
"size": {
"width": 60,
"height": 60
},
"position": {
"x": 110,
"y": 90
},
"z": 1,
"embeds": []
},
"2c5cc5a9-5a17-4d54-80ea-56e204c9c1a1": {
"size": {
"width": 60,
"height": 60
},
"position": {
"x": 70,
"y": 170
},
"z": 1,
"embeds": []
},
"e81dfbbc-e8ee-4f4b-adb0-b314056ab0b3": {
"size": {
"width": 60,
"height": 60
},
"position": {
"x": 70,
"y": 250
},
"z": 1,
"embeds": []
},
"9d3d19ab-d561-4f59-89de-73498eeeebda": {
"source": {
"id": "0a162613-8f2e-4864-be99-75d946934a4a"
},
"target": {
"id": "464ea4ae-199c-4917-9404-aed674a8615a"
},
"z": 3
},
"361e0035-6c5a-48df-8339-3e31f19bf032": {
"source": {
"id": "9d4cbbc2-f521-436d-bb4a-85b82cf22a2a"
},
"target": {
"id": "40c2d4e7-f01a-45b2-8878-a06680aa2216"
},
"z": 3
}
}
},
"Resources": {
"VpnVpc": {
"Type": "AWS::EC2::VPC",
"Properties": {
"CidrBlock": "10.0.0.0/24"
},
"Metadata": {
"AWS::CloudFormation::Designer": {
"id": "0a162613-8f2e-4864-be99-75d946934a4a"
}
}
},
"VpnSubnet": {
"Type": "AWS::EC2::Subnet",
"Properties": {
"VpcId": {
"Ref": "VpnVpc"
},
"CidrBlock": "10.0.0.0/24",
"MapPublicIpOnLaunch": true,
"AvailabilityZone": {
"Fn::Sub": "${AWS::Region}a"
}
},
"Metadata": {
"AWS::CloudFormation::Designer": {
"id": "5198eb6d-da4f-43e2-8a4b-b9bff02b26a2"
}
},
"DependsOn": [
"VpnVpc",
"VpcInternetGateway"
]
},
"VpnRouteTable": {
"Type": "AWS::EC2::RouteTable",
"Properties": {
"VpcId": {
"Ref": "VpnVpc"
}
},
"Metadata": {
"AWS::CloudFormation::Designer": {
"id": "4731d93c-f3fc-420a-b535-f0b99840f356"
}
},
"DependsOn": [
"VpnSubnet"
]
},
"PublicInternetRoute": {
"Type": "AWS::EC2::Route",
"Properties": {
"DestinationCidrBlock": "0.0.0.0/0",
"RouteTableId": {
"Ref": "VpnRouteTable"
},
"GatewayId": {
"Ref": "VpcInternetGateway"
}
},
"Metadata": {
"AWS::CloudFormation::Designer": {
"id": "5262ea47-2337-4be8-a4d1-1f0af38a1731"
}
},
"DependsOn": [
"VpnRouteTable",
"VpcInternetGateway",
"InternetGatewayAttachment"
]
},
"VpnInstance": {
"Type": "AWS::EC2::Instance",
"CreationPolicy": {
"ResourceSignal": {
"Timeout": "PT10M"
}
},
"Properties": {
"UserData": {
"Fn::Base64": {
"Fn::Join": [
"",
[
"#!/bin/bash -x\n",
"export VPN_IPSEC_PSK='",
{
"Ref": "VpnIpsecPsk"
},
"'\n",
"export VPN_USER='",
{
"Ref": "VpnUser"
},
"'\n",
"export VPN_PASSWORD='",
{
"Ref": "VpnPassword"
},
"'\n",
"sleep 60\n",
"wget https://git.io/vpnsetup -O vpnsetup.sh && sh vpnsetup.sh\n",
"apt-get install python3-pip -y\n",
"pip3 install https://s3.amazonaws.com/cloudformation-examples/aws-cfn-bootstrap-py3-latest.tar.gz\n",
"cfn-signal ",
"--stack ",
{
"Ref": "AWS::StackName"
},
" --resource VpnInstance ",
" --region ",
{
"Ref": "AWS::Region"
},
"\n"
]
]
}
},
"SecurityGroupIds": [
{
"Fn::GetAtt": [
"VpnSecurityGroup",
"GroupId"
]
}
],
"SubnetId": {
"Ref": "VpnSubnet"
},
"AvailabilityZone": {
"Fn::Sub": "${AWS::Region}a"
},
"InstanceType": {
"Ref": "InstanceType"
},
"KeyName": {
"Fn::GetAtt": [
"KeyPairInfo",
"KeyName"
]
},
"ImageId": {
"Fn::GetAtt": [
"AMIInfo",
"AMIId"
]
}
},
"Metadata": {
"AWS::CloudFormation::Designer": {
"id": "40c2d4e7-f01a-45b2-8878-a06680aa2216"
}
},
"DependsOn": [
"VpnRouteTable",
"VpnServerVolume",
"KeyPairCreation",
"AMIInfoFunction",
"VpnSecurityGroup"
]
},
"VpnSecurityGroup": {
"Type": "AWS::EC2::SecurityGroup",
"Properties": {
"GroupDescription": "The VPN Security Group, allowing ingress UDP traffic at port 4500 and 500.",
"GroupName": "VpnSecurityGroup",
"VpcId": {
"Ref": "VpnVpc"
},
"SecurityGroupIngress": [
{
"CidrIp": "0.0.0.0/0",
"IpProtocol": "tcp",
"FromPort": 22,
"ToPort": 22
},
{
"CidrIp": "0.0.0.0/0",
"IpProtocol": "udp",
"FromPort": 500,
"ToPort": 500
},
{
"CidrIp": "0.0.0.0/0",
"IpProtocol": "udp",
"FromPort": 4500,
"ToPort": 4500
}
],
"SecurityGroupEgress": [
{
"CidrIp": "0.0.0.0/0",
"IpProtocol": -1
}
]
},
"Metadata": {
"AWS::CloudFormation::Designer": {
"id": "ec256f27-66c3-423c-9d98-b9f0f634e7b8"
}
}
},
"VpnServerVolume": {
"Type": "AWS::EC2::Volume",
"Properties": {
"AvailabilityZone": {
"Fn::Sub": "${AWS::Region}a"
},
"Size": 8
},
"Metadata": {
"AWS::CloudFormation::Designer": {
"id": "9d4cbbc2-f521-436d-bb4a-85b82cf22a2a"
}
}
},
"VpcInternetGateway": {
"Type": "AWS::EC2::InternetGateway",
"Properties": {},
"Metadata": {
"AWS::CloudFormation::Designer": {
"id": "464ea4ae-199c-4917-9404-aed674a8615a"
}
},
"DependsOn": [
"VpnVpc"
]
},
"EC2SRTA4VJU5": {
"Type": "AWS::EC2::SubnetRouteTableAssociation",
"Properties": {
"RouteTableId": {
"Ref": "VpnRouteTable"
},
"SubnetId": {
"Ref": "VpnSubnet"
}
},
"Metadata": {
"AWS::CloudFormation::Designer": {
"id": "5bb16646-dc1e-4661-9164-6ecc6848dc83"
}
}
},
"KeyPairCreation": {
"Type": "AWS::Lambda::Function",
"Properties": {
"Handler": "index.handler",
"Runtime": "python3.7",
"Role": {
"Fn::GetAtt": [
"LambdaExecutionRole",
"Arn"
]
},
"Timeout": 30,
"Code": {
"ZipFile": {
"Fn::Join": [
"\n",
[
"import boto3",
"import cfnresponse",
"import string",
"import random",
"'''",
"This python program should be embedded into its designated cloudformation",
"template as the inline code of one of the lambda functions.",
"'''",
"def handler(event, context):",
" try:",
" keyName = ''.join(random.SystemRandom().choice(string.ascii_letters + string.digits) for _ in range(10))",
" region = event['ResourceProperties']['Region']",
" ec2 = boto3.client('ec2',region)",
" response = ec2.create_key_pair(",
" KeyName=keyName",
" )",
" keyMaterial = response['KeyMaterial']",
" cfnresponse.send(event, context, cfnresponse.SUCCESS, {'KeyMaterial':keyMaterial, 'KeyName':keyName}, 'KeyPairInfo')",
" except Exception:",
" cfnresponse.send(event, context, cfnresponse.FAILED, {})"
]
]
}
}
},
"Metadata": {
"AWS::CloudFormation::Designer": {
"id": "99fce86e-18b8-4b1b-a572-7bef3c5cece7"
}
},
"DependsOn": [
"LambdaExecutionRole"
]
},
"AMIInfo": {
"Type": "Custom::AMIInfo",
"Properties": {
"Region": {
"Ref": "AWS::Region"
},
"ServiceToken": {
"Fn::GetAtt": [
"AMIInfoFunction",
"Arn"
]
},
"Distribution": {
"Ref": "OS"
}
},
"Metadata": {
"AWS::CloudFormation::Designer": {
"id": "2c5cc5a9-5a17-4d54-80ea-56e204c9c1a1"
}
},
"DependsOn": [
"AMIInfoFunction"
]
},
"AMIInfoFunction": {
"Type": "AWS::Lambda::Function",
"Properties": {
"Handler": "index.handler",
"Runtime": "python3.7",
"Role": {
"Fn::GetAtt": [
"LambdaExecutionRole",
"Arn"
]
},
"Code": {
"ZipFile": {
"Fn::Join": [
"\n",
[
"import boto3",
"import cfnresponse",
"def creation_date(e):",
" return e['CreationDate']",
"",
"def handler(event, context):",
" try:",
" regionName = event['ResourceProperties']['Region']",
" distribution = event['ResourceProperties']['Distribution']",
" ec2 = boto3.client('ec2',regionName)",
" IAMName = ''",
" if distribution == 'Ubuntu16.04':",
" IAMName = 'ubuntu/images/hvm-ssd/ubuntu-xenial-16.04-amd64-server-*'",
" elif distribution == 'Ubuntu18.04':",
" IAMName = 'ubuntu/images/hvm-ssd/ubuntu-bionic-18.04-amd64-server-*'",
" elif distribution == 'Ubuntu20.04':",
" IAMName = 'ubuntu/images/hvm-ssd/ubuntu-focal-20.04-amd64-server-*'",
" elif distribution == 'Debian9':",
" IAMName = 'debian-stretch-hvm-x86_64-gp2-*'",
" response = ec2.describe_images(Filters=[{'Name':'name', 'Values':[IAMName]}], Owners=['099720109477', '379101102735'])",
" images = response['Images']",
" images.sort(key=creation_date,reverse=True)",
" AMIId = images[0]['ImageId']",
" cfnresponse.send(event, context, cfnresponse.SUCCESS, {'AMIId':AMIId}, 'AMIInfo')",
" except Exception:",
" cfnresponse.send(event, context, cfnresponse.FAILED, {})"
]
]
}
},
"Timeout": 30
},
"Metadata": {
"AWS::CloudFormation::Designer": {
"id": "58a1ab6f-49ac-4ffa-93c7-3f708bf65871"
}
},
"DependsOn": [
"LambdaExecutionRole"
]
},
"LambdaExecutionRole": {
"Type": "AWS::IAM::Role",
"Properties": {
"AssumeRolePolicyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "lambda.amazonaws.com"
},
"Action": [
"sts:AssumeRole"
]
},
{
"Effect": "Allow",
"Principal": {
"Service": [
"ec2.amazonaws.com"
]
},
"Action": [
"sts:AssumeRole"
]
}
]
},
"Path": "/",
"Policies": [
{
"PolicyName": "root",
"PolicyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "*",
"Resource": "*"
}
]
}
}
]
},
"Metadata": {
"AWS::CloudFormation::Designer": {
"id": "d3fab7a7-d694-435e-930d-ff7693dffbbc"
}
}
},
"KeyPairInfo": {
"Type": "Custom::KeyPairInfo",
"Properties": {
"Region": {
"Ref": "AWS::Region"
},
"ServiceToken": {
"Fn::GetAtt": [
"KeyPairCreation",
"Arn"
]
}
},
"Metadata": {
"AWS::CloudFormation::Designer": {
"id": "e81dfbbc-e8ee-4f4b-adb0-b314056ab0b3"
}
},
"DependsOn": [
"KeyPairCreation"
]
},
"InternetGatewayAttachment": {
"Type": "AWS::EC2::VPCGatewayAttachment",
"Properties": {
"InternetGatewayId": {
"Ref": "VpcInternetGateway"
},
"VpcId": {
"Ref": "VpnVpc"
}
},
"Metadata": {
"AWS::CloudFormation::Designer": {
"id": "9d3d19ab-d561-4f59-89de-73498eeeebda"
}
}
},
"EC2VA41EUF": {
"Type": "AWS::EC2::VolumeAttachment",
"Properties": {
"Device": "/dev/sdh",
"VolumeId": {
"Ref": "VpnServerVolume"
},
"InstanceId": {
"Ref": "VpnInstance"
}
},
"Metadata": {
"AWS::CloudFormation::Designer": {
"id": "361e0035-6c5a-48df-8339-3e31f19bf032"
}
}
}
},
"Parameters": {
"VpnUser": {
"Type": "String",
"Description": "Your VPN username"
},
"VpnIpsecPsk": {
"Type": "String",
"Description": "Your VPN IPsec PSK (pre-shared key)"
},
"VpnPassword": {
"Type": "String",
"Description": "Your VPN password"
},
"OS": {
"Type": "String",
"Description": "The OS of your VPN server. Default: Ubuntu 20.04",
"Default": "Ubuntu20.04",
"AllowedValues": [
"Ubuntu20.04",
"Ubuntu18.04",
"Ubuntu16.04",
"Debian9"
]
},
"InstanceType": {
"Type": "String",
"Description": "The instance type of your VPN server. Using t2.micro may qualify for the AWS Free Tier.",
"AllowedValues": [
"t2.micro",
"t3.nano",
"m5.large",
"t3.micro",
"t3.small",
"t2.nano",
"t2.small",
"t3a.nano",
"t3a.micro",
"t3a.small",
"m5a.large",
"t1.micro"
],
"Default": "t2.micro"
}
},
"Outputs": {
"VPNAddress": {
"Description": "This is the public IP of your newly-launched VPN server.",
"Value": {
"Fn::GetAtt": [
"VpnInstance",
"PublicIp"
]
}
},
"VPNUsername": {
"Description": "Your VPN username",
"Value": {
"Ref": "VpnUser"
}
},
"VPNPassword": {
"Description": "Your VPN password",
"Value": {
"Ref": "VpnPassword"
}
},
"VPNKey": {
"Description": "Your VPN IPsec PSK (pre-shared key)",
"Value": {
"Ref": "VpnIpsecPsk"
}
},
"EC2PrivateKeyMaterial": {
"Description": "The content of your private key for accessing the VPN server via SSH. Save it as a file for use when connecting.",
"Value": {
"Fn::GetAtt": [
"KeyPairInfo",
"KeyMaterial"
]
}
},
"NextStep": {
"Description": "Learn how to configure VPN clients.",
"Value": "https://github.com/hwdsl2/setup-ipsec-vpn#next-steps"
}
}
}