├── aws ├── init.sls ├── ec2.sls ├── secgroup.sls ├── map.jinja ├── macros.jinja └── vpc.sls ├── FORMULA ├── CHANGELOG.rst ├── LICENSING ├── pillar.example └── README.rst /aws/init.sls: -------------------------------------------------------------------------------- 1 | include: 2 | - .vpc 3 | - .secgroup 4 | - .ec2 5 | 6 | -------------------------------------------------------------------------------- /FORMULA: -------------------------------------------------------------------------------- 1 | name: aws 2 | os: RedHat, Debian, Ubuntu, Suse, FreeBSD, Gentoo 3 | os_family: RedHat, Debian, Suse, FreeBSD, Gentoo 4 | version: 201701 5 | release: 1 6 | minimum_version: 2016.11 7 | summary: Formula for creating AWS datacenters 8 | description: Formula for creating multiple VPC AWS configurations without using CloudFormation 9 | -------------------------------------------------------------------------------- /aws/ec2.sls: -------------------------------------------------------------------------------- 1 | {% from "aws/map.jinja" import aws_data with context %} 2 | 3 | # Loop through regions 4 | {%- for region_name, region_data in aws_data.get('region', {}).items() %} 5 | {%- set profile = region_data.get('profile') %} 6 | 7 | # Create Key pairs 8 | {%- for key_name, key_value in region_data.get('key_pairs', {} ).items() %} 9 | aws_region_{{ region_name }}_default_keypair_{{ key_name }}: 10 | boto_ec2.key_present: 11 | - name: {{ key_name }} 12 | - upload_public: '{{ key_value }}' 13 | - profile: {{ profile }} 14 | {%- endfor %} 15 | 16 | {% endfor %} 17 | -------------------------------------------------------------------------------- /CHANGELOG.rst: -------------------------------------------------------------------------------- 1 | ============= 2 | aws-formula 3 | ============= 4 | 5 | 6 | 0.1.3 7 | ----- 8 | 9 | - Limit states to a single VPC using command line pillar 10 | 11 | 0.1.2 12 | ----- 13 | 14 | - Remove un-used include from init.sls 15 | 16 | 0.1.1 17 | ----- 18 | 19 | - Fixed the NAT Gateway so it no longer requires a workaround 20 | - Object names from pillar have the vpc name appended for uniqueness 21 | - "Object names must be unique" workaround added 22 | - "Security Group rule creation failure" workaround added 23 | 24 | 0.1.0 25 | ----- 26 | 27 | - Create a functional VPC with workarounds for VPN and NAT Gateways 28 | -------------------------------------------------------------------------------- /LICENSING: -------------------------------------------------------------------------------- 1 | 2 | Copyright (c) 2013-2015 Salt Stack Formulas 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | 16 | -------------------------------------------------------------------------------- /aws/secgroup.sls: -------------------------------------------------------------------------------- 1 | {%- from "aws/macros.jinja" import secgroup_rules with context %} 2 | {% from "aws/map.jinja" import aws_data with context %} 3 | 4 | # Loop through regions 5 | {%- for region_name, region_data in aws_data.get('region', {}).items() %} 6 | {%- set profile = region_data.get('profile') %} 7 | 8 | # Loop through VPCs 9 | {%- for vpc_name, vpc_data in region_data.get('vpc').items() %} 10 | 11 | # Create Security Groups 12 | {%- for sg_name, sg_data in vpc_data.get('security_groups', {}).items() %} 13 | aws_vpc_{{ vpc_name }}_create_security_group_{{ sg_name }}: 14 | boto_secgroup.present: 15 | - name: {{ sg_name }}-{{ vpc_name }} 16 | - description: {{ sg_data.description }} 17 | - vpc_name: {{ vpc_name }} 18 | - profile: {{ profile }} 19 | {{ secgroup_rules('rules', sg_data.get('rules', {}), vpc_name ) }} 20 | {{ secgroup_rules('rules_egress', sg_data.get('rules_egress', {}), vpc_name ) }} 21 | {% endfor %} 22 | 23 | {% endfor %} 24 | {% endfor %} 25 | -------------------------------------------------------------------------------- /aws/map.jinja: -------------------------------------------------------------------------------- 1 | # if command line vpc provided, only include pillar that matches 2 | {% set aws_data = {} %} 3 | {% set aws_pillar = salt['pillar.get']('aws', {}) %} 4 | {% set vpc_filter = salt['pillar.get']('vpc', false ) %} 5 | 6 | # Create subset of pillar if a VPC is specified on command line 7 | {% if vpc_filter %} 8 | # Loop through regions 9 | {%- for region_name, region_data in aws_pillar.get('region', {}).items() %} 10 | # Loop through VPCs 11 | {%- for vpc_name, vpc_data in region_data.get('vpc').items() %} 12 | {% if vpc_name|string() == vpc_filter|string() %} 13 | # Include region of matching VPC 14 | {% do aws_data.update( { 'region': { region_name: region_data } } ) %} 15 | # Clear VPCs and add just matching one 16 | {% do aws_data['region'][region_name].update( { "vpc": {} }) %} 17 | {% do aws_data['region'][region_name]['vpc'].update( { vpc_name: vpc_data } ) %} 18 | {% endif %} 19 | {% endfor %} 20 | {% endfor %} 21 | {% else %} 22 | {% set aws_data = aws_pillar %} 23 | {% endif %} 24 | -------------------------------------------------------------------------------- /aws/macros.jinja: -------------------------------------------------------------------------------- 1 | # Optionally create ingress and egress security group rules 2 | {%- macro secgroup_rules(type, rules, vpc_name ) -%} 3 | {%- if rules %} 4 | - {{ type }}: 5 | {%- for rule_name, rule_data in rules.items() %} 6 | - ip_protocol: {{ rule_data.ip_protocol }} 7 | from_port: {{ rule_data.get('from_port', rule_data.get('port') ) }} 8 | to_port: {{ rule_data.get('to_port' , rule_data.get('port') ) }} 9 | {%- if rule_data.get('cidr_ip', False) %} 10 | {%- if rule_data.cidr_ip is not string %} 11 | cidr_ip: 12 | {%- for ip in rule_data.cidr_ip %} 13 | - {{ ip }} 14 | {%- endfor %} 15 | {%- else %} 16 | cidr_ip: {{ rule_data.cidr_ip }} 17 | {%- endif %} 18 | {%- endif %} 19 | {%- if rule_data.get('source_group_name', False) %} 20 | {%- if rule_data.source_group_name is not string %} 21 | source_group_name: 22 | {%- for sgn in rule_data.source_group_name %} 23 | - {{ sgn }}-{{ vpc_name }} 24 | {%- endfor %} 25 | {%- else %} 26 | source_group_name: {{ rule_data.source_group_name }}-{{ vpc_name }} 27 | {%- endif %} 28 | {%- endif %} 29 | {%- endfor %} 30 | {%- endif %} 31 | {%- endmacro %} 32 | -------------------------------------------------------------------------------- /aws/vpc.sls: -------------------------------------------------------------------------------- 1 | # Create list of route table options that need the value to have a -vpcname suffix 2 | {% set rt_append_list = [ 'internet_gateway_name', 'nat_gateway_subnet_name'] %} 3 | 4 | {% from "aws/map.jinja" import aws_data with context %} 5 | 6 | # Loop through regions 7 | {%- for region_name, region_data in aws_data.get('region', {}).items() %} 8 | {%- set profile = region_data.get('profile') %} 9 | 10 | # Loop through VPCs 11 | {%- for vpc_name, vpc_data in region_data.get('vpc').items() %} 12 | 13 | # Create VPC 14 | aws_vpc_{{ vpc_name }}_create: 15 | boto_vpc.present: 16 | {%- for option, value in vpc_data.get('vpc', {}).items() %} 17 | - {{ option }}: '{{ value }}' 18 | {%- endfor %} 19 | - profile: {{ profile }} 20 | 21 | # Create Internet Gateway 22 | aws_vpc_{{ vpc_name }}_create_internet_gateway: 23 | boto_vpc.internet_gateway_present: 24 | - name: {{ vpc_data.get('internet_gateway:name', 'internet_gateway') }}-{{ vpc_name }} 25 | - vpc_name: {{ vpc_name }} 26 | - profile: {{ profile }} 27 | 28 | # Create Subnets. Optionally NAT Gateways 29 | {%- for subnet_number, subnet_data in vpc_data.get('subnets', {}).items() %} 30 | aws_vpc_{{ vpc_name }}_create_subnet_{{ subnet_data.name }}: 31 | boto_vpc.subnet_present: 32 | - name: {{ subnet_data.name }}-{{ vpc_name }} 33 | - vpc_name: {{ vpc_name }} 34 | - cidr_block: {{ vpc_data.cidr_prefix }}.{{ subnet_number }}.0/24 35 | - availability_zone: {{ region_name }}{{ subnet_data.az }} 36 | - profile: {{ profile }} 37 | 38 | {%- if subnet_data.get('nat_gateway', False ) %} 39 | aws_vpc_{{ vpc_name }}_create_nat_gateway_{{ subnet_data.name }}: 40 | boto_vpc.nat_gateway_present: 41 | - subnet_name: {{ subnet_data.name }}-{{ vpc_name }} 42 | - profile: {{ profile }} 43 | {%- endif %} 44 | {% endfor %} 45 | 46 | # Create Routing Tables. Optionally create 47 | # - routes 48 | # - Global routes ( must be routes in order for global routes will be created ) 49 | # - subnet associations 50 | 51 | {%- for table_name, table_data in vpc_data.get('routing_tables', {}).items() %} 52 | aws_vpc_{{ vpc_name }}_create_routing_table_{{ table_name }}: 53 | boto_vpc.route_table_present: 54 | - name: {{ table_name }}-{{ vpc_name }} 55 | - vpc_name: {{ vpc_name }} 56 | - profile: {{ profile }} 57 | {%- if table_data.get('routes', false ) %} 58 | - routes: 59 | {%- for route_name, route_data in table_data.get('routes').items() %} 60 | {%- for option, value in route_data.items() %} 61 | {% if option in rt_append_list %} 62 | {% set value = '{0}-{1}'.format( value, vpc_name ) %} 63 | {% endif %} 64 | {%- if loop.first %} 65 | - {{ option }}: '{{ value }}' 66 | {%- else %} 67 | {{ option }}: '{{ value }}' 68 | {%- endif %} 69 | {%- endfor %} 70 | {%- endfor %} 71 | {%- for route_name, route_data in vpc_data.get('routing_global_routes',{}).items() %} 72 | {%- for option, value in route_data.items() %} 73 | {% if option in rt_append_list %} 74 | {% set value = '{0}-{1}'.format( value, vpc_name ) %} 75 | {% endif %} 76 | {%- if loop.first %} 77 | - {{ option }}: '{{ value }}' 78 | {%- else %} 79 | {{ option }}: '{{ value }}' 80 | {%- endif %} 81 | {%- endfor %} 82 | {%- endfor %} 83 | {%- endif %} 84 | 85 | {%- if table_data.get('subnet_names', false ) %} 86 | - subnet_names: 87 | {%- for subnet_name in table_data.subnet_names %} 88 | - {{ subnet_name }}-{{ vpc_name }} 89 | {%- endfor %} 90 | {%- endif %} 91 | {% endfor %} 92 | {% endfor %} 93 | {% endfor %} 94 | -------------------------------------------------------------------------------- /pillar.example: -------------------------------------------------------------------------------- 1 | # This example creates a 3 tiered (web, app, db) VPC spanning 3 Avalability Zones. 2 | # web tier has public IPs and app/db tier are internal and use a NAT Gateway for internet access. 3 | # 4 | # Using Jinja to set a few variables to cause repeated hard-coding of values in the pillar 5 | 6 | # Global CIDR for all your VPCs. Use this for Security Group rules 7 | {% set cidr_global = '10.0.0.0/8' %} 8 | 9 | aws: 10 | region: 11 | us-east-2: 12 | keys: 13 | mykey: 'ssh-rsa XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX admin@mycompany.com' 14 | profile: 15 | region: us-east-2 16 | keyid: ASDFASDFASDFASDFASDF 17 | key: AB12Cd3Efg45hIjk67lMNop8q9RST0uvwXyz 18 | vpc: 19 | # Set VPC specific variables at the top of each pillar. 20 | # setting vpc_name so that Security Groups names can include the VPC name 21 | {%- set vpc_name = 'vpcProdEast2' %} 22 | # Set cidr_local for use in secuirty group rules. 23 | # make sure it is consistent with the cidr_prefix 2 lines below 24 | {%- set cidr_local = '10.20.0.0/16' %} 25 | {{ vpc_name }}: 26 | cidr_prefix: '10.20' 27 | vpc: 28 | name: {{ vpc_name }} 29 | cidr_block: '{{ cidr_local }}' 30 | instance_tenancy: default 31 | dns_support: 'true' 32 | dns_hostnames: 'true' 33 | # Can only have one internet_gateway 34 | internet_gateway: 35 | name: internet_gateway 36 | subnets: 37 | # web subnets are 1,2,3 38 | 1: 39 | name: subWebA 40 | az: a 41 | nat_gateway: true 42 | 2: 43 | name: subWebB 44 | az: b 45 | nat_gateway: true 46 | 3: 47 | name: subWebC 48 | az: c 49 | nat_gateway: true 50 | # app subnets are 11,12,13 51 | 11: 52 | name: subAppA 53 | az: a 54 | 12: 55 | name: subAppB 56 | az: b 57 | 13: 58 | name: subAppC 59 | az: c 60 | # db subnets are 21, 22, 23 61 | 21: 62 | name: subDbA 63 | az: a 64 | 22: 65 | name: subDbB 66 | az: b 67 | 23: 68 | name: subDbC 69 | az: c 70 | # These will be added to every table 71 | # get the instance ID of the VPN server to connect to the 10.10 region 72 | # VPC and put here, then uncomment below 73 | # routing_tables_global: 74 | # vpnPROD: 75 | # destination_cidr_block: '10.10.0.0/16' 76 | # instance_id: i-xxxxxxxxxxxxxx 77 | routing_tables: 78 | # Create a public routing table for web subnet in each AZ per best practices 79 | publicA: 80 | routes: 81 | default: 82 | destination_cidr_block: '0.0.0.0/0' 83 | internet_gateway_name: internet_gateway 84 | subnet_names: 85 | - subWebA 86 | publicB: 87 | routes: 88 | default: 89 | destination_cidr_block: '0.0.0.0/0' 90 | internet_gateway_name: internet_gateway 91 | subnet_names: 92 | - subWebB 93 | publicC: 94 | routes: 95 | default: 96 | destination_cidr_block: '0.0.0.0/0' 97 | internet_gateway_name: internet_gateway 98 | subnet_names: 99 | - subWebC 100 | # Create a private routing table for App and DB subnets in each AZ 101 | privateA: 102 | routes: 103 | default: 104 | destination_cidr_block: '0.0.0.0/0' 105 | nat_gateway_subnet_name: subWebA 106 | subnet_names: 107 | - subAppA 108 | - subDbA 109 | privateB: 110 | routes: 111 | default: 112 | destination_cidr_block: '0.0.0.0/0' 113 | nat_gateway_subnet_name: subWebB 114 | subnet_names: 115 | - subAppB 116 | - subDbB 117 | privateC: 118 | routes: 119 | default: 120 | destination_cidr_block: '0.0.0.0/0' 121 | nat_gateway_subnet_name: subWebC 122 | subnet_names: 123 | - subAppC 124 | - subDbC 125 | security_groups: 126 | # Create a baseline security group with rules that apply to all servers. 127 | # All security groups include the VPC name in case these security group 128 | # names are used in another vpc via vpc peering 129 | sgBase: 130 | description: Base SG for all servers 131 | rules: 132 | ssh: 133 | ip_protocol: tcp 134 | port: 22 135 | cidr_ip: '{{ cidr_global }}' 136 | icmp: 137 | ip_protocol: icmp 138 | port: -1 139 | cidr_ip: '{{ cidr_global }}' 140 | rules_egress: 141 | all: 142 | ip_protocol: all 143 | port: -1 144 | cidr_ip: '0.0.0.0/0' 145 | # Web servers can access app servers. 146 | # App servers can access other app servers. 147 | sgApp: 148 | description: SG for all App servers 149 | rules: 150 | http: 151 | ip_protocol: tcp 152 | port: 80 153 | source_group_name: 154 | - sgWeb-{{ vpc_name }} 155 | - sgApp-{{ vpc_name }} 156 | https: 157 | ip_protocol: tcp 158 | port: 443 159 | source_group_name: 160 | - sgWeb-{{ vpc_name }} 161 | - sgApp-{{ vpc_name }} 162 | # App servers can access DB servers 163 | # DB servers can access other DB servers ( for replication to slaves ) 164 | sgDB: 165 | description: SG for all DB servers 166 | rules: 167 | mysql: 168 | ip_protocol: tcp 169 | port: 3306 170 | source_group_name: 171 | - sgApp-{{ vpc_name }} 172 | - sgDB-{{ vpc_name }} 173 | # Allow openVPN users access 174 | sgOpenVPN: 175 | description: SG for all OpenVPN servers 176 | rules: 177 | openVPN_tcp: 178 | ip_protocol: tcp 179 | port: 1194 180 | cidr_ip: '0.0.0.0/0' 181 | openVPN_udp: 182 | ip_protocol: udp 183 | port: 1194 184 | cidr_ip: '0.0.0.0/0' 185 | # All servers can talk to the salt server 186 | sgSalt: 187 | description: SG for all Salt servers 188 | rules: 189 | salt-master: 190 | ip_protocol: tcp 191 | from_port: 4505 192 | to_port: 4506 193 | cidr_ip: '{{ cidr_local }}' 194 | salt-api: 195 | ip_protocol: tcp 196 | port: 443 197 | cidr_ip: '{{ cidr_local }}' 198 | # Ipsec VPN servers can communicate across the internet 199 | sgIPSecVPN: 200 | description: SG for all IPSec VPN servers 201 | rules: 202 | vpn_ike: 203 | ip_protocol: udp 204 | port: 500 205 | cidr_ip: '0.0.0.0/0' 206 | vpn_ipsec_nat_tcp: 207 | ip_protocol: udp 208 | port: 4500 209 | cidr_ip: '0.0.0.0/0' 210 | vpn_ipsec_nat_udp: 211 | ip_protocol: tcp 212 | port: 4500 213 | cidr_ip: '0.0.0.0/0' 214 | vpn_l2tp: 215 | ip_protocol: udp 216 | port: 1701 217 | cidr_ip: '0.0.0.0/0' 218 | # Internet can access web servers 219 | sgWeb: 220 | description: SG for all Web servers 221 | rules: 222 | http: 223 | ip_protocol: tcp 224 | port: 80 225 | cidr_ip: '0.0.0.0/0' 226 | https: 227 | ip_protocol: tcp 228 | port: 443 229 | cidr_ip: '0.0.0.0/0' 230 | -------------------------------------------------------------------------------- /README.rst: -------------------------------------------------------------------------------- 1 | aws-formula 2 | ============ 3 | 4 | Configure the non-server parts of an AWS datacenter without using CloudFormation. Multiple VPCs in multiple regions can be configured with one pillar. 5 | 6 | **Requires**: Saltstack 2016.11 ( 2015.8.2 if not using NAT Gateway ) and Boto3 7 | 8 | .. note:: 9 | 10 | See the full `Salt Formulas installation and usage instructions 11 | `_. 12 | 13 | Available states 14 | ======================= 15 | 16 | .. contents:: 17 | :local: 18 | 19 | ``vpc`` 20 | --------- 21 | 22 | Create VPC objects, including: 23 | 24 | - VPC 25 | - Internet Gateway 26 | - NAT Gateway 27 | - Subnets 28 | - Routing Tables 29 | 30 | ``ec2`` 31 | ---------------- 32 | 33 | Create ec2 components including: 34 | 35 | - Key pairs 36 | 37 | ``secgroups`` 38 | ---------------- 39 | 40 | Create and update Security Groups rules. Servers must be added to the Security Groups as part of the salt-cloud creation proces. 41 | 42 | Limitations and Workarounds 43 | ================================== 44 | 45 | The salt boto states used in this formula have some limitations that require workarounds for the formula to work. These are: 46 | 47 | - Many object names must be unique. 48 | - Inter-Region VPN connections can not be added to routing table 49 | - Security Group rule creation can fail when when referencing other groups 50 | 51 | **Object names must be unique** 52 | 53 | The saltstack states/modules do a check if the resource exists before creating it. This lookup is not VPC specific, so will match on objects of the same name in different VPCs. If only one VPC is created in a region, this is not a problem, but if multiple are created it will cause some of the required resources to not be created. The workaround is most objects will have the VPC name appended as a suffix ( example: subAppA in the pillar will have -myVPC appended to become subAppA-myVPC ) 54 | 55 | **Inter-Region VPN** 56 | 57 | AWS currently does not offer a service for VPC peering between regions. This means the recommended solution is to create a VPN instance and then use an ipsec VPN tunnel between regions. Unfortunately, when using VPN instances you can not use the **Route Propagation** functionality, so those routes have to be manually added to all routing tables for a VPC. VPN routing is shown commented out in the pillar example. Like above, run the states once to create all of the objects. Then when the VPN tunnel is created/active, add the IPs to the pillar and rerun the states. 58 | 59 | **Security Group rule creation failure** 60 | 61 | Security Group rules will sometimes include references to other Security Groups. But the oder Groups are Created is indeterminate ( not alphabetical or pillar order ). So sometimes a Security Group creation will fail because it is being created before the group it references. Re-running the formula to create these failed security groups. 62 | 63 | VPC Selection 64 | ================= 65 | By default the states for all VPCs defined in the aws pillar will be run. 66 | To limit states to a single VPC use the command line pillar 67 | 68 | .. code-block:: 69 | 70 | salt myserver state.apply pillar='{"vpc":"myvpc"}' 71 | 72 | 73 | Configuration 74 | ================= 75 | 76 | All configuration is done through the AWS pillar. The hierarchy of this pillar is: 77 | 78 | .. code-block:: yaml 79 | 80 | aws: 81 | region: 82 | us-east-2: 83 | key_pairs: 84 | profile: 85 | vpc: 86 | myvpc: 87 | vpc: 88 | internet_gateway: 89 | subnets: 90 | routing_tables: 91 | routing_global_routes: 92 | security_groups: 93 | 94 | In this hierarchy, the 3rd level ( us-east-2 ) is a region name and the 5th level ( myvpc ) is a vpc name. These are the names that will be used for the region and the name of the VPC. All items besides internet_gateway can have multiple values. 95 | 96 | The below examples and the sample pillar uses single quotes in many places to ensure data is interepreted correctly. Not using quotes per the examples is done at your own risk. 97 | 98 | .. contents:: 99 | :local: 100 | 101 | 102 | ``key_pairs`` 103 | ------------- 104 | Key pairs are included under at the region level since they are not generally VPC specific. Key pair format is a key pair with the name and RSA public key. 105 | 106 | .. code-block:: yaml 107 | 108 | key_pairs: 109 | mykey: 'ssh-rsa XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX admin@mycompany.com' 110 | 111 | ``profile`` 112 | ------------ 113 | This formula uses an AWS profile for all states instead of the individual fields. The key and keyid should be gpg encrypted using the `Saltstack gpg renderer `_. Example below shows it in unencrypted format. 114 | 115 | .. code-block:: yaml 116 | 117 | profile: 118 | region: us-east-2 119 | keyid: ASDFASDFASDFASDFASDF 120 | key: AB12Cd3Efg45hIjk67lMNop8q9RST0uvwXyz 121 | 122 | 123 | ``vpc`` 124 | ------------ 125 | VPC contains vpcs for a given region. Each vpc will have data for all VPC specific states, even if they are not in the vpc.sls. The vpc pillar name is the name that will be used for the VPC in AWS. The only data directly under the vpc name is the CIDR block for the VPC. This Formula is designed using a class B network for the VPC and class C for all subnets. 126 | 127 | .. code-block:: yaml 128 | 129 | vpc: 130 | myvpc: 131 | cidr_prefix: '10.10' 132 | 133 | ``vpc:vpc`` 134 | ------------ 135 | the VPC subsection contains the data needed to create the VPC. The names on the left are the configuration item names from the boto_vpc.present states. The vpc pillar name should always match the name in the vpc section beneath. The cidr_block should start with the same two octets as the cidr_prefix above. 136 | 137 | .. code-block:: yaml 138 | 139 | vpc: 140 | myvpc: 141 | vpc: 142 | name: myvpc 143 | cidr_block: 10.10.0.0/16 144 | instance_tennancy: default 145 | dns_support: 'true' 146 | dns_hostnames: 'true' 147 | 148 | ``vpc:internet_gateway`` 149 | ----------------------------- 150 | An internet gateway is needed for most use cases. 151 | 152 | .. code-block:: yaml 153 | 154 | vpc: 155 | myvpc: 156 | internet_gateway: 157 | name: internet_gateway 158 | 159 | 160 | ``vpc:subnets`` 161 | ------------------ 162 | Subnets are named by their subnet ID ( assumes we are using class C subnets). The subnet ID will be appended to the cidr_prefix above to create the CIDR or the subnet. Every subnet has to at least have a subnet name and availability zone. if nat_gateway is specified, then a NAT Gateway will be created in that subnet. Subnet associations are done in the Routing Table section below. 163 | 164 | .. code-block:: yaml 165 | 166 | vpc: 167 | myvpc: 168 | subnets: 169 | 1: 170 | name: subWebA 171 | az: a 172 | nat_gateway: true 173 | 11: 174 | name: appwebA 175 | az: a 176 | 177 | The above example would create two subnets: 178 | 179 | - subWebA with CIDR 10.10.1.0/24 180 | - subAppA with CIDR 10.10.1.0/24 181 | 182 | Both are in Availability Zone A and a NAT Gateway would be created in subWebA. 183 | 184 | ``vpc:routing_tables`` 185 | ------------------------------ 186 | Routing tables will create the tables, add routes, and assign subnets to routing tables. The below example uses a subnet name that has a NAT Gateway to assocate that NAT Gateway with the routing table. 187 | 188 | .. code-block:: yaml 189 | 190 | vpc: 191 | myvpc: 192 | routig_tables: 193 | publicA: 194 | routes: 195 | default: 196 | destination_cidr_block: 0.0.0.0/0 197 | internet_gateway_name: internet_gateway 198 | subnet_names: 199 | - subWebA 200 | privateA: 201 | routes: 202 | default: 203 | destination_cidr_block: 0.0.0.0/0 204 | nat_gateway_subnet_name: subWebA 205 | subnet_names: 206 | - subAppA 207 | 208 | ``vpc:routing_global_routes`` 209 | ------------------------------ 210 | Routes that will be added to all routing tables. Use this for adding vpn routes. 211 | 212 | .. code-block:: yaml 213 | 214 | vpc: 215 | myvpc: 216 | routing_global_routes: 217 | vpnPROD: 218 | destination_cidr_block: '10.10.0.0/16' 219 | instance_id: 'i-xxxxxxxxxxxxxxx' 220 | 221 | ``vpc:security_groups`` 222 | --------------------------- 223 | Create security groups and rules. Usage notes: 224 | 225 | - If a single port is being specified, the `from_port` and `to port` can be replace with just `port`. 226 | - source_group_name and cidr_ip can be either a single item or a list. 227 | - Use `port: -1` to specify all ports 228 | - A rules pillar name is for information purposes only and is not used in the actual rule creation.s 229 | 230 | .. code-block:: yaml 231 | 232 | vpc: 233 | myvpc: 234 | security_groups: 235 | sgApp: 236 | description: SG for all App servers 237 | rules: 238 | http: 239 | ip_protocol: tcp 240 | port: 80 241 | source_group_name: 242 | - sgWeb-myvpc 243 | - sgApp-myvpc 244 | rules_egress: 245 | all: 246 | ip_protocol: all 247 | port: -1 248 | cidr_ip: '0.0.0.0/0' 249 | sgSalt: 250 | description: SG for all Salt servers 251 | rules: 252 | salt-master: 253 | ip_protocol: tcp 254 | from_port: 4505 255 | to_port: 4506 256 | cidr_ip: '10.10.0.0/16' 257 | salt-api: 258 | ip_protocol: tcp 259 | port: 443 260 | cidr_ip: 261 | - '10.10.0.0/16' 262 | - '10.20.0.0/16' 263 | --------------------------------------------------------------------------------