This check flags AKS clusters whose Kubernetes API server is reachable from any IP on the public internet. Lock it down by configuring authorized IP ranges with az aks update --api-server-authorized-ip-ranges so only your corporate networks and CI runners can reach the control plane.
The Kubernetes API server is the front door to your cluster. Every kubectl command, every controller, and every CI/CD deployment talks to it. On Azure Kubernetes Service (AKS), a public cluster exposes that API server on a public IP by default. If you never restrict who can connect, the only thing standing between an attacker and your control plane is authentication, and authentication has a habit of failing in ways you did not plan for.
The aks_noapiipranges check looks for AKS clusters that have no authorized IP ranges set on the public API server endpoint. When this control is missing, the management plane accepts connection attempts from anywhere.
What this check detects
AKS gives you a feature called API server authorized IP ranges. It is an allowlist of CIDR blocks that are permitted to reach the API server's public endpoint. When configured, traffic from any source outside those ranges is dropped at the network layer before it ever reaches the authentication stage.
This check reports a failure when:
- The cluster uses a public API server endpoint, and
- The
apiServerAccessProfile.authorizedIpRangesfield is empty or unset.
Note: This control only applies to public AKS clusters. If you run a fully private cluster, the API server has no public IP at all and this check is not relevant. Private clusters and authorized IP ranges are two different ways of solving the same exposure problem.
Why it matters
An exposed API server is one of the most heavily scanned targets on the internet. Mass scanners constantly sweep cloud IP ranges looking for Kubernetes endpoints, then probe them for anonymous access, weak RBAC, and known CVEs. Leaving the front door open turns a single misconfiguration elsewhere into a full cluster compromise.
Here is how this plays out in practice:
- Credential theft becomes catastrophic. A leaked kubeconfig or service account token in a public repo is bad enough. If the API server is also reachable from anywhere, the attacker can use that credential immediately, from anywhere, with no further hurdles.
- Anonymous and misconfigured RBAC gets exploited. Clusters that accidentally bind broad roles to
system:anonymousorsystem:unauthenticatedare a common finding. Combine that with public reachability and you have unauthenticated remote access to the control plane. - CVE exposure widens. When a new Kubernetes API server vulnerability drops, a publicly reachable endpoint moves you from "patch when convenient" to "patch before the scanners find you."
- Brute force and enumeration. Even with authentication intact, attackers can hammer the endpoint, enumerate behavior, and probe for information disclosure without any network barrier slowing them down.
Restricting the API server to known networks does not replace authentication and RBAC. It adds a layer of defense in depth so that a single failure in any one of those layers does not hand over the entire cluster.
Warning: Authorized IP ranges restrict access to the API server, not to your workloads. Services exposed through LoadBalancer or Ingress are governed by their own network rules. This check is about protecting the control plane only.
How to fix it
You have two solid options. The most common is to add authorized IP ranges to your existing public cluster. The stronger option, if your network design supports it, is to convert to a private cluster.
Option 1: Add authorized IP ranges (CLI)
First, identify the IPs that legitimately need to reach the API server. This usually includes your office or VPN egress IPs, your CI/CD runner egress IPs, and any bastion or jump host you use for cluster administration.
Find your current public egress IP if you are setting this from a workstation:
curl -s https://ifconfig.me
Danger: If you set authorized IP ranges to a list that does not include your own current egress IP, you will immediately lock yourself out of the API server. Double check every CIDR before you run the update, and always include your CI runners and admin paths.
Apply the allowlist with a single update command. Use /32 for individual IPs:
az aks update \
--resource-group myResourceGroup \
--name myAKSCluster \
--api-server-authorized-ip-ranges "203.0.113.10/32,198.51.100.0/24"
Verify the change took effect:
az aks show \
--resource-group myResourceGroup \
--name myAKSCluster \
--query "apiServerAccessProfile.authorizedIpRanges" \
-o tsv
Warning: If your cluster uses a Standard Load Balancer with outbound traffic, the cluster's own outbound public IPs are added to the authorized ranges automatically. Do not remove them or in-cluster components may lose access to the API server.
Option 2: Convert to a private cluster
For environments where the API server should never touch the public internet, a private cluster gives the API server a private IP inside your virtual network. This cannot be done by updating an existing public cluster, it requires creating a new one:
az aks create \
--resource-group myResourceGroup \
--name myPrivateAKSCluster \
--enable-private-cluster \
--network-plugin azure
With a private cluster you reach the API server through a VNet peering, VPN, ExpressRoute, or a jump host inside the network. This is the strongest option but requires more network plumbing for your CI/CD and admin access.
Fix with Terraform
If you manage AKS with Terraform, set the allowlist on the api_server_access_profile block so the configuration is enforced on every apply:
resource "azurerm_kubernetes_cluster" "this" {
name = "myAKSCluster"
resource_group_name = azurerm_resource_group.this.name
location = azurerm_resource_group.this.location
dns_prefix = "myaks"
default_node_pool {
name = "default"
node_count = 2
vm_size = "Standard_D2s_v3"
}
identity {
type = "SystemAssigned"
}
api_server_access_profile {
authorized_ip_ranges = [
"203.0.113.10/32",
"198.51.100.0/24",
]
}
}
Tip: Keep your authorized IP list in a single Terraform variable or locals block sourced from your VPN and CI egress IP data. When an office moves or a runner pool changes, you update one place and every cluster picks it up on the next apply.
How to prevent it from happening again
Fixing one cluster is easy. Making sure the next ten clusters ship with the control already in place is where the real value is. Push the guardrail as far left as you can.
Enforce with Azure Policy
Azure has a built-in policy definition: Authorized IP ranges should be defined on Kubernetes Services. Assign it with a Deny or Audit effect across your subscriptions so non-compliant clusters are flagged or blocked at creation time.
az policy assignment create \
--name "require-aks-authorized-ip-ranges" \
--display-name "Require authorized IP ranges on AKS" \
--policy "0e246bcf-5f6f-4f87-bc6f-775d4712c7ea" \
--scope "/subscriptions/00000000-0000-0000-0000-000000000000"
Gate it in CI/CD
If you provision with Terraform, scan plans before they apply. Tools like Checkov and tfsec catch missing authorized IP ranges as part of your pipeline:
# Fail the build if AKS config is non-compliant
checkov -d ./infra --framework terraform
Wire that into a pull request check so a cluster without authorized IP ranges never reaches terraform apply.
Tip: Pair policy-as-code with continuous monitoring in Lensix. Policy stops bad configs from being created, and Lensix catches drift when someone widens the allowlist to 0.0.0.0/0 through a quick manual change "just to test something."
Best practices
- Default to private clusters for production. If your network supports it, removing the public endpoint entirely is the cleanest answer. Use authorized IP ranges when you need public reachability for practical reasons.
- Keep the allowlist tight. Use
/32ranges for fixed admin IPs rather than broad/16blocks. The smaller the list, the smaller the attack surface. - Route admin access through stable egress. A NAT gateway or VPN with a fixed egress IP gives you a single, predictable CIDR to allowlist instead of chasing changing workstation IPs.
- Never use 0.0.0.0/0. Setting the authorized range to the whole internet technically satisfies the field but defeats the entire purpose. Treat it as equivalent to having no restriction at all.
- Layer your defenses. Authorized IP ranges are network-level protection. Pair them with strong RBAC, Azure AD integration, and disabling local accounts so a single layer failing does not mean game over.
- Review the list regularly. Egress IPs change as offices move and runner fleets scale. Audit the allowlist on a schedule so it stays accurate and minimal.
The API server is the most security-sensitive surface in any Kubernetes cluster. Restricting who can reach it is a low-effort, high-impact control that closes the door on the most common opportunistic attacks. Set it once, enforce it with policy, and monitor for drift.

