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