582 lines
22 KiB
JSON
582 lines
22 KiB
JSON
|
{
|
||
|
"AWSTemplateFormatVersion": "2010-09-09",
|
||
|
"Mappings": {
|
||
|
"OS": {
|
||
|
"Ubuntu2004": {
|
||
|
"HelperInstallationCommands": "export DEBIAN_FRONTEND=noninteractive\napt-get -yq update\napt-get -yq install python3-pip\npython3 -m pip install https://s3.amazonaws.com/cloudformation-examples/aws-cfn-bootstrap-py3-latest.tar.gz\n"
|
||
|
},
|
||
|
"Ubuntu2204": {
|
||
|
"HelperInstallationCommands": "export DEBIAN_FRONTEND=noninteractive\napt-get -yq update\napt-get -yq install python3-pip\npython3 -m pip install https://s3.amazonaws.com/cloudformation-examples/aws-cfn-bootstrap-py3-latest.tar.gz\n"
|
||
|
},
|
||
|
"Debian10": {
|
||
|
"HelperInstallationCommands": "export DEBIAN_FRONTEND=noninteractive\napt-get -yq update\napt-get -yq install python3-pip\npython3 -m pip install https://s3.amazonaws.com/cloudformation-examples/aws-cfn-bootstrap-py3-latest.tar.gz\n"
|
||
|
},
|
||
|
"Debian11": {
|
||
|
"HelperInstallationCommands": "export DEBIAN_FRONTEND=noninteractive\napt-get -yq update\napt-get -yq install python3-pip\npython3 -m pip install https://s3.amazonaws.com/cloudformation-examples/aws-cfn-bootstrap-py3-latest.tar.gz\n"
|
||
|
},
|
||
|
"Debian12": {
|
||
|
"HelperInstallationCommands": "export DEBIAN_FRONTEND=noninteractive\nrm -rf /usr/lib/python3.*/EXTERNALLY-MANAGED\napt-get -yq update\napt-get -yq install python3-pip\npython3 -m pip install https://s3.amazonaws.com/cloudformation-examples/aws-cfn-bootstrap-py3-latest.tar.gz\n"
|
||
|
},
|
||
|
"CentOS7": {
|
||
|
"HelperInstallationCommands": "yum -y install python3 wget\npython3 -m pip install https://s3.amazonaws.com/cloudformation-examples/aws-cfn-bootstrap-py3-latest.tar.gz\n"
|
||
|
},
|
||
|
"AmazonLinux2": {
|
||
|
"HelperInstallationCommands": "export PATH=\"$PATH:/opt/aws/bin\"\n"
|
||
|
}
|
||
|
}
|
||
|
},
|
||
|
"Metadata": {},
|
||
|
"Resources": {
|
||
|
"VpnVpc": {
|
||
|
"Type": "AWS::EC2::VPC",
|
||
|
"Properties": {
|
||
|
"CidrBlock": "10.0.0.0/24"
|
||
|
},
|
||
|
"Metadata": {}
|
||
|
},
|
||
|
"VpnSubnet": {
|
||
|
"Type": "AWS::EC2::Subnet",
|
||
|
"Properties": {
|
||
|
"VpcId": {
|
||
|
"Ref": "VpnVpc"
|
||
|
},
|
||
|
"CidrBlock": "10.0.0.0/24",
|
||
|
"MapPublicIpOnLaunch": true,
|
||
|
"AvailabilityZone": {
|
||
|
"Fn::Select": [
|
||
|
"0",
|
||
|
{
|
||
|
"Fn::GetAZs": ""
|
||
|
}
|
||
|
]
|
||
|
}
|
||
|
},
|
||
|
"Metadata": {},
|
||
|
"DependsOn": [
|
||
|
"VpnVpc",
|
||
|
"VpcInternetGateway"
|
||
|
]
|
||
|
},
|
||
|
"VpnRouteTable": {
|
||
|
"Type": "AWS::EC2::RouteTable",
|
||
|
"Properties": {
|
||
|
"VpcId": {
|
||
|
"Ref": "VpnVpc"
|
||
|
}
|
||
|
},
|
||
|
"Metadata": {},
|
||
|
"DependsOn": [
|
||
|
"VpnSubnet"
|
||
|
]
|
||
|
},
|
||
|
"PublicInternetRoute": {
|
||
|
"Type": "AWS::EC2::Route",
|
||
|
"Properties": {
|
||
|
"DestinationCidrBlock": "0.0.0.0/0",
|
||
|
"RouteTableId": {
|
||
|
"Ref": "VpnRouteTable"
|
||
|
},
|
||
|
"GatewayId": {
|
||
|
"Ref": "VpcInternetGateway"
|
||
|
}
|
||
|
},
|
||
|
"Metadata": {},
|
||
|
"DependsOn": [
|
||
|
"VpnRouteTable",
|
||
|
"VpcInternetGateway",
|
||
|
"InternetGatewayAttachment"
|
||
|
]
|
||
|
},
|
||
|
"VpnInstance": {
|
||
|
"Type": "AWS::EC2::Instance",
|
||
|
"CreationPolicy": {
|
||
|
"ResourceSignal": {
|
||
|
"Timeout": "PT15M"
|
||
|
}
|
||
|
},
|
||
|
"Properties": {
|
||
|
"UserData": {
|
||
|
"Fn::Base64": {
|
||
|
"Fn::Join": [
|
||
|
"",
|
||
|
[
|
||
|
"#!/bin/bash -xe\n",
|
||
|
"trap 'cfn-signal -e 1 ",
|
||
|
" --stack ",
|
||
|
{
|
||
|
"Ref": "AWS::StackName"
|
||
|
},
|
||
|
" --resource VpnInstance ",
|
||
|
" --region ",
|
||
|
{
|
||
|
"Ref": "AWS::Region"
|
||
|
},
|
||
|
"' ERR\n",
|
||
|
"sleep 60\n",
|
||
|
{
|
||
|
"Fn::FindInMap": [
|
||
|
"OS",
|
||
|
{
|
||
|
"Ref": "OS"
|
||
|
},
|
||
|
"HelperInstallationCommands"
|
||
|
]
|
||
|
},
|
||
|
"export VPN_IPSEC_PSK='",
|
||
|
{
|
||
|
"Ref": "VpnIpsecPsk"
|
||
|
},
|
||
|
"'\n",
|
||
|
"export VPN_USER='",
|
||
|
{
|
||
|
"Ref": "VpnUser"
|
||
|
},
|
||
|
"'\n",
|
||
|
"export VPN_PASSWORD='",
|
||
|
{
|
||
|
"Ref": "VpnPassword"
|
||
|
},
|
||
|
"'\n",
|
||
|
"wget -t 3 -T 30 -nv -O vpn.sh https://github.com/hwdsl2/setup-ipsec-vpn/raw/master/vpnsetup.sh\n",
|
||
|
"sh vpn.sh\n",
|
||
|
"cfn-signal -e 0 ",
|
||
|
" --stack ",
|
||
|
{
|
||
|
"Ref": "AWS::StackName"
|
||
|
},
|
||
|
" --resource VpnInstance ",
|
||
|
" --region ",
|
||
|
{
|
||
|
"Ref": "AWS::Region"
|
||
|
},
|
||
|
"\n"
|
||
|
]
|
||
|
]
|
||
|
}
|
||
|
},
|
||
|
"SecurityGroupIds": [
|
||
|
{
|
||
|
"Fn::GetAtt": [
|
||
|
"VpnSecurityGroup",
|
||
|
"GroupId"
|
||
|
]
|
||
|
}
|
||
|
],
|
||
|
"SubnetId": {
|
||
|
"Ref": "VpnSubnet"
|
||
|
},
|
||
|
"AvailabilityZone": {
|
||
|
"Fn::Select": [
|
||
|
"0",
|
||
|
{
|
||
|
"Fn::GetAZs": ""
|
||
|
}
|
||
|
]
|
||
|
},
|
||
|
"InstanceType": {
|
||
|
"Ref": "InstanceType"
|
||
|
},
|
||
|
"KeyName": {
|
||
|
"Fn::GetAtt": [
|
||
|
"KeyPairInfo",
|
||
|
"KeyName"
|
||
|
]
|
||
|
},
|
||
|
"ImageId": {
|
||
|
"Fn::GetAtt": [
|
||
|
"AMIInfo",
|
||
|
"AMIId"
|
||
|
]
|
||
|
}
|
||
|
},
|
||
|
"Metadata": {},
|
||
|
"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": {}
|
||
|
},
|
||
|
"VpnServerVolume": {
|
||
|
"Type": "AWS::EC2::Volume",
|
||
|
"Properties": {
|
||
|
"AvailabilityZone": {
|
||
|
"Fn::Select": [
|
||
|
"0",
|
||
|
{
|
||
|
"Fn::GetAZs": ""
|
||
|
}
|
||
|
]
|
||
|
},
|
||
|
"Size": 8
|
||
|
},
|
||
|
"Metadata": {}
|
||
|
},
|
||
|
"VpcInternetGateway": {
|
||
|
"Type": "AWS::EC2::InternetGateway",
|
||
|
"Properties": {},
|
||
|
"Metadata": {},
|
||
|
"DependsOn": [
|
||
|
"VpnVpc"
|
||
|
]
|
||
|
},
|
||
|
"EC2SRTA4VJU5": {
|
||
|
"Type": "AWS::EC2::SubnetRouteTableAssociation",
|
||
|
"Properties": {
|
||
|
"RouteTableId": {
|
||
|
"Ref": "VpnRouteTable"
|
||
|
},
|
||
|
"SubnetId": {
|
||
|
"Ref": "VpnSubnet"
|
||
|
}
|
||
|
},
|
||
|
"Metadata": {}
|
||
|
},
|
||
|
"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 = 'setup-ipsec-vpn-' + ''.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": {},
|
||
|
"DependsOn": [
|
||
|
"LambdaExecutionRole"
|
||
|
]
|
||
|
},
|
||
|
"AMIInfo": {
|
||
|
"Type": "Custom::AMIInfo",
|
||
|
"Properties": {
|
||
|
"Region": {
|
||
|
"Ref": "AWS::Region"
|
||
|
},
|
||
|
"ServiceToken": {
|
||
|
"Fn::GetAtt": [
|
||
|
"AMIInfoFunction",
|
||
|
"Arn"
|
||
|
]
|
||
|
},
|
||
|
"Distribution": {
|
||
|
"Ref": "OS"
|
||
|
}
|
||
|
},
|
||
|
"Metadata": {},
|
||
|
"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",
|
||
|
"'''",
|
||
|
"This python script should be embeded into its designated cloudformation template.",
|
||
|
"Its function is to sort out the correct AMI image to use for each of the distribution options available.",
|
||
|
"'''",
|
||
|
"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)",
|
||
|
" AMIName = {",
|
||
|
" 'Ubuntu2004': 'ubuntu/images/hvm-ssd/ubuntu-focal-20.04-amd64-server-*',",
|
||
|
" 'Ubuntu2204': 'ubuntu/images/hvm-ssd/ubuntu-jammy-22.04-amd64-server-*',",
|
||
|
" 'Debian10': 'debian-10-amd64-*',",
|
||
|
" 'Debian11': 'debian-11-amd64-*',",
|
||
|
" 'Debian12': 'debian-12-amd64-*',",
|
||
|
" 'CentOS7': 'CentOS Linux 7 x86_64 - *',",
|
||
|
" 'AmazonLinux2': 'amzn2-ami-hvm-*.*-x86_64-gp2',",
|
||
|
" }[distribution]",
|
||
|
" response = ec2.describe_images(Filters=[{'Name':'name', 'Values':[AMIName]}], Owners=['099720109477', '136693071363', '125523088429', 'amazon'])",
|
||
|
" 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": {},
|
||
|
"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": {}
|
||
|
},
|
||
|
"KeyPairInfo": {
|
||
|
"Type": "Custom::KeyPairInfo",
|
||
|
"Properties": {
|
||
|
"Region": {
|
||
|
"Ref": "AWS::Region"
|
||
|
},
|
||
|
"ServiceToken": {
|
||
|
"Fn::GetAtt": [
|
||
|
"KeyPairCreation",
|
||
|
"Arn"
|
||
|
]
|
||
|
}
|
||
|
},
|
||
|
"Metadata": {},
|
||
|
"DependsOn": [
|
||
|
"KeyPairCreation"
|
||
|
]
|
||
|
},
|
||
|
"InternetGatewayAttachment": {
|
||
|
"Type": "AWS::EC2::VPCGatewayAttachment",
|
||
|
"Properties": {
|
||
|
"InternetGatewayId": {
|
||
|
"Ref": "VpcInternetGateway"
|
||
|
},
|
||
|
"VpcId": {
|
||
|
"Ref": "VpnVpc"
|
||
|
}
|
||
|
},
|
||
|
"Metadata": {}
|
||
|
},
|
||
|
"EC2VA41EUF": {
|
||
|
"Type": "AWS::EC2::VolumeAttachment",
|
||
|
"Properties": {
|
||
|
"Device": "/dev/sdh",
|
||
|
"VolumeId": {
|
||
|
"Ref": "VpnServerVolume"
|
||
|
},
|
||
|
"InstanceId": {
|
||
|
"Ref": "VpnInstance"
|
||
|
}
|
||
|
},
|
||
|
"Metadata": {}
|
||
|
}
|
||
|
},
|
||
|
"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 22.04",
|
||
|
"Default": "Ubuntu2204",
|
||
|
"AllowedValues": [
|
||
|
"Ubuntu2004",
|
||
|
"Ubuntu2204",
|
||
|
"Debian10",
|
||
|
"Debian11",
|
||
|
"Debian12",
|
||
|
"CentOS7",
|
||
|
"AmazonLinux2"
|
||
|
]
|
||
|
},
|
||
|
"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"
|
||
|
},
|
||
|
"WarningForDebianUsers": {
|
||
|
"Description": "Please be noted that due to Debian images on AWS EC2 using cloud kernels, you are unable to use IPSec/L2TP mode if your server is running Debian. For more information, please refer to the link to the left.",
|
||
|
"Value": "https://github.com/hwdsl2/setup-ipsec-vpn/blob/master/docs/clients.md#debian-kernel"
|
||
|
}
|
||
|
}
|
||
|
}
|