Back to Checks
Prowlerprowler-provider-azure
AKS cluster has a private endpoint and node public access is disabled
aks_clusters_public_access_disabled
Service: aksSeverity: high
OfficialBuilt-inVerified
Categories:internet-exposedtrust-boundariescluster-security
Resource Type:microsoft.containerservice/managedclusters
AKS clusters expose a private control plane FQDN and agent pools have enable_node_public_ip=false.
The evaluation focuses on the presence of a private FQDN and the absence of public IPs on nodes.
Risk
Exposed node IPs or a publicly reachable API increase attack surface, impacting confidentiality and integrity.
- Internet scans reach kubelet, NodePort, or management agents
- Exploits enable RCE and lateral movement
- Metadata/secret theft leads to credential compromise
Availability is at risk from DDoS on exposed endpoints.
Run this check with Prowler
Run in Prowler CloudRun
prowler azure --checks aks_clusters_public_access_disabledRecommendation
Adopt private clusters and eliminate node public IPs:
- Set
enable_node_public_ip=falseon all pools - Use Private Link or peered VNets with VPN/ExpressRoute for admin access
- If public API is unavoidable, restrict with IP ranges and strong auth
- Enforce NSGs/firewalls and least privilege for layered defense
Remediation
Terraform
# AKS cluster with private endpoint and nodes without public IPs
resource "azurerm_kubernetes_cluster" "<example_resource_name>" {
name = "<example_resource_name>"
location = "<location>"
resource_group_name = "<example_resource_name>"
dns_prefix = "dns"
private_cluster_enabled = true # Critical: enables private cluster (private endpoint/FQDN)
default_node_pool {
name = "nodepool1"
node_count = 1
vm_size = "Standard_DS2_v2"
enable_node_public_ip = false # Critical: disables public IPs on nodes
}
identity {
type = "SystemAssigned"
}
}NativeIaC
// AKS cluster with private endpoint and nodes without public IPs
resource aks 'Microsoft.ContainerService/managedClusters@2023-11-01' = {
name: '<example_resource_name>'
location: '<location>'
identity: {
type: 'SystemAssigned'
}
properties: {
dnsPrefix: 'dns'
apiServerAccessProfile: {
enablePrivateCluster: true // Critical: enables private cluster (private endpoint/FQDN)
}
agentPoolProfiles: [
{
name: 'nodepool1'
count: 1
vmSize: 'Standard_DS2_v2'
enableNodePublicIP: false // Critical: disables public IPs on nodes
}
]
}
}Other
1In the Azure portal, go to Azure Kubernetes Service and select your cluster
2Go to Networking > API server access
3Set Private cluster to Enabled and click Save
4Go to Node pools, open each pool, select Networking, set Public IP per node to Disabled, and Save
5Repeat step 4 for all node pools
Check Code
from prowler.lib.check.models import Check, Check_Report_Azure
from prowler.providers.azure.services.aks.aks_client import aks_client
class aks_clusters_public_access_disabled(Check):
def execute(self) -> Check_Report_Azure:
findings = []
for subscription_id, clusters in aks_client.clusters.items():
subscription_name = aks_client.subscriptions.get(
subscription_id, subscription_id
)
for cluster in clusters.values():
report = Check_Report_Azure(metadata=self.metadata(), resource=cluster)
report.subscription = subscription_id
report.status = "FAIL"
report.status_extended = f"Public access to nodes is enabled for cluster '{cluster.name}' in subscription '{subscription_name} ({subscription_id})'"
if cluster.private_fqdn:
for agent_pool in cluster.agent_pool_profiles:
if not getattr(agent_pool, "enable_node_public_ip", False):
report.status = "PASS"
report.status_extended = f"Public access to nodes is disabled for cluster '{cluster.name}' in subscription '{subscription_name} ({subscription_id})'"
findings.append(report)
return findingsReferences
- https://learn.microsoft.com/en-us/azure/aks/private-clusters?tabs=azure-portal
- https://learn.microsoft.com/en-us/azure/aks/access-private-cluster?tabs=azure-cli
- https://support.icompaas.com/support/solutions/articles/62000234657-ensure-clusters-are-created-with-private-endpoint-enabled-and-public-access-disabled
- https://docs.trendmicro.com/en-us/documentation/article/trend-vision-one-cis-aks17-542