> ## Documentation Index
> Fetch the complete documentation index at: https://cloudanix.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Ec2 not in public subnet remediation

### Triage and Remediation

<Tabs>
  <Tab title="Remediation">
    ### Remediation

    <AccordionGroup>
      <Accordion title="Using Console" defaultOpen="true">
        To remediate the EC2 instance in a public subnet in AWS, follow these steps:

        1. Open the AWS Management Console and navigate to the VPC dashboard.

        2. Select the VPC containing the public subnet that the EC2 instance is in.

        3. Select the Subnets tab and then select the public subnet that the EC2 instance is in.

        4. Select the Route Table tab and then select the route table associated with the public subnet.

        5. Remove the route that allows traffic to the internet gateway. This will prevent any traffic from the internet from reaching the EC2 instance.

        6. Create a new route table and associate it with the public subnet.

        7. Add a route to the new route table that allows traffic to reach the internet gateway. This will allow any traffic from the EC2 instance to reach the internet.

        8. Launch a new EC2 instance in a private subnet and associate it with the new route table. This will ensure that the EC2 instance is not accessible from the internet.

        9. Terminate the old EC2 instance in the public subnet.

        By following these steps, you can remediate the misconfiguration of having an EC2 instance in a public subnet in AWS.

        #
      </Accordion>

      <Accordion title="Using CLI">
        To remediate the misconfiguration of having an EC2 instance in a public subnet in AWS using AWS CLI, follow these steps:

        1. Identify the public subnet in which the EC2 instance is running. You can do this by checking the subnet's route table and confirming that it has a route to an Internet Gateway.

        2. Create a new private subnet in the same VPC as the public subnet. This new subnet should have a non-overlapping CIDR block and should not have a route to an Internet Gateway.

        3. Stop the EC2 instance that is running in the public subnet.

        4. Modify the instance's network interface to move it from the public subnet to the new private subnet. You can do this using the following command:

        ```
        aws ec2 modify-network-interface-attribute --network-interface-id <network-interface-id> --subnet-id <new-private-subnet-id>
        ```

        Replace `<network-interface-id>` with the ID of the network interface attached to the EC2 instance, and `<new-private-subnet-id>` with the ID of the new private subnet you created.

        5. Start the EC2 instance.

        6. Verify that the EC2 instance now has a private IP address in the new private subnet and does not have a public IP address. You can do this by checking the instance's network interface settings.
      </Accordion>

      <Accordion title="Using Python">
        To remediate the misconfiguration of an EC2 instance in a public subnet in AWS using Python, you can follow the below steps:

        1. First, you need to identify the EC2 instances that are in the public subnet. You can do this by using the `describe_instances` method of the `boto3` library in Python.

        ```python theme={null}
        import boto3

        ec2 = boto3.client('ec2')

        response = ec2.describe_instances(
            Filters=[
                {
                    'Name': 'subnet-id',
                    'Values': [
                        'subnet-0123456789abcdef0',
                    ]
                },
            ]
        )

        for reservation in response['Reservations']:
            for instance in reservation['Instances']:
                print(instance['InstanceId'])
        ```

        Replace the `subnet-id` with the ID of the public subnet.

        2. Once you have identified the instances, you need to move them to a private subnet. To do this, you can modify the network interface of the instance and attach it to a private subnet. You can use the `modify_network_interface_attribute` method of the `boto3` library to do this.

        ```python theme={null}
        import boto3

        ec2 = boto3.client('ec2')

        response = ec2.modify_network_interface_attribute(
            NetworkInterfaceId='eni-0123456789abcdef0',
            Groups=[
                'sg-0123456789abcdef0',
            ],
            Description={
                'Value': 'Modified description'
            }
        )

        print(response)
        ```

        Replace the `NetworkInterfaceId` with the ID of the network interface of the instance that you want to modify. Also, replace the `sg-0123456789abcdef0` with the ID of the security group that you want to attach to the network interface.

        3. After modifying the network interface, you need to verify that the instance is now in the private subnet. You can do this by checking the `SubnetId` attribute of the instance using the `describe_instances` method.

        ```python theme={null}
        import boto3

        ec2 = boto3.client('ec2')

        response = ec2.describe_instances(
            InstanceIds=[
                'i-0123456789abcdef0',
            ],
        )

        for reservation in response['Reservations']:
            for instance in reservation['Instances']:
                print(instance['SubnetId'])
        ```

        Replace the `i-0123456789abcdef0` with the ID of the instance that you want to check.

        By following these steps, you can remediate the misconfiguration of an EC2 instance in a public subnet in AWS using Python.
      </Accordion>

      <Accordion title="Using Terraform">
        ```hcl theme={null}
        resource "aws_instance" "backend" {
          ami                    = "AMI_ID"                  # replace with a valid AMI ID
          instance_type          = "INSTANCE_TYPE"           # e.g., t3.micro
          subnet_id              = aws_subnet.private.id     # move instance into a PRIVATE subnet
          vpc_security_group_ids = [aws_security_group.backend.id]

          # Ensure no public IP is assigned in the private subnet
          associate_public_ip_address = false

          tags = {
            Name = "BACKEND_INSTANCE_NAME"
          }
        }

        resource "aws_subnet" "private" {
          vpc_id                  = aws_vpc.main.id
          cidr_block              = "PRIVATE_CIDR_BLOCK"      # e.g., 10.0.2.0/24
          map_public_ip_on_launch = false                     # do not auto-assign public IPs

          tags = {
            Name = "PRIVATE_SUBNET_NAME"
          }
        }

        resource "aws_route_table" "private" {
          vpc_id = aws_vpc.main.id

          # Route outbound traffic to a NAT gateway, not an Internet Gateway
          route {
            cidr_block     = "0.0.0.0/0"
            nat_gateway_id = aws_nat_gateway.private.id
          }

          tags = {
            Name = "PRIVATE_ROUTE_TABLE_NAME"
          }
        }

        resource "aws_route_table_association" "private" {
          subnet_id      = aws_subnet.private.id
          route_table_id = aws_route_table.private.id
        }

        resource "aws_nat_gateway" "private" {
          allocation_id = aws_eip.nat.id
          subnet_id     = aws_subnet.public.id  # NAT gateway lives in a public subnet

          tags = {
            Name = "NAT_GATEWAY_NAME"
          }
        }

        resource "aws_eip" "nat" {
          domain = "vpc"
        }

        resource "aws_subnet" "public" {
          vpc_id                  = aws_vpc.main.id
          cidr_block              = "PUBLIC_CIDR_BLOCK"       # e.g., 10.0.1.0/24
          map_public_ip_on_launch = true

          tags = {
            Name = "PUBLIC_SUBNET_NAME"
          }
        }

        resource "aws_internet_gateway" "igw" {
          vpc_id = aws_vpc.main.id

          tags = {
            Name = "IGW_NAME"
          }
        }

        resource "aws_route_table" "public" {
          vpc_id = aws_vpc.main.id

          route {
            cidr_block = "0.0.0.0/0"
            gateway_id = aws_internet_gateway.igw.id
          }

          tags = {
            Name = "PUBLIC_ROUTE_TABLE_NAME"
          }
        }

        resource "aws_route_table_association" "public" {
          subnet_id      = aws_subnet.public.id
          route_table_id = aws_route_table.public.id
        }

        resource "aws_vpc" "main" {
          cidr_block           = "VPC_CIDR_BLOCK"            # e.g., 10.0.0.0/16
          enable_dns_support   = true
          enable_dns_hostnames = true

          tags = {
            Name = "VPC_NAME"
          }
        }
        ```

        * The key changes that remediate the finding are:
          * `aws_instance.backend` is placed in `aws_subnet.private` (a subnet without a route to an Internet Gateway).
          * `associate_public_ip_address = false` and `aws_subnet.private.map_public_ip_on_launch = false`, so the instance cannot get a public IP.

        This change of `subnet_id` on an existing `aws_instance` forces replacement of the instance, which will cause downtime unless you handle a blue/green or rolling deployment.

        For verification, `terraform plan` should show the existing `aws_instance` resource being destroyed and a new one created in the private subnet, and it should not show any public IP being associated with that instance.
      </Accordion>
    </AccordionGroup>
  </Tab>
</Tabs>
