Open menu
-->

EC2 Instance Not In Public Subnet

Cloud Conformity allows you to automate the auditing process of this resolution page. Register for a 14 day evaluation and check your compliance level for free!

Start a Free Trial Product features
Last updated: 03 December 2016
Security

Risk level: High (not acceptable risk)

Ensure that no backend EC2 instances are provisioned in public subnets in order to protect them from exposure to the Internet. In this context, backend instances are EC2 instances that do not require direct access to the public internet such as database, API or caching servers. As best practice, all EC2 instances that are not Internet-facing should run within a private subnet, behind a NAT gateway that allows downloading software updates and implementing security patches or accessing other AWS resources like SQS and SNS.

This rule resolution is part of the Cloud Conformity Security Package

By provisioning EC2 instances within a private subnet (logically isolated section of VPC) you will prevent these instances from receiving inbound traffic initiated by someone on the Internet, therefore have a stronger guarantee that no malicious requests can reach your backend instances. Note: For this rule Cloud Conformity assumes that your EC2 instances are running within a VPC that has both public and private subnets.

Audit

To determine if your backend EC2 instances are running within AWS VPC public subnets, perform the following:

Using AWS Console

01 Sign in to the AWS Management Console.

02 Navigate to EC2 dashboard at https://console.aws.amazon.com/ec2/.

03 In the left navigation panel, under INSTANCES section, choose Instances.

04 Select the backend EC2 instance that you want to examine.

05 Select the Description tab from the dashboard bottom panel.

06 In the left column, identify the Subnet ID attribute and copy its value.

07 Now navigate to AWS VPC dashboard at https://console.aws.amazon.com/vpc/.

08 In the navigation panel, under Virtual Private Cloud section, choose Subnets.

09 Paste the subnet ID copied at step no. 6 in the dashboard search box, e.g.

Paste the subnet ID copied at step no. 6 in the dashboard search box

then press Enter.

10 Select the VPC subnet returned as result and click the Route Table tab from the dashboard bottom panel. If the route table contains any entries with the destination CIDR block set to 0.0.0.0/0 or with an Internet Gateway (e.g. igw-xxxxxxxx) attached:

 If the route table contains any entries with the destination CIDR block set to 0.0.0.0/0 or with an Internet Gateway

the selected backend instance was provisioned inside a public subnet, therefore is not running within a logically isolated environment that provides full protection.

11 Repeat steps no. 4 – 10 to check the subnet type for other backend EC2 instances provisioned in the current region.

12 Change the AWS region from the navigation bar and repeat the audit process for other regions.

Using AWS CLI

01 Run describe-instances command (OSX/Linux/UNIX) using appropriate filtering to list the IDs of all EC2 instances currently available in the selected region:

aws ec2 describe-instances
	--region us-east-1
	--output table
	--query 'Reservations[*].Instances[*].InstanceId'

02The command output should return a table with the requested instance IDs:

-------------------------
|   DescribeInstances   |
+-----------------------+
|  i-0d02069ea8a2909ba  |
|  i-04b4a39942208510e  |
|  i-081d01b9c55f55ca8  |
+-----------------------+

03 Run again describe-instances command (OSX/Linux/UNIX) using the ID of your backend instance returned at the previous step and custom query filters to expose the selected instance subnet identifier:

aws ec2 describe-instances
	--region us-east-1
	--instance-ids i-0d02069ea8a2909ba
	--query 'Reservations[*].Instances[*].SubnetId[]'

04 The command output should return the backend instance subnet ID:

[
    "subnet-c890fe81"
]

05 Run describe-route-tables command (OSX/Linux/UNIX) using the ID of the subnet returned at the previous step as filter parameter to describe the routes of the VPC route table associated with the selected subnet:

aws ec2 describe-route-tables
	--region us-east-1
	--filters "Name=association.subnet-id,Values=subnet-c890fe81"
	--query 'RouteTables[*].Routes[]'

06 The command output should return the backend instance subnet ID:

[
    {
        "GatewayId": "local",
        "DestinationCidrBlock": "10.0.0.0/16",
        "State": "active",
        "Origin": "CreateRouteTable"
    },
    {
        "GatewayId": "igw-630ab104",
        "DestinationCidrBlock": "0.0.0.0/0",
        "State": "active",
        "Origin": "CreateRoute"
    }
]

Check the GatewayId and DestinationCidrBlock attributes values returned in the output. If the route table contains any entries with the GatewayId value set to igw-xxxxxxxx or the DestinationCidrBlock value set to 0.0.0.0/0, the selected backend instance was provisioned inside a public subnet, therefore is not running within a logically isolated environment and does not adhere to AWS security best practices.

07 Repeat steps no. 3 - 6 to check the subnet type for other backend EC2 instances provisioned in the current region.

08 Change the AWS region by updating the --region command parameter value and repeat steps no. 1 - 7 to perform the audit process for other regions.

Remediation / Resolution

To move your backend EC2 instances from public subnets to private subnets, you must re-launch these instances within the right subnets. To implement the instance(s) migration, perform the following:

Using AWS Console

01 Sign in to the AWS Management Console.

02 Create an image of the backend EC2 instance that you want to migrate. To instantiate the Amazon Machine Image (AMI), perform the following:

  1. Navigate to EC2 dashboard at https://console.aws.amazon.com/ec2/.
  2. In the left navigation panel, under INSTANCES section, choose Instances.
  3. Select the backend instance that you want to move to the private subnet (see the Audit section part I section to identify the right resource).
  4. Click the Actions dropdown button from the dashboard top menu, select Image and click Create Image.
  5. Inside Create Image dialog box, provide the following information:
    • Enter a name for the new AMI in the Image Name box.
    • In the Image description box, provide a description that reflects the usage of the EC2 instance selected.
    • Leave No reboot option unchecked so the AWS can guarantee the file system integrity for the new image.
  6. Click Create Image to submit the request to create the image. Click Close to return to the EC2 dashboard. The AMI creation may take few minutes. Once the process is complete the image status should change from pending to available.

03 Once the Amazon Machine Image is ready, use it to (re)launch the selected backend instance within your VPC private subnet. To launch the instance, perform the following actions:

  1. In the navigation panel, under INSTANCES section, select Instances.
  2. Click the Launch Instance button from the EC2 dashboard top menu to initiate the process.
  3. On the Choose an Amazon Machine Image (AMI) page, choose My AMIs tab then select the AMI created at step no. 2.
  4. On the Choose an Instance Type page, select the same instance type used then click Next: Configure Instance Details button.
  5. On the Configure Instance Details page, select the private subnet that you want to use from the Subnet dropdown list and configure any other options available on the page based on your running backend instance attributes. Click Next: Add Storage and go through the next pages until you reach the Configure Security Group page, without changing any configuration.
  6. On the Configure Security Groups, choose Select an existing security group and select the security group of the existing backend instance (i.e. the one running in the public subnet). Click the Review and Launch button, review your new instance configuration details and click Launch.
  7. In the Select an existing key pair or create a new key pair dialog box, select Choose an existing key pair and use the same key pair as the running backend EC2 instance. Check I acknowledge that I have access to the selected private key file option then click Launch Instances.
  8. Click View Instances to return to the Instances page. The new instance will have the same data and configuration (except the associated subnet) as the old backend instance.

04 Once you have verified and tested the new instance, it is safe to terminate the old backend EC2 instance in order to stop incurring charges for it. To shut down the instance, perform the following:

  1. In the navigation panel, under INSTANCES section, select Instances.
  2. Select the backend instance that you want to terminate.
  3. Click the Actions dropdown button from the dashboard top menu, select Instance State and click Terminate.
  4. In the Terminate Instances confirmation box, review the instance details then click Yes, Terminate.

05 Repeat steps no. 2 – 4 to migrate other backend EC2 instances to your VPC private subnets, available in the current region.

06 Change the AWS region from the navigation bar and repeat the audit process for other regions.

Using AWS CLI

01 Run describe-instances command (OSX/Linux/UNIX) to list the running backend instance metadata. The metadata will be useful later when this instance will be recreated within a private subnet:

aws ec2 describe-instances
	--region us-east-1
	--instance-ids i-0d02069ea8a2909ba
	--query 'Reservations[*].Instances[*].[KeyName,InstanceType,SecurityGroups]'

02 The command output should return the running/existing EC2 instance metadata requested:

[
    "MySSHKeyPair",
    "m3.medium",
    [
        {
            "GroupName": "MyDBInstanceSG",
            "GroupId": "sg-b402c9c9"
        }
    ]
]

03 Now run create-image command (OSX/Linux/UNIX) to create an image from your existing backend EC2 instance. Include the –no-reboot command parameter to guarantee the file system integrity for your new AMI:

aws ec2 create-image
	--region us-east-1
	--instance-id i-0d02069ea8a2909ba
	--name "AMI for EC2 backend instance created within VPC public subnet"
	--description "Internal App Database AMI ver. 1.0"
	--no-reboot

04 The command output should return the new Amazon Machine Image (AMI) ID:

{
    "ImageId": "ami-c45eg8ab"
}

05 Execute run-instances command (OSX/Linux/UNIX) to launch the EC2 instance from the image created at the previous step. The following command example (re)creates an m3.medium backend EC2 instance using an AMI with the ID ami-c45eg8ab inside a private subnet with the ID subnet-19e7cc6f (see the Audit section part II section to identify the right subnet in your VPC):

aws ec2 run-instances
	--region us-east-1
	--image-id ami-c45eg8ab
	--subnet-id subnet-19e7cc6f
	--count 1
	--instance-type m3.medium
	--key-name MySSHKeyPair
	--security-groups MyDBInstanceSG

06 The command output should return the new EC2 instance configuration metadata (including the ID of the private subnet in which was launched - highlighted):

{
    "OwnerId": "012345678910",
    "ReservationId": "r-0467f3f325b4b5ed2",
    "Groups": [],
    "Instances": [
        {
            "EbsOptimized": false,
            "LaunchTime": "2016-11-23T09:57:13.000Z",
            "PrivateIpAddress": "172.31.4.175",
            "VpcId": "vpc-2fb56548",
            "StateTransitionReason": "",
            "InstanceId": "i-01bea9f4bfeac80ed",
            "ImageId": "ami-c45eg8ab",
            "PrivateDnsName": "ip-172-31-4-175.ec2.internal",
            "KeyName": "MySSHKeyPair",
            "SecurityGroups": [
                {
                    "GroupName": "default",
                    "GroupId": "sg-b402c9c9"
                }
            ],
            "ClientToken": "",
            "SubnetId": "subnet-19e7cc6f",
            "InstanceType": "m3.medium",

            ...


            "SourceDestCheck": true,
            "Placement": {
                "Tenancy": "default",
                "GroupName": "",
                "AvailabilityZone": "us-east-1a"
            },
            "Hypervisor": "xen",
            "BlockDeviceMappings": [],
            "Architecture": "x86_64",
            "StateReason": {
                "Message": "pending",
                "Code": "pending"
            },
            "RootDeviceName": "/dev/xvda",
            "VirtualizationType": "hvm",
            "AmiLaunchIndex": 0
        }
    ]
}

07 Once you have verified that your new backend EC2 instance is working 100% within the private subnet, you should terminate the old instance to stop incurring charges for the resource. To terminate the EC2 old running instance run terminate-instances command (OSX/Linux/UNIX) using the instance ID as identifier:

aws ec2 terminate-instances
	--instance-ids i-0d02069ea8a2909ba

08 The command output should return the shutdown request metadata:

{
    "TerminatingInstances": [
        {
            "InstanceId": "i-0d02069ea8a2909ba",
            "CurrentState": {
                "Code": 32,
                "Name": "shutting-down"
            },
            "PreviousState": {
                "Code": 16,
                "Name": "running"
            }
        }
    ]
}

09 Repeat steps no. 1 - 8 to migrate other backend EC2 instances to your VPC private subnets, available in the current region.

10 Change the AWS region by updating the --region command parameter value and repeat steps no. 1 - 9 to perform the audit process for other regions.

References

Publication date Dec 3, 2016