Review EC2 instance VPC association

Verify the actual VPC associations of the EC2 instance and subnet, and manage network access explicitly.

Description

EC2 instances are placed in VPC subnets. Omitting the instance subnet can select a default subnet or cause creation to fail, depending on the environment; it does not create an instance outside a VPC.

CloudFormation requires VpcId for AWS::EC2::Subnet. Omitting it is a deployment error. Supplying the VPC association does not automatically disable public addresses or external access.

Potential impact

Missing required VPC references can prevent deployment. An unintended subnet or security group can allow unnecessary connections or interrupt required communication.

Remediation

Connect the subnet’s VpcId and the instance’s subnet reference correctly. Review actual routing, public address assignment and security groups, and restrict access to required clients.

Examples

These excerpts require separate ImageId and KeyName inputs appropriate for the environment. Route-table and security-group settings are omitted.

Before

yaml
Resources:
  VPC:
    Type: AWS::EC2::VPC
    Properties:
      CidrBlock: 10.1.0.0/16
      EnableDnsSupport: true
      EnableDnsHostnames: true
      Tags:
          - Key: Name
            Value:  !Join ['', [!Ref "AWS::StackName", "-VPC" ]]
  InternetGateway:
    Type: AWS::EC2::InternetGateway
    DependsOn: VPC
  AttachGateway:
    Type: AWS::EC2::VPCGatewayAttachment
    Properties:
      VpcId: !Ref VPC
      InternetGatewayId: !Ref InternetGateway
  PublicSubnetA:
    Type: AWS::EC2::Subnet
    Properties:
      CidrBlock: 10.1.10.0/24
      AvailabilityZone: !Select [ 0, !GetAZs ]    # Select the first Availability Zone in the list
      Tags:
          - Key: Name
            Value: !Sub ${AWS::StackName}-Public-A
  Ec2Instance:
    Type: AWS::EC2::Instance
    Properties:
      ImageId: !Ref ImageId
      KeyName: !Ref KeyName
      NetworkInterfaces:
        -   AssociatePublicIpAddress: "true"
            DeviceIndex: 0
            SubnetId: !Ref PublicSubnetA

The required VpcId is missing from PublicSubnetA, so this subnet cannot be created.

After

yaml
Resources:
  VPC:
    Type: AWS::EC2::VPC
    Properties:
      CidrBlock: 10.1.0.0/16
      EnableDnsSupport: true
      EnableDnsHostnames: true
      Tags:
          - Key: Name
            Value:  !Join ['', [!Ref "AWS::StackName", "-VPC" ]]
  InternetGateway:
    Type: AWS::EC2::InternetGateway
    DependsOn: VPC
  AttachGateway:
    Type: AWS::EC2::VPCGatewayAttachment
    Properties:
      VpcId: !Ref VPC
      InternetGatewayId: !Ref InternetGateway
  PublicSubnetA:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref VPC
      CidrBlock: 10.1.10.0/24
      AvailabilityZone: !Select [ 0, !GetAZs ]    # Select the first Availability Zone in the list
      Tags:
          - Key: Name
            Value: !Sub ${AWS::StackName}-Public-A
  Ec2Instance:
    Type: AWS::EC2::Instance
    Properties:
      ImageId: !Ref ImageId
      KeyName: !Ref KeyName
      NetworkInterfaces:
        -   AssociatePublicIpAddress: "true"
            DeviceIndex: 0
            SubnetId: !Ref PublicSubnetA

This associates the subnet with VPC. AssociatePublicIpAddress remains true, so the example does not switch to private placement. Actual external connectivity also depends on routes and security groups.

References