Create a gist now

Instantly share code, notes, and snippets.

What would you like to do?
OpenVPN Cloudformation template
{
"Description": "EC2 OpenVPN host for stage-railz",
"Mappings": {
"AmiMap": {
"us-east-1": {
"bastion": "ami-2757f631",
"ecs": "ami-b2df2ca4",
"ubuntu1604": "ami-2757f631"
},
"us-west-2": {
"bastion": "ami-7ac6491a",
"ecs": "ami-022b9262",
"ubuntu1604": "ami-7ac6491a"
}
}
},
"Parameters": {
"AvailabilityZones": {
"Description": "Availability Zones to deploy instances in.",
"Type": "CommaDelimitedList"
},
"DefaultSG": {
"Description": "Top level security group.",
"Type": "AWS::EC2::SecurityGroup::Id"
},
"ImageName": {
"Default": "bastion",
"Description": "The image name to use from the AMIMap (usually found in the config file.)",
"Type": "String"
},
"InstanceType": {
"Default": "m3.medium",
"Description": "EC2 Instance Type",
"Type": "String"
},
"MaxSize": {
"Default": "1",
"Description": "Maximum # of instances.",
"Type": "Number"
},
"MinSize": {
"Default": "1",
"Description": "Minimum # of instances.",
"Type": "Number"
},
"OfficeNetwork": {
"Default": "0.0.0.0/0",
"Description": "CIDR block allowed to connect to bastion hosts.",
"Type": "String"
},
"PrivateSubnets": {
"Description": "Subnets to deploy private instances in.",
"Type": "List<AWS::EC2::Subnet::Id>"
},
"PublicSubnets": {
"Description": "Subnets to deploy public instances in.",
"Type": "List<AWS::EC2::Subnet::Id>"
},
"S3VpnKeysBucketName": {
"Description": "The S3 bucket that contains the keys for the OpenVPN server",
"Type": "String"
},
"SshKeyName": {
"Type": "AWS::EC2::KeyPair::KeyName"
},
"VpcCidr": {
"Description": "The name of this VPC for tagging",
"Type": "String"
},
"VpcId": {
"Description": "Vpc Id",
"Type": "AWS::EC2::VPC::Id"
},
"VpcName": {
"Description": "The name of this VPC for tagging",
"Type": "String"
}
},
"Resources": {
"AllowSSHAnywhere": {
"Properties": {
"FromPort": 22,
"GroupId": {
"Ref": "DefaultSG"
},
"IpProtocol": "tcp",
"SourceSecurityGroupId": {
"Ref": "BastionSG"
},
"ToPort": 22
},
"Type": "AWS::EC2::SecurityGroupIngress"
},
"BastionAccessPolicy": {
"Properties": {
"PolicyDocument": {
"Statement": [
{
"Action": [
"ec2:AssociateAddress",
"ec2:Describe",
"ec2:ModifyInstanceAttribute"
],
"Effect": "Allow",
"Resource": "*"
},
{
"Action": [
"s3:Get*"
],
"Effect": "Allow",
"Resource": [
{
"Fn::Join": [
"",
[
"arn:aws:s3:::",
{
"Ref": "S3VpnKeysBucketName"
}
]
]
},
{
"Fn::Join": [
"",
[
"arn:aws:s3:::",
{
"Ref": "S3VpnKeysBucketName"
},
"/*"
]
]
}
]
}
]
},
"PolicyName": "BastionAccessPolicy",
"Roles": [
{
"Ref": "BastionRole"
}
]
},
"Type": "AWS::IAM::Policy"
},
"BastionAutoscalingGroup": {
"Properties": {
"AvailabilityZones": {
"Ref": "AvailabilityZones"
},
"LaunchConfigurationName": {
"Ref": "BastionLaunchConfig"
},
"MaxSize": {
"Ref": "MaxSize"
},
"MinSize": {
"Ref": "MinSize"
},
"Tags": [
{
"Key": "Name",
"PropagateAtLaunch": true,
"Value": "stage-railz.openvpn"
},
{
"Key": "Application",
"PropagateAtLaunch": true,
"Value": {
"Ref": "AWS::StackId"
}
},
{
"Key": "network",
"PropagateAtLaunch": true,
"Value": "public"
}
],
"VPCZoneIdentifier": {
"Ref": "PublicSubnets"
}
},
"Type": "AWS::AutoScaling::AutoScalingGroup"
},
"BastionInstanceProfile": {
"Properties": {
"Path": "/",
"Roles": [
{
"Ref": "BastionRole"
}
]
},
"Type": "AWS::IAM::InstanceProfile"
},
"BastionLaunchConfig": {
"Properties": {
"AssociatePublicIpAddress": "true",
"IamInstanceProfile": {
"Ref": "BastionInstanceProfile"
},
"ImageId": {
"Fn::FindInMap": [
"AmiMap",
{
"Ref": "AWS::Region"
},
{
"Ref": "ImageName"
}
]
},
"InstanceType": {
"Ref": "InstanceType"
},
"KeyName": {
"Ref": "SshKeyName"
},
"SecurityGroups": [
{
"Ref": "DefaultSG"
},
{
"Ref": "BastionSG"
}
],
"UserData": {
"Fn::Base64": {
"Fn::Join": [
"",
[
"#!/bin/bash -x\nfunction base {\n echo \"=== Boostrap Starting \"\n apt-get update\n apt-get install -y curl python-pip\n DEBIAN_FRONTEND=noninteractive apt-get install -y iptables-persistent\n pip install awscli\n\n # IP Configuration\n aws ec2 modify-instance-attribute --no-source-dest-check --instance-id `curl http://169.254.169.254/latest/meta-data/instance-id` --region ",
{
"Ref": "AWS::Region"
},
"\n\n cat <<EOT > /etc/iptables/rules.v4\n*nat\n:PREROUTING ACCEPT [85:4110]\n:INPUT ACCEPT [84:4046]\n:OUTPUT ACCEPT [70:11051]\n:POSTROUTING ACCEPT [0:0]\n-A POSTROUTING -s 172.20.0.0/16 -o eth0 -j MASQUERADE\n-A POSTROUTING -s 172.29.0.0/20 -o eth0 -j MASQUERADE\nCOMMIT\n# Completed on Tue Mar 28 11:19:00 2017\n# Generated by iptables-save v1.6.0 on Tue Mar 28 11:19:00 2017\n*filter\n:INPUT ACCEPT [2584:919039]\n:FORWARD ACCEPT [0:0]\n:OUTPUT ACCEPT [2388:528346]\n-A FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT\n-A FORWARD -s 172.20.0.0/16 -i eth0 -o eth0 -m conntrack --ctstate NEW -j ACCEPT\n-A FORWARD -s 172.29.0.0/20 -i tun0 -o eth0 -m conntrack --ctstate NEW -j ACCEPT\n-A FORWARD -s 172.29.0.0/20 -d 172.20.0.0/16 -i tun0 -o eth0 -m conntrack --ctstate NEW -j ACCEPT\nCOMMIT\nEOT\n\n iptables-restore < /etc/iptables/rules.v4\n\n echo \"net.ipv4.ip_forward = 1\" >> /etc/sysctl.conf\n sysctl -p\n\n # OpenVPN configuration\n\n mkdir -p /etc/openvpn/keys\n aws s3 cp s3://",
{
"Ref": "S3VpnKeysBucketName"
},
" /etc/openvpn/keys --recursive --include \"ca.crt\" --include \"server.crt\" --include \"server.key\" --include \"dh2048.pem\"\n chmod -R 0600 /etc/openvpn/keys\n aws s3 cp s3://",
{
"Ref": "S3VpnKeysBucketName"
},
"/server.conf /etc/openvpn\n aws s3 cp s3://",
{
"Ref": "S3VpnKeysBucketName"
},
"/ldap.conf /etc/openvpn\n\n cat <<EOT >/etc/pam.d/openvpn\nauth sufficient pam_ldap.so config=/etc/openvpn/ldap.conf\nauth required pam_deny.so\naccount required pam_ldap.so config=/etc/openvpn/ldap.conf\naccount required pam_permit.so\nEOT\n\n DEBIAN_FRONTEND=noninteractive apt-get install -y libpam-ldap\n\n apt-get install -y openvpn \n systemctl start openvpn@server\n\n echo \"=== Boostrap complete \"\n}\n\nbase 2>&1 | tee /tmp/bootstrap.log\n"
]
]
}
}
},
"Type": "AWS::AutoScaling::LaunchConfiguration"
},
"BastionRole": {
"Properties": {
"AssumeRolePolicyDocument": {
"Statement": [
{
"Action": "sts:AssumeRole",
"Effect": "Allow",
"Principal": {
"Service": "ec2.amazonaws.com"
}
}
]
},
"Path": "/"
},
"Type": "AWS::IAM::Role"
},
"BastionSG": {
"Properties": {
"GroupDescription": "BastionSecurityGroup",
"SecurityGroupIngress": [
{
"CidrIp": {
"Ref": "OfficeNetwork"
},
"FromPort": 1194,
"IpProtocol": "udp",
"ToPort": 1194
}
],
"VpcId": {
"Ref": "VpcId"
}
},
"Type": "AWS::EC2::SecurityGroup"
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment