Info icon
End of Life Notice: For Trend Cloud One™ - Conformity Customers, Conformity will reach its End of Sale on “July 31st, 2025” and End of Life “July 31st, 2026”. The same capabilities and much more is available in TrendAI Vision One™ Cloud Risk Management. For details, please refer to Upgrade to TrendAI Vision One™
Use the Knowledge Base AI to help improve your Cloud Posture

Ensure EKS Clusters Are Created with Private Nodes

TrendAI Vision One™ provides continuous assurance that gives peace of mind for your cloud infrastructure, delivering over 1400 automated best practice checks.

Risk Level: Medium (should be achieved)
Rule ID: EKS-008

Ensure that your Amazon Elastic Kubernetes Service (EKS) cluster nodes do not have public IP addresses assigned, so that they only have private IP addresses and are not directly accessible from the Internet. Private nodes are nodes with no public IP addresses. When cluster nodes are assigned public IP addresses, they become directly addressable from the Internet, increasing the attack surface and making it harder to secure the cluster. To ensure nodes are private, they should be deployed in private subnets that do not auto-assign public IP addresses, and launch templates should set AssociatePublicIpAddress to false. Additionally, the cluster's API server endpoint should be configured with private access enabled and public access disabled or restricted to specific trusted CIDR blocks. Enabling private nodes is a recommended control required by CIS Amazon EKS Benchmark v1.8.0 (5.4.3).

Security

Disabling public IP addresses on cluster nodes restricts access to only internal networks, forcing attackers to obtain local network access before attempting to compromise the underlying Kubernetes hosts. When nodes have public IPs, each IP can serve as a potential entry point for attackers, making it easier to exploit vulnerabilities or move laterally within the cluster. By using private nodes, all inbound traffic must pass through controlled entry points such as load balancers, bastion hosts, or VPN connections, significantly improving the security posture of the Kubernetes cluster.

Private nodes do not have outbound access to the public internet. If you want to provide outbound Internet access for your private nodes, you can use a NAT Gateway or manage your own NAT instance. Ensure that alternative access methods are in place before removing public IP addresses from existing nodes. Additionally, the cluster must be configured with a private API server endpoint and IP Aliasing enabled for private nodes to function correctly.


Audit

To determine if your Amazon EKS cluster nodes are created with private nodes (i.e., no public IP addresses assigned), perform the following actions:

Using AWS Console

  1. Sign in to the AWS Management Console.

  2. Navigate to Amazon EKS console at https://console.aws.amazon.com/eks/.

  3. In the main navigation panel, under Amazon Elastic Kubernetes Service, choose Clusters.

  4. Click on the name (link) of the Amazon EKS cluster that you want to examine.

  5. Select the Networking tab to access the networking settings available for the selected cluster.

  6. Check the API server endpoint access attribute. If the API server endpoint access is NOT set to Private only, or if the Public access source allowlist includes 0.0.0.0/0 (open to all traffic), the cluster endpoint configuration is non-compliant as it does not enforce private-only access.

  7. Select the Compute tab to access the compute resources provisioned for the selected cluster.

  8. Click on the name (link) of a node group that you want to examine.

  9. In the Node group details section, check the Subnets associated with the node group. Verify that the listed subnets are private subnets (i.e., subnets that do not auto-assign public IP addresses and are not associated with a route table that has a route to an Internet Gateway).

  10. If the node group uses a Launch template, navigate to the EC2 console at https://console.aws.amazon.com/ec2/, choose Launch templates from the navigation panel, select the launch template used by the node group, and verify that Auto-assign public IPv4 address is set to Don't include in launch template or Disable. If the auto-assign public IPv4 address setting is enabled, the selected node group is non-compliant.

  11. To verify that the node group subnets are private, navigate to the VPC console at https://console.aws.amazon.com/vpc/, choose Subnets from the navigation panel, select a subnet associated with the node group, and check the Auto-assign public IPv4 address setting. If set to Yes, the subnet auto-assigns public IPs and is non-compliant. Also check the Route table tab associated with the subnet to confirm there is no route to an Internet Gateway (IGW).

  12. Repeat steps no. 8 – 11 for each node group provisioned for the selected EKS cluster.

  13. Repeat steps no. 4 – 12 for each Amazon EKS cluster deployed within the current AWS region.

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

Using AWS CLI

  1. Run list-clusters command (OSX/Linux/UNIX) with custom query filters to list the names of all Amazon EKS clusters available in the selected AWS region:

    aws eks list-clusters
    	--region us-east-1
    	--output table
    	--query 'clusters'
    
  2. The command output should return a table with the requested EKS cluster identifiers:

    -------------------------
    |     ListClusters      |
    +-----------------------+
    |  cc-eks-mobile-app    |
    |  cc-eks-kube-stack    |
    +-----------------------+
    
  3. Run describe-cluster command (OSX/Linux/UNIX) using the name of the Amazon EKS cluster that you want to examine as the identifier parameter and custom query filters to describe the Kubernetes API server endpoint access configuration for the selected cluster:

    aws eks describe-cluster
    	--region us-east-1
    	--name cc-eks-mobile-app
    	--query 'cluster.resourcesVpcConfig.{endpointPublicAccess: endpointPublicAccess, endpointPrivateAccess: endpointPrivateAccess, publicAccessCidrs: publicAccessCidrs}'
    
  4. The command output should return the requested endpoint access configuration information:

    {
    	"endpointPublicAccess": true,
    	"endpointPrivateAccess": false,
    	"publicAccessCidrs": [
    		"0.0.0.0/0"
    	]
    }
    

    If the "endpointPrivateAccess" attribute value is set to false, or the "endpointPublicAccess" attribute value is set to true and the "publicAccessCidrs" attribute value includes "0.0.0.0/0", the selected Amazon EKS cluster endpoint configuration does not enforce private-only access and is non-compliant.

  5. Run list-nodegroups command (OSX/Linux/UNIX) with custom query filters to list the name of each node group provisioned for the selected Amazon EKS cluster:

    aws eks list-nodegroups
    	--region us-east-1
    	--cluster-name cc-eks-mobile-app
    	--query 'nodegroups'
    
  6. The command output should return the requested EKS cluster node group names:

    [
    	"cc-eks-mobile-app-nodegroup-01",
    	"cc-eks-mobile-app-nodegroup-02"
    ]
    
  7. Run describe-nodegroup command (OSX/Linux/UNIX) with custom output filtering to describe the subnets and launch template configuration for the selected node group:

    aws eks describe-nodegroup
    	--region us-east-1
    	--cluster-name cc-eks-mobile-app
    	--nodegroup-name cc-eks-mobile-app-nodegroup-01
    	--query 'nodegroup.{subnets: subnets, launchTemplate: launchTemplate}'
    
  8. The command output should return the subnet and launch template information for the selected node group:

    {
    	"subnets": [
    		"subnet-0abcd1234efgh5678",
    		"subnet-0ijkl9012mnop3456"
    	],
    	"launchTemplate": {
    		"name": "cc-eks-launch-template",
    		"version": "1",
    		"id": "lt-0abcd1234efgh5678"
    	}
    }
    
  9. Run describe-subnets command (OSX/Linux/UNIX) to check whether the subnets associated with the node group auto-assign public IP addresses:

    aws ec2 describe-subnets
    	--region us-east-1
    	--subnet-ids subnet-0abcd1234efgh5678 subnet-0ijkl9012mnop3456
    	--query 'Subnets[*].{SubnetId: SubnetId, MapPublicIpOnLaunch: MapPublicIpOnLaunch, AvailabilityZone: AvailabilityZone}'
    
  10. The command output should return the requested subnet information:

    [
    	{
    		"SubnetId": "subnet-0abcd1234efgh5678",
    		"MapPublicIpOnLaunch": true,
    		"AvailabilityZone": "us-east-1a"
    	},
    	{
    		"SubnetId": "subnet-0ijkl9012mnop3456",
    		"MapPublicIpOnLaunch": false,
    		"AvailabilityZone": "us-east-1b"
    	}
    ]
    

    If the "MapPublicIpOnLaunch" attribute value is set to true for any subnet associated with the node group, as shown in the output example above for subnet-0abcd1234efgh5678, the nodes in that subnet will be assigned public IP addresses and the configuration is non-compliant.

  11. Run describe-route-tables command (OSX/Linux/UNIX) to verify that the subnets associated with the node group do not have a route to an Internet Gateway (IGW):

    aws ec2 describe-route-tables
    	--region us-east-1
    	--filters "Name=association.subnet-id,Values=subnet-0abcd1234efgh5678"
    	--query 'RouteTables[*].Routes[?GatewayId!=`local`].{DestinationCidrBlock: DestinationCidrBlock, GatewayId: GatewayId}'
    
  12. The command output should return the route information for the selected subnet:

    [
    	[
    		{
    			"DestinationCidrBlock": "0.0.0.0/0",
    			"GatewayId": "igw-0abcd1234efgh5678"
    		}
    	]
    ]
    

    If the route table associated with a node group subnet has a route with a "GatewayId" value that starts with "igw-" (indicating an Internet Gateway), the subnet is a public subnet and the node group configuration is non-compliant.

  13. (Optional) If the node group uses a launch template, run describe-launch-template-versions command (OSX/Linux/UNIX) to check whether the launch template enables public IP addresses:

    aws ec2 describe-launch-template-versions
    	--region us-east-1
    	--launch-template-id lt-0abcd1234efgh5678
    	--versions '$Latest'
    	--query 'LaunchTemplateVersions[*].LaunchTemplateData.NetworkInterfaces[*].AssociatePublicIpAddress'
    
  14. The command output should return the public IP assignment setting:

    [
    	[
    		true
    	]
    ]
    

    If the "AssociatePublicIpAddress" attribute value is set to true, the launch template assigns public IP addresses to node instances and the configuration is non-compliant. If the value is false or the attribute is not present, the launch template does not override subnet settings for public IP assignment.

  15. Repeat steps no. 7 – 14 for each node group provisioned for the selected EKS cluster.

  16. Repeat steps no. 3 – 15 for each Amazon EKS cluster available in the selected AWS region.

  17. Change the AWS cloud region by updating the --region command parameter value and repeat the Audit process for other regions.

Remediation / Resolution

To ensure your Amazon EKS cluster nodes are created with private nodes (no public IP addresses), you must configure the cluster API server endpoint for private access and deploy node groups in private subnets without public IP auto-assignment. Perform the following actions:

Transitioning to private nodes requires careful planning. Ensure a NAT Gateway or NAT instance is configured for outbound internet access from private subnets. Verify that all required services are accessible via VPC endpoints or private connections. Test connectivity before migrating production workloads. Existing node groups may need to be replaced with new node groups that use private subnets, as subnet configurations cannot be modified after node group creation.

Using AWS Console

  1. Sign in to the AWS Management Console.

  2. Navigate to Amazon EKS console at https://console.aws.amazon.com/eks/.

  3. In the main navigation panel, under Amazon Elastic Kubernetes Service, choose Clusters.

  4. Click on the name (link) of the Amazon EKS cluster that you want to reconfigure (see Audit section part I to identify the right resource).

  5. Select the Networking tab and choose Manage networking to edit the networking configuration settings for the selected cluster.

  6. For Cluster endpoint access, select Private to ensure that the cluster endpoint access and worker node traffic stays within your VPC only, thus minimizing the security risks. Choose Save changes to apply the changes.

  7. Select the Compute tab to access the compute resources provisioned for the selected cluster.

  8. Choose Add node group from the Node groups section and follow the setup wizard to configure a new node group based on your application requirements.

  9. For Step 3 Specify networking, under Node group network configuration:

    1. For Subnets, select only private subnets that do not auto-assign public IP addresses and are not associated with a route table that has a route to an Internet Gateway. Remove any public subnets from the list.
    2. If using a launch template, ensure the launch template has Auto-assign public IPv4 address set to Disable or Don't include in launch template.
  10. Complete the remaining configuration steps and choose Create to launch the new node group with private nodes.

  11. Once the new node group is active and healthy, remove the non-compliant node group by selecting it and choosing Delete. To confirm the deletion, type the node group name in the required field, and choose Delete to confirm the resource removal.

  12. Repeat steps no. 8 – 11 for each non-compliant EKS cluster node group.

  13. Repeat steps no. 4 – 12 for each Amazon EKS cluster available within the current AWS region.

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

Using AWS CLI

  1. Run update-cluster-config command (OSX/Linux/UNIX) using the name of the Amazon EKS cluster that you want to reconfigure as the identifier parameter, to disable public access and enable private access for the selected EKS cluster Kubernetes API server endpoint:

    aws eks update-cluster-config
    	--region us-east-1
    	--name cc-eks-mobile-app
    	--resources-vpc-config endpointPublicAccess=false,endpointPrivateAccess=true
    
  2. The command output should return the information available for the new API server endpoint access configuration:

    {
    	"update": {
    		"status": "InProgress",
    		"errors": [],
    		"params": [
    			{
    				"type": "EndpointPublicAccess",
    				"value": "false"
    			},
    			{
    				"type": "EndpointPrivateAccess",
    				"value": "true"
    			}
    		],
    		"type": "EndpointAccessUpdate",
    		"id": "abcd1234-abcd-abcd-abcd-1234abcd1234",
    		"createdAt": 1567589177.445
    	}
    }
    
  3. Run describe-update command (OSX/Linux/UNIX) to confirm the configuration changes performed at the previous step. The EKS cluster API server endpoint access configuration update is complete when the update process status is set to "Successful":

    aws eks describe-update
    	--region us-east-1
    	--name cc-eks-mobile-app
    	--update-id abcd1234-abcd-abcd-abcd-1234abcd1234
    	--query 'update.status'
    
  4. The command output should return the requested update status:

    "Successful"
    
  5. Run create-nodegroup command (OSX/Linux/UNIX) using the name of the Amazon EKS cluster that you want to configure as the identifier parameter, to create a new node group with private subnets only (subnets that do not auto-assign public IP addresses and have no Internet Gateway route):

    aws eks create-nodegroup
    	--region us-east-1
    	--cluster-name cc-eks-mobile-app
    	--nodegroup-name cc-eks-private-nodegroup
    	--subnets subnet-0abcd1234efgh5678 subnet-0ijkl9012mnop3456
    	--node-role arn:aws:iam::123456789012:role/cc-eks-node-role
    	--instance-types t3.medium
    

    Note: The subnets specified must be private subnets where MapPublicIpOnLaunch is set to false and the associated route table does not contain a route to an Internet Gateway (IGW). If using a launch template, include the --launch-template parameter and ensure the launch template sets AssociatePublicIpAddress to false:

    aws eks create-nodegroup
    	--region us-east-1
    	--cluster-name cc-eks-mobile-app
    	--nodegroup-name cc-eks-private-nodegroup
    	--subnets subnet-0abcd1234efgh5678 subnet-0ijkl9012mnop3456
    	--node-role arn:aws:iam::123456789012:role/cc-eks-node-role
    	--launch-template name=cc-eks-private-launch-template,version=1
    
  6. The command output should return the configuration information available for the new node group:

    {
    	"nodegroup": {
    		"nodegroupName": "cc-eks-private-nodegroup",
    		"nodegroupArn": "arn:aws:eks:us-east-1:123456789012:nodegroup/cc-eks-mobile-app/cc-eks-private-nodegroup/abcd1234-abcd-1234-abcd-1234abcd1234",
    		"clusterName": "cc-eks-mobile-app",
    		"version": "1.29",
    		"releaseVersion": "1.29.0-20240307",
    		"createdAt": "2024-03-15T10:30:00.000000+00:00",
    		"modifiedAt": "2024-03-15T10:30:00.000000+00:00",
    		"status": "CREATING",
    		"capacityType": "ON_DEMAND",
    		"scalingConfig": {
    			"minSize": 1,
    			"maxSize": 3,
    			"desiredSize": 2
    		},
    		"instanceTypes": [
    			"t3.medium"
    		],
    		"subnets": [
    			"subnet-0abcd1234efgh5678",
    			"subnet-0ijkl9012mnop3456"
    		],
    		"amiType": "AL2_x86_64",
    		"nodeRole": "arn:aws:iam::123456789012:role/cc-eks-node-role",
    		"diskSize": 20,
    		"health": {
    			"issues": []
    		},
    		"updateConfig": {
    			"maxUnavailable": 1
    		},
    		"tags": {}
    	}
    }
    
  7. Run describe-nodegroup command (OSX/Linux/UNIX) to verify that the new node group is active and using private subnets (see Audit section part II to verify the subnets):

    aws eks describe-nodegroup
    	--region us-east-1
    	--cluster-name cc-eks-mobile-app
    	--nodegroup-name cc-eks-private-nodegroup
    	--query 'nodegroup.{status: status, subnets: subnets}'
    
  8. The command output should return the status and subnet information:

    {
    	"status": "ACTIVE",
    	"subnets": [
    		"subnet-0abcd1234efgh5678",
    		"subnet-0ijkl9012mnop3456"
    	]
    }
    
  9. Once the new node group is active and healthy, run delete-nodegroup command (OSX/Linux/UNIX) to remove the non-compliant node group from your Amazon EKS cluster:

    aws eks delete-nodegroup
    	--region us-east-1
    	--cluster-name cc-eks-mobile-app
    	--nodegroup-name cc-eks-mobile-app-nodegroup-01
    
  10. The command output should return the information available for the deleted node group:

    {
    	"nodegroup": {
    		"nodegroupName": "cc-eks-mobile-app-nodegroup-01",
    		"nodegroupArn": "arn:aws:eks:us-east-1:123456789012:nodegroup/cc-eks-mobile-app/cc-eks-mobile-app-nodegroup-01/abcd1234-abcd-1234-abcd-1234abcd1234",
    		"clusterName": "cc-eks-mobile-app",
    		"status": "DELETING",
    		"subnets": [
    			"subnet-0abcd1234efgh5678",
    			"subnet-0ijkl9012mnop3456"
    		],
    		"nodeRole": "arn:aws:iam::123456789012:role/cc-eks-node-role",
    		"health": {
    			"issues": []
    		},
    		"tags": {}
    	}
    }
    
  11. Repeat steps no. 5 – 10 for each non-compliant EKS cluster node group.

  12. Repeat steps no. 1 – 11 for each Amazon EKS cluster available in the selected AWS region.

  13. Change the AWS cloud region by updating the --region command parameter value and repeat the Remediation process for other regions.

References

Publication date Mar 5, 2026