Skip to main content

Auto Scaling Group Launch Configuration Does Not Assign a Public IP Address

Overview

This check ensures that EC2 instances launched by your Auto Scaling groups do not receive public IP addresses. When instances have public IPs, they are directly reachable from the internet, which increases your attack surface.

Best practice: Use launch templates (instead of launch configurations) and place instances in private subnets without public IPs. Access services through load balancers or private endpoints.

Risk

When Auto Scaling launches instances with public IP addresses:

  • Direct internet exposure: Attackers can discover and probe your instances
  • Brute-force attacks: Login services (SSH, RDP) become targets
  • Service exploitation: Any vulnerable service is directly attackable
  • Data exfiltration: Compromised instances can easily send data out
  • Lateral movement: Attackers can use compromised instances to attack other resources

Severity: High

Remediation Steps

Prerequisites

You need:

  • Access to the AWS Console with permissions to modify Auto Scaling groups and create launch templates
  • Knowledge of which Auto Scaling group(s) need remediation
Required IAM permissions

Your IAM user or role needs these permissions:

  • autoscaling:DescribeAutoScalingGroups
  • autoscaling:DescribeLaunchConfigurations
  • autoscaling:UpdateAutoScalingGroup
  • ec2:CreateLaunchTemplate
  • ec2:DescribeLaunchTemplates

AWS Console Method

AWS recommends migrating from launch configurations to launch templates. Here is how to create a new launch template with public IP disabled and update your Auto Scaling group.

Step 1: Identify the affected Auto Scaling group

  1. Open the EC2 Console
  2. In the left navigation, under Auto Scaling, click Auto Scaling Groups
  3. Find and click on the Auto Scaling group that failed the check
  4. Note the current Launch configuration name shown in the details

Step 2: Create a new launch template without public IP

  1. In the EC2 Console, under Instances, click Launch Templates
  2. Click Create launch template
  3. Enter a Launch template name (e.g., my-app-secure-template)
  4. Under Application and OS Images, select the same AMI used by your current launch configuration
  5. Under Instance type, select the same instance type
  6. Under Network settings:
    • Click Edit
    • For Auto-assign public IP, select Disable
    • Select the appropriate Security groups
  7. Configure other settings (key pair, storage, etc.) to match your current configuration
  8. Click Create launch template

Step 3: Update the Auto Scaling group to use the new launch template

  1. Go back to Auto Scaling Groups
  2. Select your Auto Scaling group
  3. Click Edit in the Launch template section
  4. Select your new launch template from the dropdown
  5. Click Update

Step 4: Verify instances are in private subnets

For this change to be effective, your Auto Scaling group should launch instances into private subnets (subnets without a route to an Internet Gateway).

  1. In the Auto Scaling group details, check the Network section
  2. Verify the subnets listed are private subnets
  3. If needed, click Edit and select only private subnets
AWS CLI (optional)

List Auto Scaling groups and their launch configurations:

aws autoscaling describe-auto-scaling-groups \
--region us-east-1 \
--query 'AutoScalingGroups[*].[AutoScalingGroupName,LaunchConfigurationName,LaunchTemplate]' \
--output table

Check if a launch configuration assigns public IPs:

aws autoscaling describe-launch-configurations \
--region us-east-1 \
--launch-configuration-names <your-launch-config-name> \
--query 'LaunchConfigurations[*].[LaunchConfigurationName,AssociatePublicIpAddress]' \
--output table

Create a new launch template without public IP:

aws ec2 create-launch-template \
--region us-east-1 \
--launch-template-name secure-launch-template \
--launch-template-data '{
"ImageId": "<your-ami-id>",
"InstanceType": "t3.micro",
"NetworkInterfaces": [{
"DeviceIndex": 0,
"AssociatePublicIpAddress": false,
"Groups": ["<your-security-group-id>"]
}],
"MetadataOptions": {
"HttpTokens": "required",
"HttpEndpoint": "enabled"
}
}'

Update the Auto Scaling group to use the new launch template:

aws autoscaling update-auto-scaling-group \
--region us-east-1 \
--auto-scaling-group-name <your-asg-name> \
--launch-template "LaunchTemplateId=<your-template-id>,Version=\$Latest"
CloudFormation (optional)

This template creates an Auto Scaling group with a launch template that does not assign public IP addresses:

AWSTemplateFormatVersion: '2010-09-09'
Description: Auto Scaling Launch Template without public IP assignment

Parameters:
LatestAmiId:
Type: AWS::SSM::Parameter::Value<AWS::EC2::Image::Id>
Default: /aws/service/ami-amazon-linux-latest/al2023-ami-kernel-default-x86_64
InstanceType:
Type: String
Default: t3.micro
VpcId:
Type: AWS::EC2::VPC::Id
Description: VPC ID for the security group
SubnetIds:
Type: List<AWS::EC2::Subnet::Id>
Description: Private subnet IDs for the Auto Scaling group

Resources:
InstanceSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: Security group for Auto Scaling instances
VpcId: !Ref VpcId
SecurityGroupEgress:
- IpProtocol: -1
CidrIp: 0.0.0.0/0
Description: Allow all outbound traffic

LaunchTemplate:
Type: AWS::EC2::LaunchTemplate
Properties:
LaunchTemplateName: secure-launch-template
LaunchTemplateData:
ImageId: !Ref LatestAmiId
InstanceType: !Ref InstanceType
SecurityGroupIds:
- !Ref InstanceSecurityGroup
NetworkInterfaces:
- DeviceIndex: 0
AssociatePublicIpAddress: false
Groups:
- !Ref InstanceSecurityGroup
MetadataOptions:
HttpTokens: required
HttpEndpoint: enabled

AutoScalingGroup:
Type: AWS::AutoScaling::AutoScalingGroup
Properties:
AutoScalingGroupName: secure-asg
LaunchTemplate:
LaunchTemplateId: !Ref LaunchTemplate
Version: !GetAtt LaunchTemplate.LatestVersionNumber
MinSize: 1
MaxSize: 3
DesiredCapacity: 1
VPCZoneIdentifier: !Ref SubnetIds
Tags:
- Key: Name
Value: secure-asg-instance
PropagateAtLaunch: true

Outputs:
LaunchTemplateId:
Description: Launch Template ID
Value: !Ref LaunchTemplate
AutoScalingGroupName:
Description: Auto Scaling Group Name
Value: !Ref AutoScalingGroup

Deploy the stack:

aws cloudformation deploy \
--region us-east-1 \
--template-file template.yaml \
--stack-name secure-autoscaling \
--parameter-overrides \
VpcId=<your-vpc-id> \
SubnetIds=<subnet-1>,<subnet-2>
Terraform (optional)
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
}

provider "aws" {
region = "us-east-1"
}

variable "vpc_id" {
description = "VPC ID for the security group"
type = string
}

variable "subnet_ids" {
description = "List of private subnet IDs"
type = list(string)
}

variable "instance_type" {
description = "EC2 instance type"
type = string
default = "t3.micro"
}

data "aws_ami" "amazon_linux_2023" {
most_recent = true
owners = ["amazon"]

filter {
name = "name"
values = ["al2023-ami-*-kernel-*-x86_64"]
}

filter {
name = "virtualization-type"
values = ["hvm"]
}
}

resource "aws_security_group" "instance" {
name_prefix = "asg-instance-"
description = "Security group for Auto Scaling instances"
vpc_id = var.vpc_id

egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
description = "Allow all outbound traffic"
}

tags = {
Name = "asg-instance-sg"
}
}

resource "aws_launch_template" "main" {
name_prefix = "secure-launch-template-"
image_id = data.aws_ami.amazon_linux_2023.id
instance_type = var.instance_type

network_interfaces {
associate_public_ip_address = false
security_groups = [aws_security_group.instance.id]
}

metadata_options {
http_tokens = "required"
http_endpoint = "enabled"
}

tags = {
Name = "secure-launch-template"
}
}

resource "aws_autoscaling_group" "main" {
name = "secure-asg"
min_size = 1
max_size = 3
desired_capacity = 1
vpc_zone_identifier = var.subnet_ids

launch_template {
id = aws_launch_template.main.id
version = "$Latest"
}

tag {
key = "Name"
value = "secure-asg-instance"
propagate_at_launch = true
}
}

output "launch_template_id" {
description = "Launch Template ID"
value = aws_launch_template.main.id
}

output "autoscaling_group_name" {
description = "Auto Scaling Group Name"
value = aws_autoscaling_group.main.name
}

Deploy:

terraform init
terraform apply -var="vpc_id=<your-vpc-id>" -var='subnet_ids=["<subnet-1>","<subnet-2>"]'

Verification

After making changes, verify the remediation worked:

  1. In the AWS Console, go to EC2 > Auto Scaling Groups
  2. Select your Auto Scaling group
  3. Click on the Launch template link
  4. In the launch template details, verify Auto-assign public IP shows Disabled or Don't include in launch template (meaning it will use subnet default, which should be disabled for private subnets)
CLI verification
# Check the launch template network settings
aws ec2 describe-launch-template-versions \
--region us-east-1 \
--launch-template-id <your-template-id> \
--query 'LaunchTemplateVersions[*].LaunchTemplateData.NetworkInterfaces[*].AssociatePublicIpAddress' \
--output text

The output should show False.

Re-run the Prowler check:

prowler aws --checks autoscaling_group_launch_configuration_no_public_ip

Additional Resources

Notes

  • Existing instances are not affected: Changing the launch template only affects newly launched instances. To update existing instances, you can perform an instance refresh or manually terminate instances so Auto Scaling replaces them.
  • Application connectivity: Ensure your application can still function without public IPs. You may need NAT Gateways for outbound internet access, VPC endpoints for AWS services, and load balancers for inbound traffic.
  • Admin access: Use AWS Systems Manager Session Manager, a bastion host, or VPN for administrative access instead of direct SSH/RDP over the internet.
  • Launch configurations are deprecated: AWS recommends using launch templates instead of launch configurations for all new Auto Scaling groups.