mirror of
https://github.com/trailofbits/algo.git
synced 2025-06-07 15:43:54 +02:00
CF tested and working for EC2 deployment (#431)
* AWS CloudFormation #132 * IPv6 EC2 draft * CF tested and working for EC2 deployment * IPv6 Implementation, EC2, Cloudformation * Fixed ipv6 networking * adding ip6tables rule for DHCP on AWS
This commit is contained in:
parent
0e4aace6b6
commit
76cdc69548
5 changed files with 221 additions and 95 deletions
18
roles/cloud-ec2/tasks/cloudformation.yml
Normal file
18
roles/cloud-ec2/tasks/cloudformation.yml
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
---
|
||||||
|
|
||||||
|
- name: Make a cloudformation template
|
||||||
|
template:
|
||||||
|
src: stack.yml.j2
|
||||||
|
dest: "configs/{{ aws_server_name }}.yml"
|
||||||
|
|
||||||
|
- name: Deploy the template
|
||||||
|
cloudformation:
|
||||||
|
aws_access_key: "{{ aws_access_key | default(lookup('env','AWS_ACCESS_KEY_ID'), true)}}"
|
||||||
|
aws_secret_key: "{{ aws_secret_key | default(lookup('env','AWS_SECRET_ACCESS_KEY'), true)}}"
|
||||||
|
stack_name: "{{ stack_name }}"
|
||||||
|
state: "present"
|
||||||
|
region: "{{ region }}"
|
||||||
|
template: "configs/{{ aws_server_name }}.yml"
|
||||||
|
tags:
|
||||||
|
Environment: Algo
|
||||||
|
register: stack
|
|
@ -1,7 +1,7 @@
|
||||||
- name: Check if the encrypted image already exist
|
- name: Check if the encrypted image already exist
|
||||||
ec2_ami_find:
|
ec2_ami_find:
|
||||||
aws_access_key: "{{ aws_access_key | default(lookup('env','AWS_ACCESS_KEY_ID'))}}"
|
aws_access_key: "{{ aws_access_key | default(lookup('env','AWS_ACCESS_KEY_ID'), true)}}"
|
||||||
aws_secret_key: "{{ aws_secret_key | default(lookup('env','AWS_SECRET_ACCESS_KEY'))}}"
|
aws_secret_key: "{{ aws_secret_key | default(lookup('env','AWS_SECRET_ACCESS_KEY'), true)}}"
|
||||||
owner: self
|
owner: self
|
||||||
sort: creationDate
|
sort: creationDate
|
||||||
sort_order: descending
|
sort_order: descending
|
||||||
|
@ -18,8 +18,8 @@
|
||||||
|
|
||||||
- name: Copy to an encrypted image
|
- name: Copy to an encrypted image
|
||||||
ec2_ami_copy:
|
ec2_ami_copy:
|
||||||
aws_access_key: "{{ aws_access_key | default(lookup('env','AWS_ACCESS_KEY_ID'))}}"
|
aws_access_key: "{{ aws_access_key | default(lookup('env','AWS_ACCESS_KEY_ID'), true)}}"
|
||||||
aws_secret_key: "{{ aws_secret_key | default(lookup('env','AWS_SECRET_ACCESS_KEY'))}}"
|
aws_secret_key: "{{ aws_secret_key | default(lookup('env','AWS_SECRET_ACCESS_KEY'), true)}}"
|
||||||
encrypted: yes
|
encrypted: yes
|
||||||
name: algo
|
name: algo
|
||||||
kms_key_id: "{{ kms_key_id | default(omit) }}"
|
kms_key_id: "{{ kms_key_id | default(omit) }}"
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
- set_fact:
|
- set_fact:
|
||||||
access_key: "{{ aws_access_key | default(lookup('env','AWS_ACCESS_KEY_ID'), true) }}"
|
access_key: "{{ aws_access_key | default(lookup('env','AWS_ACCESS_KEY_ID'), true) }}"
|
||||||
secret_key: "{{ aws_secret_key | default(lookup('env','AWS_SECRET_ACCESS_KEY'), true) }}"
|
secret_key: "{{ aws_secret_key | default(lookup('env','AWS_SECRET_ACCESS_KEY'), true) }}"
|
||||||
|
stack_name: "{{ aws_server_name | replace('.', '-') }}"
|
||||||
|
|
||||||
- name: Locate official Ubuntu 16.04 AMI for region
|
- name: Locate official Ubuntu 16.04 AMI for region
|
||||||
ec2_ami_find:
|
ec2_ami_find:
|
||||||
|
@ -20,107 +21,20 @@
|
||||||
- include: encrypt_image.yml
|
- include: encrypt_image.yml
|
||||||
tags: [encrypted]
|
tags: [encrypted]
|
||||||
|
|
||||||
- name: Add ssh public key
|
- include: cloudformation.yml
|
||||||
ec2_key:
|
|
||||||
aws_access_key: "{{ access_key }}"
|
|
||||||
aws_secret_key: "{{ secret_key }}"
|
|
||||||
name: VPNKEY
|
|
||||||
region: "{{ region }}"
|
|
||||||
key_material: "{{ item }}"
|
|
||||||
with_file: "{{ SSH_keys.public }}"
|
|
||||||
register: keypair
|
|
||||||
|
|
||||||
- name: Configure EC2 virtual private clouds
|
|
||||||
ec2_vpc:
|
|
||||||
aws_access_key: "{{ access_key }}"
|
|
||||||
aws_secret_key: "{{ secret_key }}"
|
|
||||||
state: present
|
|
||||||
resource_tags: { "Environment":"Algo" }
|
|
||||||
region: "{{ region }}"
|
|
||||||
cidr_block: "{{ ec2_vpc_nets.cidr_block }}"
|
|
||||||
internet_gateway: yes
|
|
||||||
subnets:
|
|
||||||
- cidr: "{{ ec2_vpc_nets.subnet_cidr }}"
|
|
||||||
resource_tags: { "Environment":"Algo" }
|
|
||||||
register: vpc
|
|
||||||
|
|
||||||
- name: Set up Public Subnets Route Table
|
|
||||||
ec2_vpc_route_table:
|
|
||||||
aws_access_key: "{{ access_key }}"
|
|
||||||
aws_secret_key: "{{ secret_key }}"
|
|
||||||
vpc_id: "{{ vpc.vpc_id }}"
|
|
||||||
region: "{{ region }}"
|
|
||||||
state: present
|
|
||||||
tags:
|
|
||||||
Environment: Algo
|
|
||||||
subnets:
|
|
||||||
- "{{ ec2_vpc_nets.subnet_cidr }}"
|
|
||||||
routes:
|
|
||||||
- dest: 0.0.0.0/0
|
|
||||||
gateway_id: "{{ vpc.igw_id }}"
|
|
||||||
register: public_rt
|
|
||||||
|
|
||||||
- name: Configure EC2 security group
|
|
||||||
ec2_group:
|
|
||||||
aws_access_key: "{{ access_key }}"
|
|
||||||
aws_secret_key: "{{ secret_key }}"
|
|
||||||
name: vpn-secgroup
|
|
||||||
description: Security group for VPN servers
|
|
||||||
region: "{{ region }}"
|
|
||||||
vpc_id: "{{ vpc.vpc_id }}"
|
|
||||||
rules:
|
|
||||||
- proto: udp
|
|
||||||
from_port: 4500
|
|
||||||
to_port: 4500
|
|
||||||
cidr_ip: 0.0.0.0/0
|
|
||||||
- proto: udp
|
|
||||||
from_port: 500
|
|
||||||
to_port: 500
|
|
||||||
cidr_ip: 0.0.0.0/0
|
|
||||||
- proto: tcp
|
|
||||||
from_port: 22
|
|
||||||
to_port: 22
|
|
||||||
cidr_ip: 0.0.0.0/0
|
|
||||||
rules_egress:
|
|
||||||
- proto: all
|
|
||||||
from_port: 0-65535
|
|
||||||
to_port: 0-65535
|
|
||||||
cidr_ip: 0.0.0.0/0
|
|
||||||
|
|
||||||
- name: Launch instance
|
|
||||||
ec2:
|
|
||||||
aws_access_key: "{{ access_key }}"
|
|
||||||
aws_secret_key: "{{ secret_key }}"
|
|
||||||
keypair: "VPNKEY"
|
|
||||||
vpc_subnet_id: "{{ vpc.subnets[0].id }}"
|
|
||||||
group: vpn-secgroup
|
|
||||||
instance_type: "{{ cloud_providers.ec2.size }}"
|
|
||||||
image: "{{ ami_image }}"
|
|
||||||
wait: true
|
|
||||||
region: "{{ region }}"
|
|
||||||
instance_tags:
|
|
||||||
Name: "{{ aws_server_name }}"
|
|
||||||
Environment: Algo
|
|
||||||
exact_count: 1
|
|
||||||
count_tag:
|
|
||||||
Name: "{{ aws_server_name }}"
|
|
||||||
assign_public_ip: yes
|
|
||||||
instance_initiated_shutdown_behavior: terminate
|
|
||||||
register: ec2
|
|
||||||
|
|
||||||
- name: Add new instance to host group
|
- name: Add new instance to host group
|
||||||
add_host:
|
add_host:
|
||||||
hostname: "{{ item.public_ip }}"
|
hostname: "{{ stack.stack_outputs.PublicIP }}"
|
||||||
groupname: vpn-host
|
groupname: vpn-host
|
||||||
ansible_ssh_user: ubuntu
|
ansible_ssh_user: ubuntu
|
||||||
ansible_python_interpreter: "/usr/bin/python2.7"
|
ansible_python_interpreter: "/usr/bin/python2.7"
|
||||||
ansible_ssh_private_key_file: "{{ SSH_keys.private }}"
|
ansible_ssh_private_key_file: "{{ SSH_keys.private }}"
|
||||||
cloud_provider: ec2
|
cloud_provider: ec2
|
||||||
ipv6_support: no
|
ipv6_support: yes
|
||||||
with_items: "{{ ec2.tagged_instances }}"
|
|
||||||
|
|
||||||
- set_fact:
|
- set_fact:
|
||||||
cloud_instance_ip: "{{ ec2.tagged_instances[0].public_ip }}"
|
cloud_instance_ip: "{{ stack.stack_outputs.PublicIP }}"
|
||||||
|
|
||||||
- name: Get EC2 instances
|
- name: Get EC2 instances
|
||||||
ec2_remote_facts:
|
ec2_remote_facts:
|
||||||
|
|
192
roles/cloud-ec2/templates/stack.yml.j2
Normal file
192
roles/cloud-ec2/templates/stack.yml.j2
Normal file
|
@ -0,0 +1,192 @@
|
||||||
|
---
|
||||||
|
|
||||||
|
AWSTemplateFormatVersion: '2010-09-09'
|
||||||
|
Description: 'Algo VPN stack'
|
||||||
|
Resources:
|
||||||
|
|
||||||
|
VPC:
|
||||||
|
Type: AWS::EC2::VPC
|
||||||
|
Properties:
|
||||||
|
CidrBlock: {{ ec2_vpc_nets.cidr_block }}
|
||||||
|
EnableDnsSupport: true
|
||||||
|
EnableDnsHostnames: true
|
||||||
|
InstanceTenancy: default
|
||||||
|
Tags:
|
||||||
|
- Key: Name
|
||||||
|
Value: Algo
|
||||||
|
- Key: Environment
|
||||||
|
Value: Algo
|
||||||
|
|
||||||
|
VPCIPv6:
|
||||||
|
Type: AWS::EC2::VPCCidrBlock
|
||||||
|
Properties:
|
||||||
|
AmazonProvidedIpv6CidrBlock: true
|
||||||
|
VpcId: !Ref VPC
|
||||||
|
|
||||||
|
InternetGateway:
|
||||||
|
Type: AWS::EC2::InternetGateway
|
||||||
|
Properties:
|
||||||
|
Tags:
|
||||||
|
- Key: Environment
|
||||||
|
Value: Algo
|
||||||
|
- Key: Name
|
||||||
|
Value: Algo
|
||||||
|
|
||||||
|
Subnet:
|
||||||
|
Type: AWS::EC2::Subnet
|
||||||
|
Properties:
|
||||||
|
CidrBlock: {{ ec2_vpc_nets.subnet_cidr }}
|
||||||
|
MapPublicIpOnLaunch: true
|
||||||
|
Tags:
|
||||||
|
- Key: Environment
|
||||||
|
Value: Algo
|
||||||
|
- Key: Name
|
||||||
|
Value: Algo
|
||||||
|
VpcId: !Ref VPC
|
||||||
|
|
||||||
|
VPCGatewayAttachment:
|
||||||
|
Type: AWS::EC2::VPCGatewayAttachment
|
||||||
|
Properties:
|
||||||
|
VpcId: !Ref VPC
|
||||||
|
InternetGatewayId: !Ref InternetGateway
|
||||||
|
|
||||||
|
RouteTable:
|
||||||
|
Type: AWS::EC2::RouteTable
|
||||||
|
Properties:
|
||||||
|
VpcId: !Ref VPC
|
||||||
|
Tags:
|
||||||
|
- Key: Environment
|
||||||
|
Value: Algo
|
||||||
|
- Key: Name
|
||||||
|
Value: Algo
|
||||||
|
|
||||||
|
Route:
|
||||||
|
Type: AWS::EC2::Route
|
||||||
|
DependsOn:
|
||||||
|
- InternetGateway
|
||||||
|
- RouteTable
|
||||||
|
- VPCGatewayAttachment
|
||||||
|
Properties:
|
||||||
|
RouteTableId: !Ref RouteTable
|
||||||
|
DestinationCidrBlock: 0.0.0.0/0
|
||||||
|
GatewayId: !Ref InternetGateway
|
||||||
|
|
||||||
|
RouteIPv6:
|
||||||
|
Type: AWS::EC2::Route
|
||||||
|
DependsOn:
|
||||||
|
- InternetGateway
|
||||||
|
- RouteTable
|
||||||
|
- VPCGatewayAttachment
|
||||||
|
Properties:
|
||||||
|
RouteTableId: !Ref RouteTable
|
||||||
|
DestinationIpv6CidrBlock: "::/0"
|
||||||
|
GatewayId: !Ref InternetGateway
|
||||||
|
|
||||||
|
SubnetIPv6:
|
||||||
|
Type: AWS::EC2::SubnetCidrBlock
|
||||||
|
DependsOn:
|
||||||
|
- RouteIPv6
|
||||||
|
- VPC
|
||||||
|
- VPCIPv6
|
||||||
|
Properties:
|
||||||
|
Ipv6CidrBlock:
|
||||||
|
"Fn::Join":
|
||||||
|
- ""
|
||||||
|
- - !Select [0, !Split [ "::", !Select [0, !GetAtt VPC.Ipv6CidrBlocks] ]]
|
||||||
|
- "::dead:beef/64"
|
||||||
|
SubnetId: !Ref Subnet
|
||||||
|
|
||||||
|
RouteSubnet:
|
||||||
|
Type: "AWS::EC2::SubnetRouteTableAssociation"
|
||||||
|
DependsOn:
|
||||||
|
- RouteTable
|
||||||
|
- Subnet
|
||||||
|
- Route
|
||||||
|
Properties:
|
||||||
|
RouteTableId: !Ref RouteTable
|
||||||
|
SubnetId: !Ref Subnet
|
||||||
|
|
||||||
|
InstanceSecurityGroup:
|
||||||
|
Type: AWS::EC2::SecurityGroup
|
||||||
|
DependsOn:
|
||||||
|
- Subnet
|
||||||
|
Properties:
|
||||||
|
VpcId: !Ref VPC
|
||||||
|
GroupDescription: Enable SSH and IPsec
|
||||||
|
SecurityGroupIngress:
|
||||||
|
- 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'
|
||||||
|
CidrIp: 0.0.0.0/0
|
||||||
|
Tags:
|
||||||
|
- Key: Name
|
||||||
|
Value: Algo
|
||||||
|
- Key: Environment
|
||||||
|
Value: Algo
|
||||||
|
|
||||||
|
EC2Instance:
|
||||||
|
Type: AWS::EC2::Instance
|
||||||
|
DependsOn:
|
||||||
|
- SubnetIPv6
|
||||||
|
- Subnet
|
||||||
|
- InstanceSecurityGroup
|
||||||
|
Metadata:
|
||||||
|
AWS::CloudFormation::Init:
|
||||||
|
config:
|
||||||
|
users:
|
||||||
|
ubuntu:
|
||||||
|
groups:
|
||||||
|
- "sudo"
|
||||||
|
homeDir: "/home/ubuntu/"
|
||||||
|
files:
|
||||||
|
/home/ubuntu/.ssh/authorized_keys:
|
||||||
|
content: {{ lookup('file', SSH_keys.public) }}
|
||||||
|
mode: "000644"
|
||||||
|
owner: "ubuntu"
|
||||||
|
group: "ubuntu"
|
||||||
|
Properties:
|
||||||
|
InstanceType: {{ cloud_providers.ec2.size }}
|
||||||
|
InstanceInitiatedShutdownBehavior: terminate
|
||||||
|
SecurityGroupIds:
|
||||||
|
- Ref: InstanceSecurityGroup
|
||||||
|
ImageId: {{ ami_image }}
|
||||||
|
SubnetId: !Ref Subnet
|
||||||
|
Ipv6AddressCount: 1
|
||||||
|
UserData:
|
||||||
|
"Fn::Base64":
|
||||||
|
!Sub |
|
||||||
|
#!/bin/bash -xe
|
||||||
|
# http://docs.aws.amazon.com/AmazonVPC/latest/UserGuide/vpc-migrate-ipv6.html
|
||||||
|
# https://bugs.launchpad.net/ubuntu/+source/ifupdown/+bug/1013597
|
||||||
|
cat <<EOF > /etc/network/interfaces.d/60-default-with-ipv6.cfg
|
||||||
|
iface eth0 inet6 dhcp
|
||||||
|
up sysctl net.ipv6.conf.\$IFACE.accept_ra=2
|
||||||
|
pre-down ip link set dev \$IFACE up
|
||||||
|
EOF
|
||||||
|
ifdown eth0; ifup eth0
|
||||||
|
dhclient -6
|
||||||
|
apt-get update
|
||||||
|
apt-get -y install python-setuptools
|
||||||
|
easy_install https://s3.amazonaws.com/cloudformation-examples/aws-cfn-bootstrap-latest.tar.gz
|
||||||
|
cfn-init -v --stack {{ stack_name }} --resource EC2Instance --region {{ region }}
|
||||||
|
cfn-signal -e $? --stack {{ stack_name }} --resource EC2Instance --region {{ region }}
|
||||||
|
Tags:
|
||||||
|
- Key: Name
|
||||||
|
Value: Algo
|
||||||
|
- Key: Environment
|
||||||
|
Value: Algo
|
||||||
|
|
||||||
|
Outputs:
|
||||||
|
PublicIP:
|
||||||
|
Value:
|
||||||
|
Fn::GetAtt:
|
||||||
|
- EC2Instance
|
||||||
|
- PublicIp
|
|
@ -31,6 +31,8 @@ COMMIT
|
||||||
-A INPUT -p icmpv6 --icmpv6-type neighbor-solicitation -m hl --hl-eq 255 -j ACCEPT
|
-A INPUT -p icmpv6 --icmpv6-type neighbor-solicitation -m hl --hl-eq 255 -j ACCEPT
|
||||||
-A INPUT -p icmpv6 --icmpv6-type neighbor-advertisement -m hl --hl-eq 255 -j ACCEPT
|
-A INPUT -p icmpv6 --icmpv6-type neighbor-advertisement -m hl --hl-eq 255 -j ACCEPT
|
||||||
-A INPUT -p icmpv6 --icmpv6-type redirect -m hl --hl-eq 255 -j ACCEPT
|
-A INPUT -p icmpv6 --icmpv6-type redirect -m hl --hl-eq 255 -j ACCEPT
|
||||||
|
# DHCP in AWS
|
||||||
|
-A INPUT -m state --state NEW -m udp -p udp --dport 546 -d fe80::/64 -j ACCEPT
|
||||||
# TODO:
|
# TODO:
|
||||||
# The IP of the resolver should be bound to a DUMMY interface.
|
# The IP of the resolver should be bound to a DUMMY interface.
|
||||||
# DUMMY interfaces are the proper way to install IPs without assigning them any
|
# DUMMY interfaces are the proper way to install IPs without assigning them any
|
||||||
|
|
Loading…
Add table
Reference in a new issue