Use the Conformity Knowledge Base AI to help improve your Cloud Posture

Disable Public IP Address Assignment for EC2 Instances

Trend Cloud One™ – Conformity is a continuous assurance tool that provides peace of mind for your cloud infrastructure, delivering over 1000 automated best practice checks.

Risk Level: High (not acceptable risk)

Ensure that Amazon EC2 instances such as backend instances are not using public IP addresses in order to prevent Internet exposure. Backend instances are EC2 instances that run behind a load balancer and do not need direct access to the Internet, therefore do not require public IP addresses.

This rule can help you work with the AWS Well-Architected Framework.

Security
Reliability
Performance
efficiency

Amazon EC2 instances should not get public IP addresses at launch in order to enhance security by reducing the attack surface. Instead, they should be placed in private VPC subnets and accessed through the associated load balancer. This setup ensures that incoming traffic is tightly controlled and monitored.


Audit

To determine if your Amazon EC2 instances use public IP addresses, perform the following operations:

Using AWS Console

01 Sign in to the AWS Management Console.

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

03 In the navigation panel, under Instances, choose Instances.

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

05 Choose the Details tab from the console bottom panel to access the instance configuration details.

06 In the Instance summary section, check the Public IPv4 address configuration attribute value. If the Public IPv4 address attribute value is set to an IPv4 address, the selected Amazon EC2 instance is using a public IP address that is reachable from the Internet.

07 Repeat steps no. 4 – 6 for each Amazon EC2 instance that you want to examine available within the current AWS region.

08 Change the AWS cloud region from the navigation bar and repeat the Audit process for other regions.

Using AWS CLI

01 Run describe-instances command (OSX/Linux/UNIX) with custom query filters to list the ID of each Amazon EC2 instance provisioned in the selected AWS region:

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

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

-------------------------
|   DescribeInstances   |
+-----------------------+
|  i-01234abcd1234abcd  |
|  i-0abcabcabc1234567  |
|  i-01234567abcabcabc  |
+-----------------------+

03 Run describe-instances command (OSX/Linux/UNIX) using the ID of the Amazon EC2 instance that you want to examine as the identifier parameter and custom query filters to determine whether the selected EC2 instance is associated with a public or an Elastic IP address:

aws ec2 describe-instances
  --region us-east-1
  --instance-ids i-01234abcd1234abcd
  --query "Reservations[*].Instances[*].NetworkInterfaces[*].Association.IpOwnerId[] | []"

04 The command output should return an empty array – if the verified instance has no public IP address assigned, "amazon" – if the instance has a public IP address, or the AWS account ID of the owner – if the selected instance is associated with an Elastic IP address:

[
	"amazon"
]

If the describe-instances command output returns an AWS account ID or "amazon" (as shown in the output example above), the selected backend Amazon EC2 instance is using a public or an Elastic IP address that is reachable from the Internet.

05 Repeat steps no. 3 and 4 for each Amazon EC2 instance that you want to examine, available in the selected AWS region.

06 Change the AWS cloud region by updating the --region command parameter value and repeat steps no. 1 – 5 to perform the Audit process for other regions.

Remediation / Resolution

To disable public IP address assignment for your existing Amazon EC2 instances, you have to re-create your EC2 instances with the appropriate configuration. To relaunch your Amazon EC2 instances, perform the following operations:

Using AWS Console

01 Sign in to the AWS Management Console.

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

03 In the navigation panel, under Instances, choose Instances.

04 Select the Amazon EC2 instance that you want to re-create.

05 Click on the Actions dropdown menu from the console top menu, select Image and templates, and choose Create image.

06 On the Create image setup page, provide the following information:

  1. In the Image name box, enter a unique name for the new AMI.
  2. (Optional) In the Image description - optional box, provide a short description that reflects the usage of the selected EC2 instance.
  3. Deselect Enable under No reboot so that Amazon EC2 service can guarantee the file system integrity for the new AMI.
  4. (Optional) For Tags, choose Tag image and snapshots together and use the Add new tag button to create and apply user-defined tags to the new image.
  5. Choose Create image to create your new AMI.

07 Once the new image is ready, use it to relaunch your Amazon EC2 instance without assigning a public IP address. On the Instances listing page, choose Launch instances and perform the following actions:

  1. For Name and tags, provide a name (tag) for your new Amazon EC2 instance in the Name box. (Optional) Choose Add additional tags to add and apply user-defined tags to the new instance.
  2. For Application and OS Images (Amazon Machine Image), choose Browse more AMIs, select My AMIs tab, and select the Amazon Machine Image (AMI) created at step no. 6.
  3. For Instance type, select the required instance type (must match the instance type used by the source, non-compliant instance).
  4. For Key pair (login), select the required SSH key from the Key pair name - required dropdown list.
  5. For Network settings, choose Edit, and perform the following actions:
    • Select the VPC and the VPC subnet that you want to use from the VPC - required and Subnet dropdown lists. You can also choose Create new subnet to create a new VPC subnet.
    • Select Disable from the Auto-assign public IP dropdown list to launch the new EC2 instance without a public IP address.
    • Choose Select existing security group, and select the necessary security group(s) from the Common security groups list.
  6. For Configure storage, configure the storage device settings, then click Next: Add Tags to set up the instance tags.
  7. Choose Advanced details and configure the identity management, behavior, and metadata settings. The new instance configuration must match the source, non-compliant instance configuration.
  8. For Summary, review your instance configuration details, then choose Launch instance to launch your new Amazon EC2 instance.
  9. Choose View all instances to return to the Instances page.

08 (Optional) Once the new Amazon EC2 instance is provisioned, you can terminate the source, non-compliant instance in order to stop adding charges for that resource. To shut down the required instance, perform the following actions:

  1. In the navigation panel, under Instances, choose Instances.
  2. Select the Amazon EC2 instance that you want to terminate.
  3. Choose Instance state and select Terminate instance.
  4. In the Terminate instance? confirmation box, review the instance details, then choose Terminate to shut down the selected EC2 instance.

09 Repeat steps no. 4 – 8 for each Amazon EC2 instance that you want to relaunch, available within the current AWS region.

10 Change the AWS cloud region from the navigation bar and repeat the Remediation process for other regions.

Using AWS CLI

01 Run describe-instances command (OSX/Linux/UNIX) to list the configuration information available for the Amazon EC2 instance that you want to re-create:

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

02 The command output should return an array with the requested configuration information:

[
	{
		"AmiLaunchIndex": 0,
		"ImageId": "ami-0abcd1234abcd1234",
		"InstanceId": "i-01234abcd1234abcd",
		"InstanceType": "t2.micro",
		"KeyName": "admin-ssh-key",
		"LaunchTime": "2021-03-10T10:00:00+00:00",
		"Monitoring": {
			"State": "disabled"
		},
		"Placement": {
			"AvailabilityZone": "us-east-1a",
			"GroupName": "",
			"Tenancy": "default"
		},
		"PrivateDnsName": "ip-10-0-0-15.ec2.internal",
		"PrivateIpAddress": "10.0.0.15",
		"ProductCodes": [],
		"PublicDnsName": "ec2-10-0-1-20.compute-1.amazonaws.com",
		"PublicIpAddress": "10.0.1.20",
		"State": {
			"Code": 16,
			"Name": "running"
		},
		"StateTransitionReason": "",
		"SubnetId": "subnet-abcd1234",
		"VpcId": "vpc-1234abcd",
		"Architecture": "x86_64",
		"BlockDeviceMappings": [
			{
				"DeviceName": "/dev/xvda",
				"Ebs": {
					"AttachTime": "2021-03-10T10:00:00+00:00",
					"DeleteOnTermination": true,
					"Status": "attached",
					"VolumeId": "vol-0abcd1234abcd1234"
				}
			}
		],
		"ClientToken": "",
		"EbsOptimized": false,
		"EnaSupport": true,
		"Hypervisor": "xen",
		"IamInstanceProfile": {
			"Arn": "arn:aws:iam::123456789012:instance-profile/ec2-manager-role",
			"Id": "ABCDABCDABCDABCDABCDA"
		},
		"NetworkInterfaces": [
			{
				"Association": {
					"IpOwnerId": "amazon",
					"PublicDnsName": "ec2-10-0-1-20.compute-1.amazonaws.com",
					"PublicIp": "10.0.1.20"
				},
				"Attachment": {
					"AttachTime": "2021-03-10T10:00:00+00:00",
					"AttachmentId": "eni-attach-0abcd1234abcd1234",
					"DeleteOnTermination": true,
					"DeviceIndex": 0,
					"Status": "attached",
					"NetworkCardIndex": 0
				},
				"Description": "Primary network interface",
				"Groups": [
					{
						"GroupName": "cc-prod-security-group",
						"GroupId": "sg-01234abcd1234abcd"
					}
				],
				"Ipv6Addresses": [],
				"MacAddress": "0e:53:19:7b:62:6b",
				"NetworkInterfaceId": "eni-0abcd1234abcd1234",
				"OwnerId": "123456789012",
				"PrivateDnsName": "ip-10-0-0-15.ec2.internal",
				"PrivateIpAddress": "10.0.0.15",
				"PrivateIpAddresses": [
					{
						"Association": {
							"IpOwnerId": "amazon",
							"PublicDnsName": "ec2-10-0-1-20.compute-1.amazonaws.com",
							"PublicIp": "10.0.1.20"
						},
						"Primary": true,
						"PrivateDnsName": "ip-10-0-0-15.ec2.internal",
						"PrivateIpAddress": "10.0.0.15"
					}
				],
				"SourceDestCheck": true,
				"Status": "in-use",
				"SubnetId": "subnet-abcd1234",
				"VpcId": "vpc-1234abcd",
				"InterfaceType": "interface"
			}
		],
		"RootDeviceName": "/dev/xvda",
		"RootDeviceType": "ebs",
		"SecurityGroups": [
			{
				"GroupName": "cc-prod-security-group",
				"GroupId": "sg-01234abcd1234abcd"
			}
		],
		"SourceDestCheck": true,
		"VirtualizationType": "hvm",
		"CpuOptions": {
			"CoreCount": 2,
			"ThreadsPerCore": 4
		},
		"CapacityReservationSpecification": {
			"CapacityReservationPreference": "open"
		},
		"HibernationOptions": {
			"Configured": false
		},
		"MetadataOptions": {
			"State": "applied",
			"HttpTokens": "optional",
			"HttpPutResponseHopLimit": 1,
			"HttpEndpoint": "enabled"
		},
		"EnclaveOptions": {
			"Enabled": false
		}
	}
]

03 Run create-image command (OSX/Linux/UNIX) to create an image from your source 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-01234abcd1234abcd
  --name "EC2 Instance AMI"
  --description "Web Stack Instance AMI"
  --no-reboot

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

{
	"ImageId": "ami-0abcdabcdabcdabcd"
}

05 Execute run-instances command (OSX/Linux/UNIX) to launch a new Amazon EC2 instance from the AMI created at the previous steps. Use the information returned at step no. 2 for the instance configuration parameters. Include the --no-associate-public-ip-address parameter in the command request to prevent assigning a public IPv4 address to the new EC2 instance:

aws ec2 run-instances
  --region us-east-1
  --image-id ami-0abcdabcdabcdabcd
  --count 1
  --instance-type t2.micro
  --key-name admin-ssh-key
  --security-group-ids sg-01234abcd1234abcd
  --subnet-id subnet-0abcd1234abcd1234
  --no-associate-public-ip-address

06 The command output should return the configuration information for the newly created EC2 instance:

{
	"Groups": [],
	"Instances": [
		{
			"AmiLaunchIndex": 0,
			"ImageId": "ami-0abcdabcdabcdabcd",
			"InstanceId": "i-01234123412341234",
			"InstanceType": "t2.micro",
			"KeyName": "admin-ssh-key",
			"LaunchTime": "2021-03-22T17:29:43+00:00",
			"Monitoring": {
				"State": "disabled"
			},
			"Placement": {
				"AvailabilityZone": "us-east-1e",
				"GroupName": "",
				"Tenancy": "default"
			},
			"PrivateDnsName": "ip-10-0-0-5.ec2.internal",
			"PrivateIpAddress": "10.0.0.5",
			"ProductCodes": [],
			"PublicDnsName": "",
			"State": {
				"Code": 0,
				"Name": "pending"
			},
			"StateTransitionReason": "",
			"SubnetId": "subnet-0abcd1234abcd1234",
			"VpcId": "vpc-1234abcd",
			"Architecture": "x86_64",
			"BlockDeviceMappings": [],
			"EbsOptimized": false,
			"EnaSupport": true,
			"Hypervisor": "xen",
			"IamInstanceProfile": {
				"Arn": "arn:aws:iam::123456789012:instance-profile/ec2-manager-role",
				"Id": "ABCDABCDABCDABCDABCD"
			},
			"NetworkInterfaces": [
				{
					"Attachment": {
						"AttachTime": "2021-03-22T17:29:43+00:00",
						"AttachmentId": "eni-attach-0abcd1234abcd1234",
						"DeleteOnTermination": true,
						"DeviceIndex": 0,
						"Status": "attaching",
						"NetworkCardIndex": 0
					},
					"Description": "",
					"Groups": [
						{
							"GroupName": "cc-prod-security-group",
							"GroupId": "sg-01234abcd1234abcd"
						}
					],
					"Ipv6Addresses": [],
					"MacAddress": "06:00:c7:12:51:99",
					"NetworkInterfaceId": "eni-0abcd1234abcd1234",
					"OwnerId": "123456789012",
					"PrivateDnsName": "ip-10-0-0-5.ec2.internal",
					"PrivateIpAddress": "10.0.0.5",
					"PrivateIpAddresses": [
						{
							"Primary": true,
							"PrivateDnsName": "ip-10-0-0-5.ec2.internal",
							"PrivateIpAddress": "10.0.0.5"
						}
					],
					"SourceDestCheck": true,
					"Status": "in-use",
					"SubnetId": "subnet-abcdabcd",
					"VpcId": "vpc-1234abcd",
					"InterfaceType": "interface"
				}
			],
			"RootDeviceName": "/dev/xvda",
			"RootDeviceType": "ebs",
			"SecurityGroups": [
				{
					"GroupName": "cc-prod-security-group",
					"GroupId": "sg-01234abcd1234abcd"
				}
			],
			"SourceDestCheck": true,
			"StateReason": {
				"Code": "pending",
				"Message": "pending"
			},
			"VirtualizationType": "hvm",
			"CpuOptions": {
				"CoreCount": 1,
				"ThreadsPerCore": 1
			},
			"CapacityReservationSpecification": {
				"CapacityReservationPreference": "open"
			},
			"MetadataOptions": {
				"State": "pending",
				"HttpTokens": "optional",
				"HttpPutResponseHopLimit": 1,
				"HttpEndpoint": "enabled"
			},
			"EnclaveOptions": {
				"Enabled": false
			}
		}
	],
	"OwnerId": "123456789012",
	"ReservationId": "r-0abcd1234abcd1234"
}

07 (Optional) Once the new Amazon EC2 instance is launched, you can terminate the source, non-compliant instance in order to stop adding charges for that resource. To shut down the required instance, run terminate-instances command (OSX/Linux/UNIX) using the instance ID as the identifier parameter:

aws ec2 terminate-instances
  --instance-ids i-01234abcd1234abcd

08 The output should return the ter**minate-instances** command request information:

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

09 Repeat steps no. 1 – 8 for each Amazon EC2 instance that you want to re-create, available in the selected AWS region.

10 Change the AWS cloud region by updating the --region command parameter value and repeat steps no. 1 – 9 for other regions.

References

Publication date Sep 4, 2023