├── CODE_OF_CONDUCT.md ├── LICENSE ├── README.md ├── CONTRIBUTING.md └── infra.yaml /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | ## Code of Conduct 2 | This project has adopted the [Amazon Open Source Code of Conduct](https://aws.github.io/code-of-conduct). 3 | For more information see the [Code of Conduct FAQ](https://aws.github.io/code-of-conduct-faq) or contact 4 | opensource-codeofconduct@amazon.com with any additional questions or comments. 5 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT No Attribution 2 | 3 | Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so. 10 | 11 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 12 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 13 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 14 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 15 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 16 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 17 | 18 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Accelerate IPv6 adoption on AWS with Amazon VPC Lattice 2 | 3 | This repo includes the Cloudformation template that deploys the architecture shown in Figure-1 at this blog: 4 | https://aws.amazon.com/blogs/networking-and-content-delivery/accelerate-your-ipv6-adoption-on-aws-with-amazon-vpc-lattice/ 5 | 6 | ## PreRequisites 7 | The template will deploy VPCs, EC2 instances and Amazon VPC Lattice constructs into your AWS account. Ensure that you have the right IAM credentials. You can issue `aws configure` to check the AWS permissions. 8 | 9 | ## Deploying the template 10 | 11 | Isse this command to clone the repo: 12 | ``` 13 | git clone https://github.com/aws-samples/accelerate-ipv6-adoption-on-aws-with-amazon-vpc-lattice/ 14 | ``` 15 | 16 | After that, navigate to the right directory: 17 | ``` 18 | cd accelerate-ipv6-adoption-on-aws-with-amazon-vpc-lattice 19 | ``` 20 | 21 | Use the following command to deploy the CloudFormation template. Please replace the correct SSHClientIP and SSHClientIPv6 addresses. These are the IP and IPv6 addresses of your SSH client machine: 22 | 23 | ``` 24 | aws cloudformation create-stack --stack-name lattice-ipv6-stack \ 25 | --template-body file://infra.yaml \ 26 | --parameters ParameterKey=SSHClientIP,ParameterValue=a.b.c.d/32 \ 27 | ParameterKey=SSHClientIPv6,ParameterValue=2001:db8::1/128 \ 28 | --capabilities CAPABILITY_NAMED_IAM 29 | ``` 30 | Currently the instances do not have HTTPD automatically installed. After creating the stack, please log into the instances and install HTTPD. 31 | 32 | ## Cleanup 33 | Use this command to delete the stack and all the resources deployed by the stack: 34 | ``` 35 | aws cloudformation delete-stack --stack-name lattice-ipv6-stack 36 | ``` 37 | 38 | ## Security 39 | 40 | See [CONTRIBUTING](CONTRIBUTING.md#security-issue-notifications) for more information. 41 | 42 | ## License 43 | 44 | This library is licensed under the MIT-0 License. See the LICENSE file. 45 | 46 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing Guidelines 2 | 3 | Thank you for your interest in contributing to our project. Whether it's a bug report, new feature, correction, or additional 4 | documentation, we greatly value feedback and contributions from our community. 5 | 6 | Please read through this document before submitting any issues or pull requests to ensure we have all the necessary 7 | information to effectively respond to your bug report or contribution. 8 | 9 | 10 | ## Reporting Bugs/Feature Requests 11 | 12 | We welcome you to use the GitHub issue tracker to report bugs or suggest features. 13 | 14 | When filing an issue, please check existing open, or recently closed, issues to make sure somebody else hasn't already 15 | reported the issue. Please try to include as much information as you can. Details like these are incredibly useful: 16 | 17 | * A reproducible test case or series of steps 18 | * The version of our code being used 19 | * Any modifications you've made relevant to the bug 20 | * Anything unusual about your environment or deployment 21 | 22 | 23 | ## Contributing via Pull Requests 24 | Contributions via pull requests are much appreciated. Before sending us a pull request, please ensure that: 25 | 26 | 1. You are working against the latest source on the *main* branch. 27 | 2. You check existing open, and recently merged, pull requests to make sure someone else hasn't addressed the problem already. 28 | 3. You open an issue to discuss any significant work - we would hate for your time to be wasted. 29 | 30 | To send us a pull request, please: 31 | 32 | 1. Fork the repository. 33 | 2. Modify the source; please focus on the specific change you are contributing. If you also reformat all the code, it will be hard for us to focus on your change. 34 | 3. Ensure local tests pass. 35 | 4. Commit to your fork using clear commit messages. 36 | 5. Send us a pull request, answering any default questions in the pull request interface. 37 | 6. Pay attention to any automated CI failures reported in the pull request, and stay involved in the conversation. 38 | 39 | GitHub provides additional document on [forking a repository](https://help.github.com/articles/fork-a-repo/) and 40 | [creating a pull request](https://help.github.com/articles/creating-a-pull-request/). 41 | 42 | 43 | ## Finding contributions to work on 44 | Looking at the existing issues is a great way to find something to contribute on. As our projects, by default, use the default GitHub issue labels (enhancement/bug/duplicate/help wanted/invalid/question/wontfix), looking at any 'help wanted' issues is a great place to start. 45 | 46 | 47 | ## Code of Conduct 48 | This project has adopted the [Amazon Open Source Code of Conduct](https://aws.github.io/code-of-conduct). 49 | For more information see the [Code of Conduct FAQ](https://aws.github.io/code-of-conduct-faq) or contact 50 | opensource-codeofconduct@amazon.com with any additional questions or comments. 51 | 52 | 53 | ## Security issue notifications 54 | If you discover a potential security issue in this project we ask that you notify AWS/Amazon Security via our [vulnerability reporting page](http://aws.amazon.com/security/vulnerability-reporting/). Please do **not** create a public github issue. 55 | 56 | 57 | ## Licensing 58 | 59 | See the [LICENSE](LICENSE) file for our project's licensing. We will ask you to confirm the licensing of your contribution. 60 | -------------------------------------------------------------------------------- /infra.yaml: -------------------------------------------------------------------------------- 1 | AWSTemplateFormatVersion: "2010-09-09" 2 | Description: "VPC Infrastructure with IPv4/IPv6 Subnets, NAT Gateways, VPC Lattice, and EC2 Instances" 3 | 4 | Parameters: 5 | LatestAmiId: 6 | Type: "AWS::SSM::Parameter::Value" 7 | Default: "/aws/service/ami-amazon-linux-latest/al2023-ami-kernel-default-x86_64" 8 | Description: "Latest Amazon Linux 2023 AMI" 9 | 10 | Resources: 11 | 12 | # ---------- Security Groups ---------- 13 | VPC1InstanceSecurityGroup: 14 | DependsOn: 15 | - LatticeInfoFunction 16 | - LatticeInfoResource 17 | Type: AWS::EC2::SecurityGroup 18 | Properties: 19 | GroupDescription: "Security group for VPC1 EC2 instances" 20 | VpcId: !Ref VPC1 21 | SecurityGroupIngress: 22 | - Description: Allow HTTP from VPC Lattice IPv4 23 | IpProtocol: tcp 24 | FromPort: 80 25 | ToPort: 80 26 | SourcePrefixListId: !GetAtt LatticeInfoResource.IPv4PrefixList 27 | - Description: Allow HTTP from VPC Lattice IPv6 28 | IpProtocol: tcp 29 | FromPort: 80 30 | ToPort: 80 31 | SourcePrefixListId: !GetAtt LatticeInfoResource.IPv6PrefixList 32 | SecurityGroupEgress: 33 | - Description: Allow HTTPS for downloading webserver httpd 34 | IpProtocol: tcp 35 | FromPort: 443 36 | ToPort: 443 37 | CidrIp: 0.0.0.0/0 38 | - Description: Allow HTTPS for downloading webserver httpd 39 | IpProtocol: tcp 40 | FromPort: 443 41 | ToPort: 443 42 | CidrIpv6: ::/0 43 | - Description: Allow HTTP to VPC Lattice IPv4 44 | IpProtocol: tcp 45 | FromPort: 80 46 | ToPort: 80 47 | DestinationPrefixListId: !GetAtt LatticeInfoResource.IPv4PrefixList 48 | - Description: Allow HTTP to VPC Lattice IPv6 49 | IpProtocol: tcp 50 | FromPort: 80 51 | ToPort: 80 52 | DestinationPrefixListId: !GetAtt LatticeInfoResource.IPv6PrefixList 53 | Tags: 54 | - Key: Name 55 | Value: VPC1-Instance-SG 56 | 57 | VPC1EndpointsSecurityGroup: 58 | Type: AWS::EC2::SecurityGroup 59 | DependsOn: 60 | - NATGW1PrivateIP 61 | - NATGW2PrivateIP 62 | Properties: 63 | GroupDescription: "Security group for VPC1 VPC endpoints that allows HTTPS traffic from EC2 instances and NAT Gateway private IPs" 64 | VpcId: !Ref VPC1 65 | SecurityGroupIngress: 66 | - Description: Allow HTTPS from instances 67 | IpProtocol: tcp 68 | FromPort: 443 69 | ToPort: 443 70 | SourceSecurityGroupId: !Ref VPC1InstanceSecurityGroup 71 | - Description: Allow HTTPS from VPC1NATGW1 72 | IpProtocol: tcp 73 | FromPort: 443 74 | ToPort: 443 75 | CidrIp: !Sub "${NATGW1PrivateIP.PrivateIp}/32" 76 | - Description: Allow HTTPS from VPC1NATGW2 77 | IpProtocol: tcp 78 | FromPort: 443 79 | ToPort: 443 80 | CidrIp: !Sub "${NATGW2PrivateIP.PrivateIp}/32" 81 | SecurityGroupEgress: 82 | - IpProtocol: tcp 83 | FromPort: 443 84 | ToPort: 443 85 | CidrIp: 0.0.0.0/0 86 | - IpProtocol: tcp 87 | FromPort: 443 88 | ToPort: 443 89 | CidrIpv6: ::/0 90 | Tags: 91 | - Key: Name 92 | Value: VPC1-Endpoints-SG 93 | 94 | VPC1LatticeSecurityGroup: 95 | Type: AWS::EC2::SecurityGroup 96 | Properties: 97 | GroupDescription: "Security group for VPC1 VPC Lattice service integration that allows HTTP/HTTPS traffic from EC2 instances and enables outbound HTTPS for service communication" 98 | VpcId: !Ref VPC1 99 | SecurityGroupIngress: 100 | - Description: Allow HTTP from instances 101 | IpProtocol: tcp 102 | FromPort: 80 103 | ToPort: 80 104 | SourceSecurityGroupId: !Ref VPC1InstanceSecurityGroup 105 | - Description: Allow HTTPS from instances 106 | IpProtocol: tcp 107 | FromPort: 443 108 | ToPort: 443 109 | SourceSecurityGroupId: !Ref VPC1InstanceSecurityGroup 110 | SecurityGroupEgress: 111 | - IpProtocol: tcp 112 | FromPort: 443 113 | ToPort: 443 114 | CidrIp: 0.0.0.0/0 115 | - IpProtocol: tcp 116 | FromPort: 443 117 | ToPort: 443 118 | CidrIpv6: ::/0 119 | Tags: 120 | - Key: Name 121 | Value: VPC1-Lattice-SG 122 | 123 | VPC2InstanceSecurityGroup: 124 | DependsOn: 125 | - LatticeInfoFunction 126 | - LatticeInfoResource 127 | Type: AWS::EC2::SecurityGroup 128 | Properties: 129 | GroupDescription: "Security group for VPC2 EC2 instances" 130 | VpcId: !Ref VPC2 131 | SecurityGroupIngress: 132 | - Description: Allow HTTP from VPC Lattice IPv4 133 | IpProtocol: tcp 134 | FromPort: 80 135 | ToPort: 80 136 | SourcePrefixListId: !GetAtt LatticeInfoResource.IPv4PrefixList 137 | - Description: Allow HTTP from VPC Lattice IPv6 138 | IpProtocol: tcp 139 | FromPort: 80 140 | ToPort: 80 141 | SourcePrefixListId: !GetAtt LatticeInfoResource.IPv6PrefixList 142 | SecurityGroupEgress: 143 | - Description: Allow HTTP for downloading webserver httpd 144 | IpProtocol: tcp 145 | FromPort: 443 146 | ToPort: 443 147 | CidrIp: 0.0.0.0/0 148 | - Description: Allow HTTP for downloading webserver httpd 149 | IpProtocol: tcp 150 | FromPort: 443 151 | ToPort: 443 152 | CidrIpv6: ::/0 153 | - Description: Allow HTTP to VPC Lattice IPv4PrefixList 154 | IpProtocol: tcp 155 | FromPort: 80 156 | ToPort: 80 157 | DestinationPrefixListId: !GetAtt LatticeInfoResource.IPv4PrefixList 158 | - Description: Allow HTTP to VPC Lattice IPv6PrefixList 159 | IpProtocol: tcp 160 | FromPort: 80 161 | ToPort: 80 162 | DestinationPrefixListId: !GetAtt LatticeInfoResource.IPv6PrefixList 163 | Tags: 164 | - Key: Name 165 | Value: VPC2-Instance-SG 166 | 167 | VPC2EndpointsSecurityGroup: 168 | Type: AWS::EC2::SecurityGroup 169 | DependsOn: 170 | - NATGW3PrivateIP 171 | - NATGW4PrivateIP 172 | Properties: 173 | GroupDescription: "Security group for VPC2 VPC endpoints that allows HTTPS traffic from EC2 instances and NAT Gateway private IPs" 174 | VpcId: !Ref VPC2 175 | SecurityGroupIngress: 176 | - Description: Allow HTTPS from instances 177 | IpProtocol: tcp 178 | FromPort: 443 179 | ToPort: 443 180 | SourceSecurityGroupId: !Ref VPC2InstanceSecurityGroup 181 | - Description: Allow HTTPS from VPC2NATGW1 182 | IpProtocol: tcp 183 | FromPort: 443 184 | ToPort: 443 185 | CidrIp: !Sub "${NATGW3PrivateIP.PrivateIp}/32" 186 | - Description: Allow HTTPS from VPC2NATGW2 187 | IpProtocol: tcp 188 | FromPort: 443 189 | ToPort: 443 190 | CidrIp: !Sub "${NATGW4PrivateIP.PrivateIp}/32" 191 | SecurityGroupEgress: 192 | - IpProtocol: tcp 193 | FromPort: 443 194 | ToPort: 443 195 | CidrIp: 0.0.0.0/0 196 | - IpProtocol: tcp 197 | FromPort: 443 198 | ToPort: 443 199 | CidrIpv6: ::/0 200 | Tags: 201 | - Key: Name 202 | Value: VPC2-Endpoints-SG 203 | 204 | VPC2LatticeSecurityGroup: 205 | Type: AWS::EC2::SecurityGroup 206 | Properties: 207 | GroupDescription: "Security group for VPC2 VPC Lattice service integration that allows HTTP/HTTPS traffic from EC2 instances and enables outbound HTTPS for service communication" 208 | VpcId: !Ref VPC2 209 | SecurityGroupIngress: 210 | - Description: Allow HTTP from instances 211 | IpProtocol: tcp 212 | FromPort: 80 213 | ToPort: 80 214 | SourceSecurityGroupId: !Ref VPC2InstanceSecurityGroup 215 | - Description: Allow HTTPS from instances 216 | IpProtocol: tcp 217 | FromPort: 443 218 | ToPort: 443 219 | SourceSecurityGroupId: !Ref VPC2InstanceSecurityGroup 220 | SecurityGroupEgress: 221 | - IpProtocol: tcp 222 | FromPort: 443 223 | ToPort: 443 224 | CidrIp: 0.0.0.0/0 225 | - IpProtocol: tcp 226 | FromPort: 443 227 | ToPort: 443 228 | CidrIpv6: ::/0 229 | Tags: 230 | - Key: Name 231 | Value: VPC2-Lattice-SG 232 | 233 | # ---------- VPCs and IPv6 CIDRs ---------- 234 | VPC1: 235 | Type: AWS::EC2::VPC 236 | Properties: 237 | CidrBlock: 10.1.0.0/16 238 | EnableDnsSupport: true 239 | EnableDnsHostnames: true 240 | InstanceTenancy: default 241 | Tags: 242 | - Key: Name 243 | Value: VPC-1 244 | 245 | VPC1IPv6CIDR: 246 | Type: AWS::EC2::VPCCidrBlock 247 | Properties: 248 | AmazonProvidedIpv6CidrBlock: true 249 | VpcId: !Ref VPC1 250 | 251 | VPC2: 252 | Type: AWS::EC2::VPC 253 | Properties: 254 | CidrBlock: 10.2.0.0/16 255 | EnableDnsSupport: true 256 | EnableDnsHostnames: true 257 | InstanceTenancy: default 258 | Tags: 259 | - Key: Name 260 | Value: VPC-2 261 | 262 | VPC2IPv6CIDR: 263 | Type: AWS::EC2::VPCCidrBlock 264 | Properties: 265 | AmazonProvidedIpv6CidrBlock: true 266 | VpcId: !Ref VPC2 267 | 268 | # ---------- Internet Gateways and Attachments ---------- 269 | VPC1IGW: 270 | Type: AWS::EC2::InternetGateway 271 | Properties: 272 | Tags: 273 | - Key: Name 274 | Value: VPC1-IGW 275 | 276 | VPC2IGW: 277 | Type: AWS::EC2::InternetGateway 278 | Properties: 279 | Tags: 280 | - Key: Name 281 | Value: VPC2-IGW 282 | 283 | VPC1IGWAttachment: 284 | Type: AWS::EC2::VPCGatewayAttachment 285 | Properties: 286 | VpcId: !Ref VPC1 287 | InternetGatewayId: !Ref VPC1IGW 288 | 289 | VPC2IGWAttachment: 290 | Type: AWS::EC2::VPCGatewayAttachment 291 | Properties: 292 | VpcId: !Ref VPC2 293 | InternetGatewayId: !Ref VPC2IGW 294 | 295 | # ---------- Egress-Only Internet Gateways ---------- 296 | VPC1EIGW: 297 | Type: AWS::EC2::EgressOnlyInternetGateway 298 | Properties: 299 | VpcId: !Ref VPC1 300 | 301 | VPC2EIGW: 302 | Type: AWS::EC2::EgressOnlyInternetGateway 303 | Properties: 304 | VpcId: !Ref VPC2 305 | 306 | # ---------- Route Tables ---------- 307 | VPC1PublicRouteTable: 308 | Type: AWS::EC2::RouteTable 309 | Properties: 310 | VpcId: !Ref VPC1 311 | Tags: 312 | - Key: Name 313 | Value: VPC1-Public-RT 314 | 315 | VPC1IPv4OnlySubnetRouteTable1: 316 | Type: AWS::EC2::RouteTable 317 | Properties: 318 | VpcId: !Ref VPC1 319 | Tags: 320 | - Key: Name 321 | Value: VPC1-IPV4-RT-AZ1 322 | 323 | VPC1IPv6OnlySubnetRouteTable2: 324 | Type: AWS::EC2::RouteTable 325 | Properties: 326 | VpcId: !Ref VPC1 327 | Tags: 328 | - Key: Name 329 | Value: VPC1-IPV6-RT-AZ2 330 | 331 | VPC2PublicRouteTable: 332 | Type: AWS::EC2::RouteTable 333 | Properties: 334 | VpcId: !Ref VPC2 335 | Tags: 336 | - Key: Name 337 | Value: VPC2-Public-RT 338 | 339 | VPC2IPv4OnlySubnetRouteTable1: 340 | Type: AWS::EC2::RouteTable 341 | Properties: 342 | VpcId: !Ref VPC2 343 | Tags: 344 | - Key: Name 345 | Value: VPC2-IPV4-RT-AZ1 346 | 347 | VPC2DualStackSubnetRouteTable2: 348 | Type: AWS::EC2::RouteTable 349 | Properties: 350 | VpcId: !Ref VPC2 351 | Tags: 352 | - Key: Name 353 | Value: VPC2-DualStack-RT-AZ2 354 | 355 | # ---------- Elastic IPs for NAT Gateways ---------- 356 | VPC1EIP1: 357 | Type: AWS::EC2::EIP 358 | Properties: 359 | Domain: vpc 360 | Tags: 361 | - Key: Name 362 | Value: VPC1-NAT-EIP1 363 | 364 | VPC1EIP2: 365 | Type: AWS::EC2::EIP 366 | Properties: 367 | Domain: vpc 368 | Tags: 369 | - Key: Name 370 | Value: VPC1-NAT-EIP2 371 | 372 | VPC2EIP1: 373 | Type: AWS::EC2::EIP 374 | Properties: 375 | Domain: vpc 376 | Tags: 377 | - Key: Name 378 | Value: VPC2-NAT-EIP1 379 | 380 | VPC2EIP2: 381 | Type: AWS::EC2::EIP 382 | Properties: 383 | Domain: vpc 384 | Tags: 385 | - Key: Name 386 | Value: VPC2-NAT-EIP2 387 | 388 | # ---------- Subnets ---------- 389 | # VPC1 Public Subnets 390 | VPC1PublicSubnet1: 391 | Type: AWS::EC2::Subnet 392 | DependsOn: VPC1IPv6CIDR 393 | Properties: 394 | VpcId: !Ref VPC1 395 | AvailabilityZone: !Select [0, !GetAZs ""] 396 | CidrBlock: 10.1.10.0/24 397 | Ipv6CidrBlock: 398 | Fn::Select: 399 | - 0 400 | - Fn::Cidr: 401 | - !Select [0, !GetAtt VPC1.Ipv6CidrBlocks] 402 | - 256 403 | - 64 404 | AssignIpv6AddressOnCreation: true 405 | Tags: 406 | - Key: Name 407 | Value: VPC1-Public-Subnet-1 408 | 409 | VPC1PublicSubnet2: 410 | Type: AWS::EC2::Subnet 411 | DependsOn: VPC1IPv6CIDR 412 | Properties: 413 | VpcId: !Ref VPC1 414 | AvailabilityZone: !Select [1, !GetAZs ""] 415 | CidrBlock: 10.1.11.0/24 416 | Ipv6CidrBlock: 417 | Fn::Select: 418 | - 1 419 | - Fn::Cidr: 420 | - !Select [0, !GetAtt VPC1.Ipv6CidrBlocks] 421 | - 256 422 | - 64 423 | AssignIpv6AddressOnCreation: true 424 | Tags: 425 | - Key: Name 426 | Value: VPC1-Public-Subnet-2 427 | 428 | 429 | # VPC1 Private Subnets 430 | VPC1IPv4OnlySubnet: 431 | Type: AWS::EC2::Subnet 432 | Properties: 433 | VpcId: !Ref VPC1 434 | AvailabilityZone: !Select [0, !GetAZs ""] 435 | CidrBlock: 10.1.0.0/24 436 | Tags: 437 | - Key: Name 438 | Value: VPC1-IPv4-Only-Subnet 439 | 440 | VPC1IPv6OnlySubnet: 441 | Type: AWS::EC2::Subnet 442 | DependsOn: VPC1IPv6CIDR 443 | Properties: 444 | VpcId: !Ref VPC1 445 | AvailabilityZone: !Select [1, !GetAZs ""] 446 | Ipv6Native: true 447 | EnableDns64: true 448 | Ipv6CidrBlock: 449 | Fn::Select: 450 | - 2 451 | - Fn::Cidr: 452 | - !Select [0, !GetAtt VPC1.Ipv6CidrBlocks] 453 | - 256 454 | - 64 455 | AssignIpv6AddressOnCreation: true 456 | Tags: 457 | - Key: Name 458 | Value: VPC1-IPv6-Only-Subnet 459 | 460 | 461 | VPC1EndpointsSubnet1: 462 | Type: AWS::EC2::Subnet 463 | DependsOn: VPC1IPv6CIDR 464 | Properties: 465 | VpcId: !Ref VPC1 466 | AvailabilityZone: !Select [0, !GetAZs ""] 467 | CidrBlock: 10.1.3.0/24 468 | Ipv6CidrBlock: 469 | Fn::Select: 470 | - 3 471 | - Fn::Cidr: 472 | - !Select [0, !GetAtt VPC1.Ipv6CidrBlocks] 473 | - 256 474 | - 64 475 | AssignIpv6AddressOnCreation: true 476 | Tags: 477 | - Key: Name 478 | Value: VPC1-Endpoints-Subnet-1 479 | 480 | VPC1EndpointsSubnet2: 481 | Type: AWS::EC2::Subnet 482 | DependsOn: VPC1IPv6CIDR 483 | Properties: 484 | VpcId: !Ref VPC1 485 | AvailabilityZone: !Select [1, !GetAZs ""] 486 | CidrBlock: 10.1.4.0/24 487 | Ipv6CidrBlock: 488 | Fn::Select: 489 | - 4 490 | - Fn::Cidr: 491 | - !Select [0, !GetAtt VPC1.Ipv6CidrBlocks] 492 | - 256 493 | - 64 494 | AssignIpv6AddressOnCreation: true 495 | Tags: 496 | - Key: Name 497 | Value: VPC1-Endpoints-Subnet-2 498 | 499 | # VPC2 Public Subnets 500 | VPC2PublicSubnet1: 501 | Type: AWS::EC2::Subnet 502 | DependsOn: VPC2IPv6CIDR 503 | Properties: 504 | VpcId: !Ref VPC2 505 | AvailabilityZone: !Select [0, !GetAZs ""] 506 | CidrBlock: 10.2.1.0/24 507 | Ipv6CidrBlock: 508 | Fn::Select: 509 | - 0 510 | - Fn::Cidr: 511 | - !Select [0, !GetAtt VPC2.Ipv6CidrBlocks] 512 | - 256 513 | - 64 514 | AssignIpv6AddressOnCreation: true 515 | Tags: 516 | - Key: Name 517 | Value: VPC2-Public-Subnet-1 518 | 519 | VPC2PublicSubnet2: 520 | Type: AWS::EC2::Subnet 521 | DependsOn: VPC2IPv6CIDR 522 | Properties: 523 | VpcId: !Ref VPC2 524 | AvailabilityZone: !Select [1, !GetAZs ""] 525 | CidrBlock: 10.2.11.0/24 526 | Ipv6CidrBlock: 527 | Fn::Select: 528 | - 1 529 | - Fn::Cidr: 530 | - !Select [0, !GetAtt VPC2.Ipv6CidrBlocks] 531 | - 256 532 | - 64 533 | AssignIpv6AddressOnCreation: true 534 | Tags: 535 | - Key: Name 536 | Value: VPC2-Public-Subnet-2 537 | 538 | # VPC2 Private Subnets 539 | VPC2IPv4OnlySubnet: 540 | Type: AWS::EC2::Subnet 541 | Properties: 542 | VpcId: !Ref VPC2 543 | AvailabilityZone: !Select [0, !GetAZs ""] 544 | CidrBlock: 10.2.20.0/24 545 | Tags: 546 | - Key: Name 547 | Value: VPC2-IPv4-Only-Subnet 548 | 549 | VPC2DualStackSubnet: 550 | Type: AWS::EC2::Subnet 551 | DependsOn: VPC2IPv6CIDR 552 | Properties: 553 | VpcId: !Ref VPC2 554 | AvailabilityZone: !Select [1, !GetAZs ""] 555 | CidrBlock: 10.2.10.0/24 556 | EnableDns64: true 557 | Ipv6CidrBlock: 558 | Fn::Select: 559 | - 2 560 | - Fn::Cidr: 561 | - !Select [0, !GetAtt VPC2.Ipv6CidrBlocks] 562 | - 256 563 | - 64 564 | AssignIpv6AddressOnCreation: true 565 | Tags: 566 | - Key: Name 567 | Value: VPC2DualStack-Subnet 568 | 569 | VPC2EndpointsSubnet1: 570 | DependsOn: 571 | - VPC2IPv6CIDR 572 | Type: AWS::EC2::Subnet 573 | Properties: 574 | VpcId: !Ref VPC2 575 | AvailabilityZone: !Select [0, !GetAZs ""] 576 | CidrBlock: 10.2.3.0/24 577 | Ipv6CidrBlock: 578 | Fn::Select: 579 | - 3 580 | - Fn::Cidr: 581 | - !Select [0, !GetAtt VPC2.Ipv6CidrBlocks] 582 | - 256 583 | - 64 584 | AssignIpv6AddressOnCreation: true 585 | Tags: 586 | - Key: Name 587 | Value: VPC2-Endpoints-Subnet-1 588 | 589 | VPC2EndpointsSubnet2: 590 | DependsOn: 591 | - VPC2IPv6CIDR 592 | Type: AWS::EC2::Subnet 593 | Properties: 594 | VpcId: !Ref VPC2 595 | AvailabilityZone: !Select [1, !GetAZs ""] 596 | CidrBlock: 10.2.4.0/24 597 | Ipv6CidrBlock: 598 | Fn::Select: 599 | - 4 600 | - Fn::Cidr: 601 | - !Select [0, !GetAtt VPC2.Ipv6CidrBlocks] 602 | - 256 603 | - 64 604 | AssignIpv6AddressOnCreation: true 605 | Tags: 606 | - Key: Name 607 | Value: VPC2-Endpoints-Subnet-2 608 | 609 | # ---------- NAT Gateways ---------- 610 | VPC1NATGW1: 611 | Type: AWS::EC2::NatGateway 612 | Properties: 613 | AllocationId: !GetAtt VPC1EIP1.AllocationId 614 | SubnetId: !Ref VPC1PublicSubnet1 615 | Tags: 616 | - Key: Name 617 | Value: VPC1-NATGW-AZ1 618 | 619 | VPC1NATGW2: 620 | Type: AWS::EC2::NatGateway 621 | Properties: 622 | AllocationId: !GetAtt VPC1EIP2.AllocationId 623 | SubnetId: !Ref VPC1PublicSubnet2 624 | Tags: 625 | - Key: Name 626 | Value: VPC1-NATGW-AZ2 627 | 628 | VPC2NATGW1: 629 | Type: AWS::EC2::NatGateway 630 | Properties: 631 | AllocationId: !GetAtt VPC2EIP1.AllocationId 632 | SubnetId: !Ref VPC2PublicSubnet1 633 | Tags: 634 | - Key: Name 635 | Value: VPC2-NATGW-AZ1 636 | 637 | VPC2NATGW2: 638 | Type: AWS::EC2::NatGateway 639 | Properties: 640 | AllocationId: !GetAtt VPC2EIP2.AllocationId 641 | SubnetId: !Ref VPC2PublicSubnet2 642 | Tags: 643 | - Key: Name 644 | Value: VPC2-NATGW-AZ2 645 | 646 | 647 | # ---------- Route Table Associations ---------- 648 | VPC1PublicSubnet1RouteTableAssociation: 649 | Type: AWS::EC2::SubnetRouteTableAssociation 650 | Properties: 651 | SubnetId: !Ref VPC1PublicSubnet1 652 | RouteTableId: !Ref VPC1PublicRouteTable 653 | 654 | VPC1PublicSubnet2RouteTableAssociation: 655 | Type: AWS::EC2::SubnetRouteTableAssociation 656 | Properties: 657 | SubnetId: !Ref VPC1PublicSubnet2 658 | RouteTableId: !Ref VPC1PublicRouteTable 659 | 660 | VPC1IPv4OnlySubnetRouteTableAssociation: 661 | Type: AWS::EC2::SubnetRouteTableAssociation 662 | Properties: 663 | SubnetId: !Ref VPC1IPv4OnlySubnet 664 | RouteTableId: !Ref VPC1IPv4OnlySubnetRouteTable1 665 | 666 | VPC1IPv6OnlySubnetRouteTableAssociation: 667 | Type: AWS::EC2::SubnetRouteTableAssociation 668 | Properties: 669 | SubnetId: !Ref VPC1IPv6OnlySubnet 670 | RouteTableId: !Ref VPC1IPv6OnlySubnetRouteTable2 671 | 672 | VPC2PublicSubnet1RouteTableAssociation: 673 | Type: AWS::EC2::SubnetRouteTableAssociation 674 | Properties: 675 | SubnetId: !Ref VPC2PublicSubnet1 676 | RouteTableId: !Ref VPC2PublicRouteTable 677 | 678 | VPC2PublicSubnet2RouteTableAssociation: 679 | Type: AWS::EC2::SubnetRouteTableAssociation 680 | Properties: 681 | SubnetId: !Ref VPC2PublicSubnet2 682 | RouteTableId: !Ref VPC2PublicRouteTable 683 | 684 | VPC2IPv4OnlySubnetRouteTableAssociation: 685 | Type: AWS::EC2::SubnetRouteTableAssociation 686 | Properties: 687 | SubnetId: !Ref VPC2IPv4OnlySubnet 688 | RouteTableId: !Ref VPC2IPv4OnlySubnetRouteTable1 689 | 690 | VPC2DualStackSubnetRouteTableAssociation: 691 | Type: AWS::EC2::SubnetRouteTableAssociation 692 | Properties: 693 | SubnetId: !Ref VPC2DualStackSubnet 694 | RouteTableId: !Ref VPC2DualStackSubnetRouteTable2 695 | 696 | # ---------- Routes ---------- 697 | # VPC1 Public Routes 698 | VPC1PublicDefaultRoute: 699 | Type: AWS::EC2::Route 700 | DependsOn: VPC1IGWAttachment 701 | Properties: 702 | RouteTableId: !Ref VPC1PublicRouteTable 703 | DestinationCidrBlock: 0.0.0.0/0 704 | GatewayId: !Ref VPC1IGW 705 | 706 | VPC1PublicDefaultIPv6Route: 707 | Type: AWS::EC2::Route 708 | DependsOn: VPC1IGWAttachment 709 | Properties: 710 | RouteTableId: !Ref VPC1PublicRouteTable 711 | DestinationIpv6CidrBlock: ::/0 712 | GatewayId: !Ref VPC1IGW 713 | 714 | # VPC1 Private Routes 715 | VPC1PrivateDefaultRoute1: 716 | Type: AWS::EC2::Route 717 | Properties: 718 | RouteTableId: !Ref VPC1IPv4OnlySubnetRouteTable1 719 | DestinationCidrBlock: 0.0.0.0/0 720 | NatGatewayId: !Ref VPC1NATGW1 721 | 722 | VPC1PrivateDefaultRoute2: 723 | Type: AWS::EC2::Route 724 | Properties: 725 | RouteTableId: !Ref VPC1IPv6OnlySubnetRouteTable2 726 | DestinationCidrBlock: 0.0.0.0/0 727 | NatGatewayId: !Ref VPC1NATGW2 728 | 729 | VPC1PrivateDefaultRoute3: 730 | Type: AWS::EC2::Route 731 | Properties: 732 | RouteTableId: !Ref VPC1IPv6OnlySubnetRouteTable2 733 | DestinationIpv6CidrBlock: 64:ff9b::/96 734 | NatGatewayId: !Ref VPC1NATGW2 735 | 736 | VPC1PrivateDefaultIPv6Route1: 737 | Type: AWS::EC2::Route 738 | Properties: 739 | RouteTableId: !Ref VPC1IPv4OnlySubnetRouteTable1 740 | DestinationIpv6CidrBlock: ::/0 741 | EgressOnlyInternetGatewayId: !Ref VPC1EIGW 742 | 743 | VPC1PrivateDefaultIPv6Route2: 744 | Type: AWS::EC2::Route 745 | Properties: 746 | RouteTableId: !Ref VPC1IPv6OnlySubnetRouteTable2 747 | DestinationIpv6CidrBlock: ::/0 748 | EgressOnlyInternetGatewayId: !Ref VPC1EIGW 749 | 750 | # VPC2 Public Routes 751 | VPC2PublicDefaultRoute: 752 | Type: AWS::EC2::Route 753 | DependsOn: VPC2IGWAttachment 754 | Properties: 755 | RouteTableId: !Ref VPC2PublicRouteTable 756 | DestinationCidrBlock: 0.0.0.0/0 757 | GatewayId: !Ref VPC2IGW 758 | 759 | VPC2PublicDefaultIPv6Route: 760 | Type: AWS::EC2::Route 761 | DependsOn: VPC2IGWAttachment 762 | Properties: 763 | RouteTableId: !Ref VPC2PublicRouteTable 764 | DestinationIpv6CidrBlock: ::/0 765 | GatewayId: !Ref VPC2IGW 766 | 767 | # VPC2 Private Routes 768 | VPC2PrivateDefaultRoute1: 769 | Type: AWS::EC2::Route 770 | Properties: 771 | RouteTableId: !Ref VPC2IPv4OnlySubnetRouteTable1 772 | DestinationCidrBlock: 0.0.0.0/0 773 | NatGatewayId: !Ref VPC2NATGW1 774 | 775 | VPC2PrivateDefaultRoute2: 776 | Type: AWS::EC2::Route 777 | Properties: 778 | RouteTableId: !Ref VPC2DualStackSubnetRouteTable2 779 | DestinationCidrBlock: 0.0.0.0/0 780 | NatGatewayId: !Ref VPC2NATGW2 781 | 782 | VPC2PrivateDefaultRoute3: 783 | Type: AWS::EC2::Route 784 | Properties: 785 | RouteTableId: !Ref VPC2DualStackSubnetRouteTable2 786 | DestinationIpv6CidrBlock: 64:ff9b::/96 787 | NatGatewayId: !Ref VPC2NATGW2 788 | 789 | VPC2PrivateDefaultIPv6Route1: 790 | Type: AWS::EC2::Route 791 | Properties: 792 | RouteTableId: !Ref VPC2IPv4OnlySubnetRouteTable1 793 | DestinationIpv6CidrBlock: ::/0 794 | EgressOnlyInternetGatewayId: !Ref VPC2EIGW 795 | 796 | VPC2PrivateDefaultIPv6Route2: 797 | Type: AWS::EC2::Route 798 | Properties: 799 | RouteTableId: !Ref VPC2DualStackSubnetRouteTable2 800 | DestinationIpv6CidrBlock: ::/0 801 | EgressOnlyInternetGatewayId: !Ref VPC2EIGW 802 | 803 | # ---------- VPC Endpoints ---------- 804 | VPC1SSMEndpoint: 805 | Type: AWS::EC2::VPCEndpoint 806 | Properties: 807 | ServiceName: !Sub com.amazonaws.${AWS::Region}.ssm 808 | VpcId: !Ref VPC1 809 | SubnetIds: 810 | - !Ref VPC1EndpointsSubnet1 811 | - !Ref VPC1EndpointsSubnet2 812 | SecurityGroupIds: 813 | - !Ref VPC1EndpointsSecurityGroup 814 | VpcEndpointType: Interface 815 | PrivateDnsEnabled: true 816 | PolicyDocument: 817 | Version: '2012-10-17' 818 | Statement: 819 | - Effect: Allow 820 | Principal: '*' 821 | Action: '*' 822 | Resource: '*' 823 | Condition: 824 | StringEquals: 825 | 'aws:PrincipalAccount': !Ref 'AWS::AccountId' 826 | 827 | VPC1SSMMessagesEndpoint: 828 | Type: AWS::EC2::VPCEndpoint 829 | Properties: 830 | ServiceName: !Sub com.amazonaws.${AWS::Region}.ssmmessages 831 | VpcId: !Ref VPC1 832 | SubnetIds: 833 | - !Ref VPC1EndpointsSubnet1 834 | - !Ref VPC1EndpointsSubnet2 835 | SecurityGroupIds: 836 | - !Ref VPC1EndpointsSecurityGroup 837 | VpcEndpointType: Interface 838 | PrivateDnsEnabled: true 839 | PolicyDocument: 840 | Version: '2012-10-17' 841 | Statement: 842 | - Effect: Allow 843 | Principal: '*' 844 | Action: '*' 845 | Resource: '*' 846 | Condition: 847 | StringEquals: 848 | 'aws:PrincipalAccount': !Ref 'AWS::AccountId' 849 | 850 | VPC1EC2MessagesEndpoint: 851 | Type: AWS::EC2::VPCEndpoint 852 | Properties: 853 | ServiceName: !Sub com.amazonaws.${AWS::Region}.ec2messages 854 | VpcId: !Ref VPC1 855 | SubnetIds: 856 | - !Ref VPC1EndpointsSubnet1 857 | - !Ref VPC1EndpointsSubnet2 858 | SecurityGroupIds: 859 | - !Ref VPC1EndpointsSecurityGroup 860 | VpcEndpointType: Interface 861 | PrivateDnsEnabled: true 862 | PolicyDocument: 863 | Version: '2012-10-17' 864 | Statement: 865 | - Effect: Allow 866 | Principal: '*' 867 | Action: '*' 868 | Resource: '*' 869 | Condition: 870 | StringEquals: 871 | 'aws:PrincipalAccount': !Ref 'AWS::AccountId' 872 | 873 | VPC2SSMEndpoint: 874 | Type: AWS::EC2::VPCEndpoint 875 | Properties: 876 | ServiceName: !Sub com.amazonaws.${AWS::Region}.ssm 877 | VpcId: !Ref VPC2 878 | SubnetIds: 879 | - !Ref VPC2EndpointsSubnet1 880 | - !Ref VPC2EndpointsSubnet2 881 | SecurityGroupIds: 882 | - !Ref VPC2EndpointsSecurityGroup 883 | VpcEndpointType: Interface 884 | PrivateDnsEnabled: true 885 | PolicyDocument: 886 | Version: '2012-10-17' 887 | Statement: 888 | - Effect: Allow 889 | Principal: '*' 890 | Action: '*' 891 | Resource: '*' 892 | Condition: 893 | StringEquals: 894 | 'aws:PrincipalAccount': !Ref 'AWS::AccountId' 895 | 896 | VPC2SSMMessagesEndpoint: 897 | Type: AWS::EC2::VPCEndpoint 898 | Properties: 899 | ServiceName: !Sub com.amazonaws.${AWS::Region}.ssmmessages 900 | VpcId: !Ref VPC2 901 | SubnetIds: 902 | - !Ref VPC2EndpointsSubnet1 903 | - !Ref VPC2EndpointsSubnet2 904 | SecurityGroupIds: 905 | - !Ref VPC2EndpointsSecurityGroup 906 | VpcEndpointType: Interface 907 | PrivateDnsEnabled: true 908 | PolicyDocument: 909 | Version: '2012-10-17' 910 | Statement: 911 | - Effect: Allow 912 | Principal: '*' 913 | Action: '*' 914 | Resource: '*' 915 | Condition: 916 | StringEquals: 917 | 'aws:PrincipalAccount': !Ref 'AWS::AccountId' 918 | 919 | VPC2EC2MessagesEndpoint: 920 | Type: AWS::EC2::VPCEndpoint 921 | Properties: 922 | ServiceName: !Sub com.amazonaws.${AWS::Region}.ec2messages 923 | VpcId: !Ref VPC2 924 | SubnetIds: 925 | - !Ref VPC2EndpointsSubnet1 926 | - !Ref VPC2EndpointsSubnet2 927 | SecurityGroupIds: 928 | - !Ref VPC2EndpointsSecurityGroup 929 | VpcEndpointType: Interface 930 | PrivateDnsEnabled: true 931 | PolicyDocument: 932 | Version: '2012-10-17' 933 | Statement: 934 | - Effect: Allow 935 | Principal: '*' 936 | Action: '*' 937 | Resource: '*' 938 | Condition: 939 | StringEquals: 940 | 'aws:PrincipalAccount': !Ref 'AWS::AccountId' 941 | 942 | # ---------- IAM Roles ---------- 943 | EC2SSMIAMRoleWorkloads: 944 | Type: AWS::IAM::Role 945 | Properties: 946 | AssumeRolePolicyDocument: 947 | Version: '2012-10-17' 948 | Statement: 949 | - Effect: Allow 950 | Principal: 951 | Service: ec2.amazonaws.com 952 | Action: sts:AssumeRole 953 | ManagedPolicyArns: 954 | - arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore 955 | Path: / 956 | 957 | EC2SSMInstanceProfileWorkloads: 958 | Type: AWS::IAM::InstanceProfile 959 | Properties: 960 | Path: / 961 | Roles: 962 | - !Ref EC2SSMIAMRoleWorkloads 963 | 964 | 965 | EC2DescribeManagedPrefixListsPolicy: 966 | Type: AWS::IAM::ManagedPolicy 967 | Properties: 968 | Description: "Policy for EC2 describe managed prefix lists" 969 | PolicyDocument: 970 | Version: '2012-10-17' 971 | Statement: 972 | - Effect: Allow 973 | Action: ec2:DescribeManagedPrefixLists 974 | Resource: '*' 975 | 976 | CustomEC2DescribePolicy: 977 | Type: AWS::IAM::ManagedPolicy 978 | Properties: 979 | Description: "Policy for EC2 describe actions needed by Lambda functions" 980 | PolicyDocument: 981 | Version: '2012-10-17' 982 | Statement: 983 | - Effect: Allow 984 | Action: ec2:Describe* 985 | Resource: '*' 986 | 987 | # ---------- EC2 Instances ---------- 988 | VPC1IPv4Instance: 989 | Type: AWS::EC2::Instance 990 | DependsOn: 991 | - VPC1SSMEndpoint 992 | - VPC1SSMMessagesEndpoint 993 | - VPC1EC2MessagesEndpoint 994 | Properties: 995 | InstanceType: t3.micro 996 | EbsOptimized: true 997 | Monitoring: true 998 | IamInstanceProfile: !Ref EC2SSMInstanceProfileWorkloads 999 | ImageId: !Ref LatestAmiId 1000 | SecurityGroupIds: 1001 | - !Ref VPC1InstanceSecurityGroup 1002 | SubnetId: !Ref VPC1IPv4OnlySubnet 1003 | UserData: 1004 | Fn::Base64: !Sub | 1005 | #!/bin/bash 1006 | yum update -y 1007 | yum install -y httpd 1008 | systemctl start httpd 1009 | systemctl enable httpd 1010 | echo "Hello from Application-1's version-1. This instance is deployed in an IPv4 only subnet." > /var/www/html/index.html 1011 | Tags: 1012 | - Key: Name 1013 | Value: VPC1-IPv4-Only-Instance 1014 | 1015 | VPC1IPv6Instance: 1016 | Type: AWS::EC2::Instance 1017 | DependsOn: 1018 | - VPC1SSMEndpoint 1019 | - VPC1SSMMessagesEndpoint 1020 | - VPC1EC2MessagesEndpoint 1021 | Properties: 1022 | InstanceType: t3.micro 1023 | EbsOptimized: true 1024 | Monitoring: true 1025 | IamInstanceProfile: !Ref EC2SSMInstanceProfileWorkloads 1026 | ImageId: !Ref LatestAmiId 1027 | SecurityGroupIds: 1028 | - !Ref VPC1InstanceSecurityGroup 1029 | SubnetId: !Ref VPC1IPv6OnlySubnet 1030 | UserData: 1031 | Fn::Base64: !Sub | 1032 | #!/bin/bash 1033 | yum update -y 1034 | yum install -y httpd 1035 | systemctl start httpd 1036 | systemctl enable httpd 1037 | echo "Hello from Application-1's version-2. This instance is deployed in an IPv6 only subnet." > /var/www/html/index.html 1038 | Tags: 1039 | - Key: Name 1040 | Value: VPC1-IPv6-Only-Instance 1041 | 1042 | VPC2IPv4Instance: 1043 | Type: AWS::EC2::Instance 1044 | DependsOn: 1045 | - VPC2SSMEndpoint 1046 | - VPC2SSMMessagesEndpoint 1047 | - VPC2EC2MessagesEndpoint 1048 | Properties: 1049 | InstanceType: t3.micro 1050 | EbsOptimized: true 1051 | Monitoring: true 1052 | IamInstanceProfile: !Ref EC2SSMInstanceProfileWorkloads 1053 | ImageId: !Ref LatestAmiId 1054 | SecurityGroupIds: 1055 | - !Ref VPC2InstanceSecurityGroup 1056 | SubnetId: !Ref VPC2IPv4OnlySubnet 1057 | UserData: 1058 | Fn::Base64: !Sub | 1059 | #!/bin/bash 1060 | yum update -y 1061 | yum install -y httpd 1062 | systemctl start httpd 1063 | systemctl enable httpd 1064 | echo "Hello from Application-2's version-1. This instance is deployed in an IPv4 only subnet." > /var/www/html/index.html 1065 | Tags: 1066 | - Key: Name 1067 | Value: VPC2-IPv4-Only-Instance 1068 | 1069 | VPC2DualStackInstance: 1070 | Type: AWS::EC2::Instance 1071 | DependsOn: 1072 | - VPC2SSMEndpoint 1073 | - VPC2SSMMessagesEndpoint 1074 | - VPC2EC2MessagesEndpoint 1075 | Properties: 1076 | InstanceType: t3.micro 1077 | EbsOptimized: true 1078 | Monitoring: true 1079 | IamInstanceProfile: !Ref EC2SSMInstanceProfileWorkloads 1080 | ImageId: !Ref LatestAmiId 1081 | SecurityGroupIds: 1082 | - !Ref VPC2InstanceSecurityGroup 1083 | SubnetId: !Ref VPC2DualStackSubnet 1084 | UserData: 1085 | Fn::Base64: !Sub | 1086 | #!/bin/bash 1087 | yum update -y 1088 | yum install -y httpd 1089 | systemctl start httpd 1090 | systemctl enable httpd 1091 | echo "Hello from Application-2's version-2. This instance is deployed in a dual stack subnet." > /var/www/html/index.html 1092 | Tags: 1093 | - Key: Name 1094 | Value: VPC2-Dual-Stack-Instance 1095 | 1096 | # ---------- Lambda Resources ---------- 1097 | LambdaBasicExecutionRole: 1098 | Type: AWS::IAM::Role 1099 | Properties: 1100 | AssumeRolePolicyDocument: 1101 | Version: '2012-10-17' 1102 | Statement: 1103 | - Effect: Allow 1104 | Principal: 1105 | Service: lambda.amazonaws.com 1106 | Action: sts:AssumeRole 1107 | Path: / 1108 | ManagedPolicyArns: 1109 | - !Sub arn:${AWS::Partition}:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole 1110 | - !Ref CustomEC2DescribePolicy 1111 | Tags: 1112 | - Key: Name 1113 | Value: IPv6-Lambda-Role 1114 | 1115 | # DLQ not needed - CloudFormation manages retries 1116 | # Lambda Function performs error handling 1117 | CustomFunction: 1118 | Type: AWS::Lambda::Function 1119 | Properties: 1120 | FunctionName: !Sub "CustomFunction-${AWS::StackName}" 1121 | Handler: index.lambda_handler 1122 | ReservedConcurrentExecutions: 5 1123 | Description: "Retrieves IPv6 address of EC2 instance" 1124 | Timeout: 30 1125 | MemorySize: 128 1126 | Role: !GetAtt LambdaBasicExecutionRole.Arn 1127 | Runtime: python3.11 1128 | Environment: 1129 | Variables: 1130 | LOG_LEVEL: INFO 1131 | Code: 1132 | ZipFile: | 1133 | import json 1134 | import logging 1135 | import cfnresponse 1136 | import boto3 1137 | 1138 | logger = logging.getLogger() 1139 | logger.setLevel(logging.INFO) 1140 | 1141 | def lambda_handler(event, context): 1142 | logger.info(f'Event received: {json.dumps(event, default=str)}') 1143 | logger.info(f'Context: {context}') 1144 | try: 1145 | responseData = {} 1146 | if event['RequestType'] == 'Delete': 1147 | logger.info('Processing Delete operation') 1148 | cfnresponse.send(event, context, cfnresponse.SUCCESS, {}) 1149 | return 1150 | 1151 | if event['RequestType'] in ["Create", "Update"]: 1152 | ResourceRef = event['ResourceProperties']['ResourceRef'] 1153 | logger.info(f'Processing {event["RequestType"]} for instance: {ResourceRef}') 1154 | 1155 | ec2 = boto3.client('ec2') 1156 | logger.info('Calling describe_network_interfaces') 1157 | response = ec2.describe_network_interfaces( 1158 | Filters=[{'Name': 'attachment.instance-id', 'Values': [ResourceRef]}] 1159 | ) 1160 | logger.info(f'EC2 response: {json.dumps(response, default=str)}') 1161 | 1162 | if response['NetworkInterfaces']: 1163 | eni = response['NetworkInterfaces'][0] 1164 | logger.info(f'Found ENI: {eni.get("NetworkInterfaceId")}') 1165 | ipv6_addresses = eni.get('Ipv6Addresses', []) 1166 | logger.info(f'IPv6 addresses found: {ipv6_addresses}') 1167 | 1168 | if ipv6_addresses: 1169 | responseData['Ipv6Address'] = ipv6_addresses[0]['Ipv6Address'] 1170 | logger.info(f"Success - IPv6 address: {responseData['Ipv6Address']}") 1171 | cfnresponse.send(event, context, cfnresponse.SUCCESS, responseData) 1172 | return 1173 | else: 1174 | logger.warning('No IPv6 addresses found on ENI') 1175 | else: 1176 | logger.warning('No network interfaces found for instance') 1177 | 1178 | raise Exception(f"No IPv6 address found for instance {ResourceRef}") 1179 | 1180 | logger.warning(f'Unexpected RequestType: {event.get("RequestType")}') 1181 | cfnresponse.send(event, context, cfnresponse.SUCCESS, responseData) 1182 | 1183 | except Exception as err: 1184 | logger.error(f'Error in lambda_handler: {str(err)}', exc_info=True) 1185 | responseData = {"Error": str(err)} 1186 | cfnresponse.send(event, context, cfnresponse.FAILED, responseData) 1187 | 1188 | CustomIpv6Resource1: 1189 | Type: AWS::CloudFormation::CustomResource 1190 | Properties: 1191 | ServiceToken: !GetAtt CustomFunction.Arn 1192 | ResourceRef: !Ref VPC1IPv6Instance 1193 | 1194 | CustomIpv6Resource2: 1195 | Type: AWS::CloudFormation::CustomResource 1196 | Properties: 1197 | ServiceToken: !GetAtt CustomFunction.Arn 1198 | ResourceRef: !Ref VPC2DualStackInstance 1199 | 1200 | LatticeInfoFunctionRole: 1201 | Type: AWS::IAM::Role 1202 | Properties: 1203 | AssumeRolePolicyDocument: 1204 | Version: '2012-10-17' 1205 | Statement: 1206 | - Effect: Allow 1207 | Principal: 1208 | Service: lambda.amazonaws.com 1209 | Action: sts:AssumeRole 1210 | ManagedPolicyArns: 1211 | - !Sub arn:${AWS::Partition}:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole 1212 | - !Ref EC2DescribeManagedPrefixListsPolicy 1213 | 1214 | # DLQ not needed - CloudFormation manages retries 1215 | # Lambda Function performs error handling 1216 | LatticeInfoFunction: 1217 | Type: AWS::Lambda::Function 1218 | DependsOn: LatticeInfoFunctionLogGroup 1219 | Properties: 1220 | FunctionName: !Sub "LatticeInfoFunction-${AWS::StackName}" 1221 | Handler: index.handler 1222 | ReservedConcurrentExecutions: 5 1223 | Role: !GetAtt LatticeInfoFunctionRole.Arn 1224 | Runtime: python3.11 1225 | Timeout: 30 1226 | Environment: 1227 | Variables: 1228 | LOG_LEVEL: INFO 1229 | Code: 1230 | ZipFile: | 1231 | import boto3 1232 | import cfnresponse 1233 | import json 1234 | import logging 1235 | 1236 | logger = logging.getLogger() 1237 | logger.setLevel(logging.INFO) 1238 | 1239 | def handler(event, context): 1240 | logger.info(f'Event received: {json.dumps(event, default=str)}') 1241 | logger.info(f'AWS Region: {boto3.Session().region_name}') 1242 | 1243 | if event['RequestType'] in ['Create', 'Update']: 1244 | logger.info(f'Processing {event["RequestType"]} request') 1245 | ec2 = boto3.client('ec2') 1246 | try: 1247 | logger.info('Calling describe_managed_prefix_lists for VPC Lattice') 1248 | response = ec2.describe_managed_prefix_lists( 1249 | Filters=[ 1250 | { 1251 | 'Name': 'prefix-list-name', 1252 | 'Values': ['com.amazonaws.*.vpc-lattice'] 1253 | } 1254 | ] 1255 | ) 1256 | logger.info(f"API response: {json.dumps(response, default=str)}") 1257 | 1258 | prefix_lists = response.get('PrefixLists', []) 1259 | logger.info(f"Found {len(prefix_lists)} prefix lists") 1260 | 1261 | ipv4_pl = None 1262 | ipv6_pl = None 1263 | 1264 | for pl in prefix_lists: 1265 | name = pl.get('PrefixListName', '') 1266 | pl_id = pl.get('PrefixListId', '') 1267 | logger.info(f"Processing prefix list: {name} -> {pl_id}") 1268 | 1269 | if 'ipv6' in name.lower(): 1270 | ipv6_pl = pl_id 1271 | logger.info(f"Found IPv6 prefix list: {ipv6_pl}") 1272 | else: 1273 | ipv4_pl = pl_id 1274 | logger.info(f"Found IPv4 prefix list: {ipv4_pl}") 1275 | 1276 | if not ipv4_pl or not ipv6_pl: 1277 | error_msg = f"Missing prefix lists. IPv4: {ipv4_pl}, IPv6: {ipv6_pl}. Region may not support VPC Lattice." 1278 | logger.error(error_msg) 1279 | raise Exception(error_msg) 1280 | 1281 | responseData = { 1282 | 'IPv4PrefixList': ipv4_pl, 1283 | 'IPv6PrefixList': ipv6_pl 1284 | } 1285 | logger.info(f"Success - sending response: {responseData}") 1286 | cfnresponse.send(event, context, cfnresponse.SUCCESS, responseData) 1287 | except Exception as e: 1288 | logger.error(f"Error in handler: {str(e)}", exc_info=True) 1289 | cfnresponse.send(event, context, cfnresponse.FAILED, {"Error": str(e)}) 1290 | else: 1291 | logger.info(f'Processing {event.get("RequestType", "Unknown")} request - no action needed') 1292 | cfnresponse.send(event, context, cfnresponse.SUCCESS, {}) 1293 | 1294 | LatticeInfoResource: 1295 | Type: Custom::LatticeInfo 1296 | DependsOn: LatticeInfoFunction 1297 | Properties: 1298 | ServiceToken: !GetAtt LatticeInfoFunction.Arn 1299 | 1300 | # DLQ not needed - CloudFormation manages retries 1301 | # Lambda Function performs error handling 1302 | NATGatewayInfoFunction: 1303 | Type: AWS::Lambda::Function 1304 | Properties: 1305 | FunctionName: !Sub "NATGatewayInfoFunction-${AWS::StackName}" 1306 | Handler: index.lambda_handler 1307 | ReservedConcurrentExecutions: 5 1308 | Role: !GetAtt LambdaBasicExecutionRole.Arn 1309 | Runtime: python3.11 1310 | Timeout: 30 1311 | Environment: 1312 | Variables: 1313 | LOG_LEVEL: INFO 1314 | Code: 1315 | ZipFile: | 1316 | import boto3 1317 | import json 1318 | import logging 1319 | import urllib.request 1320 | from datetime import datetime 1321 | 1322 | logger = logging.getLogger() 1323 | logger.setLevel(logging.INFO) 1324 | 1325 | class DateTimeEncoder(json.JSONEncoder): 1326 | def default(self, obj): 1327 | if isinstance(obj, datetime): 1328 | return obj.isoformat() 1329 | return super().default(obj) 1330 | 1331 | def send_response(event, context, response_status, response_data, physical_resource_id=None, no_echo=False): 1332 | response_url = event['ResponseURL'] 1333 | 1334 | logger.info(f"ResponseURL: {response_url}") 1335 | 1336 | response_body = { 1337 | 'Status': response_status, 1338 | 'Reason': f"See the details in CloudWatch Log Stream: {context.log_stream_name}", 1339 | 'PhysicalResourceId': physical_resource_id or context.log_stream_name, 1340 | 'StackId': event['StackId'], 1341 | 'RequestId': event['RequestId'], 1342 | 'LogicalResourceId': event['LogicalResourceId'], 1343 | 'NoEcho': no_echo, 1344 | 'Data': response_data 1345 | } 1346 | 1347 | json_response_body = json.dumps(response_body, cls=DateTimeEncoder) 1348 | logger.info(f"Response body: {json_response_body}") 1349 | 1350 | headers = { 1351 | 'content-type': '', 1352 | 'content-length': str(len(json_response_body)) 1353 | } 1354 | 1355 | try: 1356 | req = urllib.request.Request(response_url, 1357 | data=json_response_body.encode('utf-8'), 1358 | headers=headers, 1359 | method='PUT') 1360 | response = urllib.request.urlopen(req) 1361 | logger.info(f"Status code: {response.getcode()}") 1362 | return True 1363 | except Exception as e: 1364 | logger.error(f"send_response failed: {str(e)}") 1365 | return False 1366 | 1367 | def lambda_handler(event, context): 1368 | logger.info(f"Received event: {json.dumps(event, cls=DateTimeEncoder)}") 1369 | 1370 | if event['RequestType'] == 'Delete': 1371 | logger.info("Request Type is Delete; sending SUCCESS response") 1372 | send_response(event, context, 'SUCCESS', {}) 1373 | return 1374 | 1375 | try: 1376 | nat_gateway_id = event['ResourceProperties']['NatGatewayId'] 1377 | logger.info(f"Looking up NAT Gateway: {nat_gateway_id}") 1378 | 1379 | ec2 = boto3.client('ec2') 1380 | 1381 | response = ec2.describe_nat_gateways(NatGatewayIds=[nat_gateway_id]) 1382 | logger.info(f"NAT Gateway response: {json.dumps(response, cls=DateTimeEncoder)}") 1383 | 1384 | if not response['NatGateways']: 1385 | raise Exception(f"NAT Gateway {nat_gateway_id} not found") 1386 | 1387 | nat_gateway = response['NatGateways'][0] 1388 | 1389 | if nat_gateway['State'] != 'available': 1390 | raise Exception(f"NAT Gateway {nat_gateway_id} is not available. Current state: {nat_gateway['State']}") 1391 | 1392 | if not nat_gateway['NatGatewayAddresses']: 1393 | raise Exception(f"NAT Gateway {nat_gateway_id} has no addresses") 1394 | 1395 | private_ip = nat_gateway['NatGatewayAddresses'][0]['PrivateIp'] 1396 | logger.info(f"Found private IP: {private_ip}") 1397 | 1398 | send_response(event, context, 'SUCCESS', {'PrivateIp': private_ip}) 1399 | 1400 | except Exception as e: 1401 | logger.error(f"Error: {str(e)}") 1402 | send_response(event, context, 'FAILED', {'Error': str(e)}) 1403 | 1404 | 1405 | 1406 | 1407 | 1408 | NATGW1PrivateIP: 1409 | Type: Custom::NATGatewayInfo 1410 | DependsOn: VPC1NATGW1 1411 | Properties: 1412 | ServiceToken: !GetAtt NATGatewayInfoFunction.Arn 1413 | NatGatewayId: !Ref VPC1NATGW1 1414 | 1415 | NATGW2PrivateIP: 1416 | Type: Custom::NATGatewayInfo 1417 | DependsOn: VPC1NATGW2 1418 | Properties: 1419 | ServiceToken: !GetAtt NATGatewayInfoFunction.Arn 1420 | NatGatewayId: !Ref VPC1NATGW2 1421 | 1422 | NATGW3PrivateIP: 1423 | Type: Custom::NATGatewayInfo 1424 | DependsOn: VPC2NATGW1 1425 | Properties: 1426 | ServiceToken: !GetAtt NATGatewayInfoFunction.Arn 1427 | NatGatewayId: !Ref VPC2NATGW1 1428 | 1429 | NATGW4PrivateIP: 1430 | Type: Custom::NATGatewayInfo 1431 | DependsOn: VPC2NATGW2 1432 | Properties: 1433 | ServiceToken: !GetAtt NATGatewayInfoFunction.Arn 1434 | NatGatewayId: !Ref VPC2NATGW2 1435 | 1436 | 1437 | 1438 | 1439 | # ---------- VPC Lattice Resources ---------- 1440 | ServiceNetwork: 1441 | Type: AWS::VpcLattice::ServiceNetwork 1442 | DeletionPolicy: Delete 1443 | Properties: 1444 | Name: ipv6-day-service-network 1445 | AuthType: AWS_IAM 1446 | Tags: 1447 | - Key: Name 1448 | Value: ipv6-day-service-network 1449 | 1450 | ServiceNetworkAuthPolicy: 1451 | Type: AWS::VpcLattice::AuthPolicy 1452 | DeletionPolicy: Delete 1453 | Properties: 1454 | ResourceIdentifier: !Ref ServiceNetwork 1455 | Policy: 1456 | Version: '2012-10-17' 1457 | Statement: 1458 | - Effect: Allow 1459 | Principal: '*' 1460 | Action: '*' 1461 | Resource: '*' 1462 | 1463 | LatticeApp1SNAssociation: 1464 | Type: AWS::VpcLattice::ServiceNetworkVpcAssociation 1465 | Properties: 1466 | SecurityGroupIds: 1467 | - !Ref VPC1LatticeSecurityGroup 1468 | ServiceNetworkIdentifier: !Ref ServiceNetwork 1469 | VpcIdentifier: !Ref VPC1 1470 | 1471 | LatticeApp2SNAssociation: 1472 | Type: AWS::VpcLattice::ServiceNetworkVpcAssociation 1473 | Properties: 1474 | SecurityGroupIds: 1475 | - !Ref VPC2LatticeSecurityGroup 1476 | ServiceNetworkIdentifier: !Ref ServiceNetwork 1477 | VpcIdentifier: !Ref VPC2 1478 | 1479 | App1ServiceNetworkAssociation: 1480 | Type: AWS::VpcLattice::ServiceNetworkServiceAssociation 1481 | Properties: 1482 | ServiceNetworkIdentifier: !Ref ServiceNetwork 1483 | ServiceIdentifier: !Ref App1 1484 | 1485 | App2ServiceNetworkAssociation: 1486 | Type: AWS::VpcLattice::ServiceNetworkServiceAssociation 1487 | Properties: 1488 | ServiceNetworkIdentifier: !Ref ServiceNetwork 1489 | ServiceIdentifier: !Ref App2 1490 | 1491 | 1492 | App1IPv4TargetGroup: 1493 | Type: AWS::VpcLattice::TargetGroup 1494 | DeletionPolicy: Delete 1495 | Properties: 1496 | Name: app-1-ipv4-targets 1497 | Type: INSTANCE 1498 | Config: 1499 | Protocol: HTTP 1500 | Port: 80 1501 | ProtocolVersion: HTTP1 1502 | VpcIdentifier: !Ref VPC1 1503 | HealthCheck: 1504 | Enabled: false 1505 | Targets: 1506 | - Id: !Ref VPC1IPv4Instance 1507 | Port: 80 1508 | 1509 | App2IPv4TargetGroup: 1510 | Type: AWS::VpcLattice::TargetGroup 1511 | DeletionPolicy: Delete 1512 | Properties: 1513 | Name: app-2-ipv4-targets 1514 | Type: INSTANCE 1515 | Config: 1516 | Protocol: HTTP 1517 | Port: 80 1518 | ProtocolVersion: HTTP1 1519 | VpcIdentifier: !Ref VPC2 1520 | HealthCheck: 1521 | Enabled: false 1522 | Targets: 1523 | - Id: !Ref VPC2IPv4Instance 1524 | Port: 80 1525 | 1526 | App1IPv6TargetGroup: 1527 | Type: AWS::VpcLattice::TargetGroup 1528 | DeletionPolicy: Delete 1529 | Properties: 1530 | Name: app-1-ipv6-targets 1531 | Type: IP 1532 | Config: 1533 | Protocol: HTTP 1534 | Port: 80 1535 | ProtocolVersion: HTTP1 1536 | VpcIdentifier: !Ref VPC1 1537 | IpAddressType: "IPV6" 1538 | HealthCheck: 1539 | Enabled: false 1540 | Targets: 1541 | - Id: !GetAtt CustomIpv6Resource1.Ipv6Address 1542 | Port: 80 1543 | 1544 | App2IPv6TargetGroup: 1545 | Type: AWS::VpcLattice::TargetGroup 1546 | DeletionPolicy: Delete 1547 | Properties: 1548 | Name: app-2-dual-stack-target 1549 | Type: IP 1550 | Config: 1551 | Protocol: HTTP 1552 | Port: 80 1553 | ProtocolVersion: HTTP1 1554 | VpcIdentifier: !Ref VPC2 1555 | IpAddressType: "IPV6" 1556 | HealthCheck: 1557 | Enabled: false 1558 | Targets: 1559 | - Id: !GetAtt CustomIpv6Resource2.Ipv6Address 1560 | Port: 80 1561 | 1562 | App1: 1563 | Type: AWS::VpcLattice::Service 1564 | DeletionPolicy: Delete 1565 | Properties: 1566 | Name: app-1 1567 | AuthType: NONE 1568 | 1569 | App2: 1570 | Type: AWS::VpcLattice::Service 1571 | DeletionPolicy: Delete 1572 | Properties: 1573 | Name: app-2 1574 | AuthType: NONE 1575 | 1576 | App1AccessLogSubscription: 1577 | Type: AWS::VpcLattice::AccessLogSubscription 1578 | DeletionPolicy: Delete 1579 | UpdateReplacePolicy: Delete 1580 | Properties: 1581 | ResourceIdentifier: !Ref App1 1582 | DestinationArn: !GetAtt App1ServiceLogGroup.Arn 1583 | 1584 | App2AccessLogSubscription: 1585 | Type: AWS::VpcLattice::AccessLogSubscription 1586 | DeletionPolicy: Delete 1587 | UpdateReplacePolicy: Delete 1588 | Properties: 1589 | ResourceIdentifier: !Ref App2 1590 | DestinationArn: !GetAtt App2ServiceLogGroup.Arn 1591 | 1592 | 1593 | App1Listener: 1594 | Type: AWS::VpcLattice::Listener 1595 | DeletionPolicy: Delete 1596 | DependsOn: 1597 | - App1IPv4TargetGroup 1598 | - App1IPv6TargetGroup 1599 | Properties: 1600 | ServiceIdentifier: !Ref App1 1601 | Protocol: HTTP 1602 | Port: 80 1603 | DefaultAction: 1604 | Forward: 1605 | TargetGroups: 1606 | - TargetGroupIdentifier: !Ref App1IPv4TargetGroup 1607 | Weight: 100 1608 | 1609 | App2Listener: 1610 | Type: AWS::VpcLattice::Listener 1611 | DeletionPolicy: Delete 1612 | DependsOn: 1613 | - App2IPv4TargetGroup 1614 | - App2IPv6TargetGroup 1615 | Properties: 1616 | ServiceIdentifier: !Ref App2 1617 | Protocol: HTTP 1618 | Port: 80 1619 | DefaultAction: 1620 | Forward: 1621 | TargetGroups: 1622 | - TargetGroupIdentifier: !Ref App2IPv4TargetGroup 1623 | Weight: 100 1624 | 1625 | App1AuthPolicy: 1626 | Type: AWS::VpcLattice::AuthPolicy 1627 | DeletionPolicy: Delete 1628 | Properties: 1629 | ResourceIdentifier: !Ref App1 1630 | Policy: 1631 | Statement: 1632 | - Effect: Allow 1633 | Principal: '*' 1634 | Action: '*' 1635 | Resource: '*' 1636 | 1637 | App2AuthPolicy: 1638 | Type: AWS::VpcLattice::AuthPolicy 1639 | DeletionPolicy: Delete 1640 | Properties: 1641 | ResourceIdentifier: !Ref App2 1642 | Policy: 1643 | Statement: 1644 | - Effect: Allow 1645 | Principal: '*' 1646 | Action: '*' 1647 | Resource: '*' 1648 | 1649 | # ---------- Log Groups ---------- 1650 | VPCFlowLogsGroup: 1651 | Type: AWS::Logs::LogGroup 1652 | DeletionPolicy: Delete 1653 | UpdateReplacePolicy: Delete 1654 | Properties: 1655 | LogGroupName: !Sub "/vpc/VPC-Flow-Logs/${AWS::Region}" 1656 | RetentionInDays: 3 1657 | Tags: 1658 | - Key: Name 1659 | Value: VPC-Flow-Logs 1660 | 1661 | App1ServiceLogGroup: 1662 | Type: AWS::Logs::LogGroup 1663 | DeletionPolicy: Delete 1664 | UpdateReplacePolicy: Delete 1665 | Properties: 1666 | LogGroupName: !Sub "/aws/vpc-lattice/lattice-app-1-lg/${AWS::Region}" 1667 | RetentionInDays: 3 1668 | Tags: 1669 | - Key: Name 1670 | Value: lattice-app-1-lg 1671 | 1672 | App2ServiceLogGroup: 1673 | Type: AWS::Logs::LogGroup 1674 | DeletionPolicy: Delete 1675 | UpdateReplacePolicy: Delete 1676 | Properties: 1677 | LogGroupName: !Sub "/aws/vpc-lattice/lattice-app-2-lg/${AWS::Region}" 1678 | RetentionInDays: 3 1679 | Tags: 1680 | - Key: Name 1681 | Value: lattice-app-2-lg 1682 | 1683 | LatticeServiceLogsGroup: 1684 | Type: AWS::Logs::LogGroup 1685 | DeletionPolicy: Delete 1686 | UpdateReplacePolicy: Delete 1687 | Properties: 1688 | LogGroupName: !Sub "/aws/vpc-lattice/VPC-Lattice-Service-Logs/${AWS::Region}" 1689 | RetentionInDays: 3 1690 | Tags: 1691 | - Key: Name 1692 | Value: VPC-Lattice-Service-Logs 1693 | 1694 | CustomFunctionLogGroup: 1695 | Type: AWS::Logs::LogGroup 1696 | DeletionPolicy: Delete 1697 | UpdateReplacePolicy: Delete 1698 | Properties: 1699 | LogGroupName: !Sub "/aws/lambda/CustomFunction-${AWS::StackName}" 1700 | RetentionInDays: 3 1701 | Tags: 1702 | - Key: Name 1703 | Value: custom-function-logs 1704 | 1705 | LatticeInfoFunctionLogGroup: 1706 | Type: AWS::Logs::LogGroup 1707 | DeletionPolicy: Delete 1708 | UpdateReplacePolicy: Delete 1709 | Properties: 1710 | LogGroupName: !Sub "/aws/lambda/LatticeInfoFunction-${AWS::StackName}" 1711 | RetentionInDays: 3 1712 | Tags: 1713 | - Key: Name 1714 | Value: lattice-info-function-logs 1715 | 1716 | NATGatewayInfoFunctionLogGroup: 1717 | Type: AWS::Logs::LogGroup 1718 | DeletionPolicy: Delete 1719 | UpdateReplacePolicy: Delete 1720 | Properties: 1721 | LogGroupName: !Sub "/aws/lambda/NATGatewayInfoFunction-${AWS::StackName}" 1722 | RetentionInDays: 3 1723 | Tags: 1724 | - Key: Name 1725 | Value: natgateway-info-function-logs 1726 | 1727 | 1728 | Outputs: 1729 | VPCInformation: 1730 | Description: VPC Information 1731 | Value: !Sub | 1732 | VPC1: 1733 | ID: ${VPC1} 1734 | CIDR: 10.1.0.0/16 1735 | IPv6: ${VPC1IPv6CIDR} 1736 | VPC2: 1737 | ID: ${VPC2} 1738 | CIDR: 10.2.0.0/16 1739 | IPv6: ${VPC2IPv6CIDR} 1740 | 1741 | NATGatewayIPs: 1742 | Description: NAT Gateway Private IPs 1743 | Value: !Sub | 1744 | VPC1: 1745 | NATGW1: ${NATGW1PrivateIP.PrivateIp} 1746 | NATGW2: ${NATGW2PrivateIP.PrivateIp} 1747 | VPC2: 1748 | NATGW1: ${NATGW3PrivateIP.PrivateIp} 1749 | NATGW2: ${NATGW4PrivateIP.PrivateIp} 1750 | 1751 | SubnetInformation: 1752 | Description: Subnet Information 1753 | Value: !Sub | 1754 | VPC1 Subnets: 1755 | Public AZ1: ${VPC1PublicSubnet1} 1756 | Public AZ2: ${VPC1PublicSubnet2} 1757 | Private AZ1: ${VPC1IPv4OnlySubnet} 1758 | Private AZ2: ${VPC1IPv6OnlySubnet} 1759 | VPC2 Subnets: 1760 | Public AZ1: ${VPC2PublicSubnet1} 1761 | Public AZ2: ${VPC2PublicSubnet2} 1762 | Private AZ1: ${VPC2IPv4OnlySubnet} 1763 | Private AZ2: ${VPC2DualStackSubnet} 1764 | 1765 | NetworkingResources: 1766 | Description: Networking Resources 1767 | Value: !Sub | 1768 | NAT Gateways: 1769 | VPC1 AZ1: ${VPC1NATGW1} 1770 | VPC1 AZ2: ${VPC1NATGW2} 1771 | VPC2 AZ1: ${VPC2NATGW1} 1772 | VPC2 AZ2: ${VPC2NATGW2} 1773 | Route Tables: 1774 | VPC1 Public: ${VPC1PublicRouteTable} 1775 | VPC1 Private AZ1: ${VPC1IPv4OnlySubnetRouteTable1} 1776 | VPC1 Private AZ2: ${VPC1IPv6OnlySubnetRouteTable2} 1777 | VPC2 Public: ${VPC2PublicRouteTable} 1778 | VPC2 Private AZ1: ${VPC2IPv4OnlySubnetRouteTable1} 1779 | VPC2 Private AZ2: ${VPC2DualStackSubnetRouteTable2} 1780 | 1781 | SecurityGroups: 1782 | Description: Security Group Information 1783 | Value: !Sub | 1784 | VPC1: 1785 | Instance SG: ${VPC1InstanceSecurityGroup} 1786 | Endpoints SG: ${VPC1EndpointsSecurityGroup} 1787 | Lattice SG: ${VPC1LatticeSecurityGroup} 1788 | VPC2: 1789 | Instance SG: ${VPC2InstanceSecurityGroup} 1790 | Endpoints SG: ${VPC2EndpointsSecurityGroup} 1791 | Lattice SG: ${VPC2LatticeSecurityGroup} 1792 | 1793 | EC2Instances: 1794 | Description: EC2 Instance Information 1795 | Value: !Sub | 1796 | VPC1: 1797 | IPv4 Instance: 1798 | ID: ${VPC1IPv4Instance} 1799 | Private IP: ${VPC1IPv4Instance.PrivateIp} 1800 | IPv6 Instance: 1801 | ID: ${VPC1IPv6Instance} 1802 | IPv6: ${CustomIpv6Resource1.Ipv6Address} 1803 | VPC2: 1804 | IPv4 Instance: 1805 | ID: ${VPC2IPv4Instance} 1806 | Private IP: ${VPC2IPv4Instance.PrivateIp} 1807 | Dual Stack Instance: 1808 | ID: ${VPC2DualStackInstance} 1809 | IPv6: ${CustomIpv6Resource2.Ipv6Address} 1810 | 1811 | VPCEndpoints: 1812 | Description: VPC Endpoint Information 1813 | Value: !Sub | 1814 | VPC1: 1815 | SSM: ${VPC1SSMEndpoint} 1816 | SSMMessages: ${VPC1SSMMessagesEndpoint} 1817 | EC2Messages: ${VPC1EC2MessagesEndpoint} 1818 | VPC2: 1819 | SSM: ${VPC2SSMEndpoint} 1820 | SSMMessages: ${VPC2SSMMessagesEndpoint} 1821 | EC2Messages: ${VPC2EC2MessagesEndpoint} 1822 | 1823 | LatticeResources: 1824 | Description: VPC Lattice Resource Information 1825 | Value: !Sub | 1826 | Service Network: ${ServiceNetwork} 1827 | Services: 1828 | Service 1: ${App1} 1829 | Service 2: ${App2} 1830 | VPC Associations: 1831 | VPC1: ${LatticeApp1SNAssociation} 1832 | VPC2: ${LatticeApp2SNAssociation} 1833 | 1834 | SSMConnectCommands: 1835 | Description: SSM Session Manager Connection Commands 1836 | Value: !Sub | 1837 | VPC1: 1838 | IPv4 Instance: aws ssm start-session --target ${VPC1IPv4Instance} 1839 | IPv6 Instance: aws ssm start-session --target ${VPC1IPv6Instance} 1840 | VPC2: 1841 | IPv4 Instance: aws ssm start-session --target ${VPC2IPv4Instance} 1842 | Dual Stack Instance: aws ssm start-session --target ${VPC2DualStackInstance} 1843 | 1844 | LogGroups: 1845 | Description: CloudWatch Log Group Information 1846 | Value: !Sub | 1847 | VPC Flow Logs: ${VPCFlowLogsGroup} 1848 | Lattice Service Logs: ${LatticeServiceLogsGroup} 1849 | --------------------------------------------------------------------------------