Skip to main content

Ensure EKS Clusters Are Not Publicly Accessible

Overview

This check verifies that your Amazon EKS cluster's Kubernetes API server endpoint is not publicly accessible from the internet. By default, EKS creates clusters with a public API endpoint, which means anyone on the internet can potentially attempt to connect to your cluster's control plane.

Risk

When your EKS cluster API endpoint is publicly accessible (especially with 0.0.0.0/0 allowed), you expose your cluster to:

  • Unauthorized access attempts: Attackers can probe, enumerate, and attempt brute-force attacks against your API server
  • Exploitation of misconfigurations: Any RBAC or API vulnerabilities become exploitable from anywhere
  • Data theft: Compromised access could lead to stolen secrets, credentials, or sensitive workload data
  • Workload tampering: Attackers could modify or delete your running applications
  • Cost abuse: Malicious actors could scale resources to generate unexpected charges

Remediation Steps

Prerequisites

You need:

  • Access to the AWS Console with permissions to modify EKS clusters, OR
  • AWS CLI configured with appropriate credentials
  • Network connectivity to your cluster after switching to private access (VPN, Direct Connect, or bastion host)

Important: Before disabling public access, ensure you have a way to reach the cluster privately. If you disable public access without private network connectivity, you will lose access to manage your cluster.

AWS Console Method

  1. Open the Amazon EKS console
  2. Click on Clusters in the left navigation
  3. Select the cluster you want to secure
  4. Click the Networking tab
  5. In the "Cluster endpoint access" section, click Manage endpoint access
  6. Configure the settings:
    • Set Private access to Enabled
    • Set Public access to Disabled
  7. Click Save changes

The update takes a few minutes to complete. Your cluster remains operational during this time.

Alternative: Restrict public access to specific CIDRs

If you cannot fully disable public access, you can restrict it to specific IP ranges:

  1. In the "Manage endpoint access" dialog, keep Public access enabled
  2. Enable Private access as well
  3. Under "Public access source allowlist", remove 0.0.0.0/0
  4. Add only the specific CIDR blocks that need public access (e.g., your office IP range)
  5. Click Save changes

This is less secure than fully private access but significantly reduces your attack surface.

AWS CLI

Disable public access entirely (recommended):

aws eks update-cluster-config \
--region us-east-1 \
--name <your-cluster-name> \
--resources-vpc-config endpointPublicAccess=false,endpointPrivateAccess=true

Check the update status:

aws eks describe-update \
--region us-east-1 \
--name <your-cluster-name> \
--update-id <update-id-from-previous-command>

Alternative - Restrict to specific CIDRs:

If you must keep some public access, restrict it to specific IP ranges:

aws eks update-cluster-config \
--region us-east-1 \
--name <your-cluster-name> \
--resources-vpc-config endpointPublicAccess=true,endpointPrivateAccess=true,publicAccessCidrs="10.0.0.0/8,192.168.1.0/24"

Replace the CIDR blocks with your actual allowed IP ranges.

CloudFormation

For new clusters or infrastructure-as-code deployments, use this CloudFormation template:

AWSTemplateFormatVersion: '2010-09-09'
Description: EKS Cluster with private-only API endpoint access

Parameters:
ClusterName:
Type: String
Description: Name of the EKS cluster
SubnetIds:
Type: List<AWS::EC2::Subnet::Id>
Description: List of subnet IDs for the EKS cluster
SecurityGroupIds:
Type: List<AWS::EC2::SecurityGroup::Id>
Description: List of security group IDs for the EKS cluster
ClusterRoleArn:
Type: String
Description: ARN of the IAM role for the EKS cluster

Resources:
EKSCluster:
Type: AWS::EKS::Cluster
Properties:
Name: !Ref ClusterName
RoleArn: !Ref ClusterRoleArn
ResourcesVpcConfig:
SubnetIds: !Ref SubnetIds
SecurityGroupIds: !Ref SecurityGroupIds
EndpointPublicAccess: false
EndpointPrivateAccess: true

Outputs:
ClusterEndpoint:
Description: EKS cluster endpoint
Value: !GetAtt EKSCluster.Endpoint
ClusterArn:
Description: EKS cluster ARN
Value: !GetAtt EKSCluster.Arn

To update an existing cluster, you cannot directly modify endpoint access via CloudFormation stack updates for some configurations. Use the AWS CLI or Console method instead.

Terraform

For new clusters:

resource "aws_eks_cluster" "private_cluster" {
name = var.cluster_name
role_arn = var.cluster_role_arn

vpc_config {
subnet_ids = var.subnet_ids
endpoint_private_access = true
endpoint_public_access = false
}
}

For existing clusters, update the vpc_config block:

resource "aws_eks_cluster" "existing_cluster" {
# ... existing configuration ...

vpc_config {
subnet_ids = var.subnet_ids
endpoint_private_access = true
endpoint_public_access = false
# Or restrict public access to specific CIDRs:
# endpoint_public_access = true
# public_access_cidrs = ["10.0.0.0/8", "192.168.1.0/24"]
}
}

Run terraform plan to review changes before applying.

Verification

After making changes, verify the configuration:

  1. In the AWS Console, navigate to your EKS cluster
  2. Click the Networking tab
  3. Confirm that "Cluster endpoint access" shows:
    • Private: Enabled
    • Public: Disabled (or restricted to specific CIDRs)
CLI verification
aws eks describe-cluster \
--region us-east-1 \
--name <your-cluster-name> \
--query 'cluster.resourcesVpcConfig.{PublicAccess:endpointPublicAccess,PrivateAccess:endpointPrivateAccess,PublicCIDRs:publicAccessCidrs}'

Expected output for a fully private cluster:

{
"PublicAccess": false,
"PrivateAccess": true,
"PublicCIDRs": []
}

Additional Resources

Notes

  • Plan your connectivity first: Before disabling public access, ensure you have private network connectivity to the cluster VPC via VPN, AWS Direct Connect, or a bastion host. Otherwise, you will be locked out.

  • Update takes time: Cluster configuration updates are asynchronous and typically complete within a few minutes. Your cluster remains operational during the update.

  • kubectl access: After switching to private-only access, you must run kubectl commands from within the VPC or through a connected network. Update your kubeconfig if needed.

  • CI/CD pipelines: If you have CI/CD pipelines that interact with your cluster, ensure they can reach the private endpoint (e.g., by running in the same VPC or through a VPN connection).

  • Consider defense in depth: Even with private access, implement proper RBAC policies, use AWS IAM authentication, and follow the principle of least privilege for all cluster access.