Skip to main content

Ensure Network Policy Is Enabled And Appropriate

More Info:

Amazon EKS provides two ways to implement network policy. You choose a network policy option when you create an EKS cluster. The policy option cant be changed after the cluster is created: Calico Network Policies, an open-source network and network security solution founded by Tigera. Both implementations use Linux IPTables to enforce the specified policies. Policies are translated into sets of allowed and disallowed IP pairs. These pairs are then programmed as IPTable filter rules.

Risk Level

Low

Address

Security

Compliance Standards

  • APRA CPS 234 (Australia)
  • BSI C5 (Germany)
  • Brazil LGPD
  • CCPA / CPRA (California)
  • CIS AKS
  • CIS Critical Security Controls v8
  • CMMC 2.0
  • CSA Cloud Controls Matrix v4
  • DPDPA
  • Digital Operational Resilience Act (EU)
  • ISO/IEC 27017
  • ISO/IEC 27018
  • ISO/IEC 27701
  • KSA PDPL
  • MAS Technology Risk Management (Singapore)
  • NIS2 Directive
  • NIST SP 800-171
  • NYDFS 23 NYCRR 500
  • SWIFT Customer Security Controls Framework
  • Sarbanes-Oxley IT General Controls
  • UK NCSC Cyber Assessment Framework

Triage and Remediation

Remediation

Manual Steps
  1. Determine current network plugin and policy setting

    • Run on any machine with Azure CLI access:
      az aks show \
      --resource-group <RESOURCE_GROUP_NAME> \
      --name <CLUSTER_NAME> \
      --query '{networkPlugin:networkProfile.networkPlugin, networkPolicy:networkProfile.networkPolicy}' \
      --output table
    • Review the output:
      • networkPolicy empty or null ⇒ network policy is not enabled.
      • networkPolicy is azure or calico ⇒ network policy is enabled with that engine.
  2. Confirm whether the current setting meets your isolation requirements

    • If networkPolicy is set (Azure or Calico), review how it’s used by listing policies (for awareness only; enforcement behavior is decided at creation time):
      kubectl get networkpolicy --all-namespaces -o wide
    • On any machine with kubectl access, inspect a few critical namespaces (e.g., kube-system, application namespaces) to see if policies exist and whether they restrict ingress/egress as required:
      kubectl describe networkpolicy -n <NAMESPACE_NAME> <POLICY_NAME>
  3. Decide if the current cluster is acceptable as-is

    • If networkPolicy is set and existing policies provide the needed segmentation/isolation, document this and no control-plane change is required.
    • If networkPolicy is not set or policies are too permissive for your risk profile, plan to migrate workloads to a cluster with appropriate network policy enabled. The network policy engine (Azure or Calico) cannot be changed on an existing AKS cluster.
  4. Plan and provision a compliant AKS cluster (if needed)

    • Select the network plugin and policy engine based on your requirements:
      • Use --network-policy azure --network-plugin azure for Azure Network Policy Manager.
      • Use --network-policy calico --network-plugin azure or Calico-compatible plugin for Calico.
    • Create a new cluster from any machine with Azure CLI access:
      az aks create \
      --resource-group <RESOURCE_GROUP_NAME> \
      --name <NEW_CLUSTER_NAME> \
      --node-count 3 \
      --network-plugin azure \
      --network-policy azure
    • Adjust node count and other options (VM size, autoscaling, zones) per your standards or IaC templates.
  5. Migrate workloads and define appropriate policies

    • Point kubectl to the new cluster:
      az aks get-credentials \
      --resource-group <RESOURCE_GROUP_NAME> \
      --name <NEW_CLUSTER_NAME> \
      --overwrite-existing
    • Recreate namespaces and deploy workloads using your manifests/Helm/IaC.
    • Define network policies that implement least-privilege communication, for example:
      kubectl apply -f secure-namespace-networkpolicies.yaml
    • Validate key application paths still work and non-approved paths are blocked (e.g., using kubectl exec with curl/nc between pods).
  6. Verify and document compliance

    • On the new cluster, confirm network policy is enabled as intended:
      az aks show \
      --resource-group <RESOURCE_GROUP_NAME> \
      --name <NEW_CLUSTER_NAME> \
      --query '{networkPlugin:networkProfile.networkPlugin, networkPolicy:networkProfile.networkPolicy}' \
      --output table
    • Confirm policies exist in required namespaces:
      kubectl get networkpolicy --all-namespaces
    • Record the chosen network policy engine, key policies, and test evidence as proof that network segmentation and isolation are in place.
Using kubectl

kubectl cannot enable or change the AKS network policy engine; this is configured only at the managed control-plane / cloud provider layer (Azure portal, az aks, or IaC) when the cluster is created. Refer to the Manual Steps section for how to review and remediate this finding via Azure configuration.

Automation
#!/usr/bin/env bash
# Purpose: Report AKS network policy configuration and basic policy usage
# Scope: Run on any machine with Azure CLI and kubectl configured

set -euo pipefail

# ---------- CONFIGURATION ----------
# Space-separated list of AKS clusters to check in the current subscription
# Format per entry: RESOURCE_GROUP:CLUSTER_NAME
CLUSTERS=(
"rg-aks-prod:aks-prod"
"rg-aks-nonprod:aks-nonprod"
)

echo "=== AKS Network Policy Report ==="
echo "Subscription: $(az account show --query name -o tsv)"
echo

for entry in "${CLUSTERS[@]}"; do
RG="${entry%%:*}"
CLUSTER="${entry##*:}"

echo "------------------------------------------------------------"
echo "Cluster: ${CLUSTER} (resource group: ${RG})"
echo "------------------------------------------------------------"

# 1. Get AKS cluster network policy and plugin from Azure control plane
# This is the authoritative source for whether a network policy engine is enabled.
NP_ENGINE=$(az aks show \
--resource-group "${RG}" \
--name "${CLUSTER}" \
--query "networkProfile.networkPolicy" -o tsv 2>/dev/null || echo "N/A")

NET_PLUGIN=$(az aks show \
--resource-group "${RG}" \
--name "${CLUSTER}" \
--query "networkProfile.networkPlugin" -o tsv 2>/dev/null || echo "N/A")

echo "Azure networkPlugin : ${NET_PLUGIN:-<unset>}"
echo "Azure networkPolicy : ${NP_ENGINE:-<unset>}"

if [[ "${NP_ENGINE:-}" == "none" || -z "${NP_ENGINE:-}" ]]; then
echo "!! Finding: No network policy engine enabled at the AKS control-plane level."
fi

# 2. Get credentials and interrogate cluster for NetworkPolicy objects
echo
echo "Fetching cluster credentials for kubectl..."
az aks get-credentials --resource-group "${RG}" --name "${CLUSTER}" --overwrite-existing >/dev/null

echo
echo "Kubernetes NetworkPolicy resources:"
# Count network policies cluster-wide
NP_COUNT=$(kubectl get networkpolicy --all-namespaces --no-headers 2>/dev/null | wc -l | tr -d ' ')
echo "Total NetworkPolicy objects: ${NP_COUNT}"

if [[ "${NP_COUNT}" -eq 0 ]]; then
echo "!! Finding: No Kubernetes NetworkPolicy objects defined in this cluster."
fi

echo
echo "NetworkPolicy count per namespace:"
kubectl get networkpolicy --all-namespaces 2>/dev/null \
| awk 'NR==1{next} {count[$1]++} END{for (ns in count) printf "%-30s %5d\n", ns, count[ns]}' \
| sort

# 3. Highlight namespaces with no NetworkPolicy
echo
echo "Namespaces with zero NetworkPolicy objects (potentially overly-permissive):"
# Build a list of namespaces that have at least one policy
ns_with_np=$(kubectl get networkpolicy --all-namespaces --no-headers 2>/dev/null | awk '{print $1}' | sort -u || true)
# Compare to all namespaces
kubectl get ns --no-headers 2>/dev/null | awk '{print $1}' | while read -r ns; do
if ! grep -qx "${ns}" <<< "${ns_with_np}"; then
echo " - ${ns}"
fi
done

echo
echo "NOTE: Namespaces listed above should be reviewed to determine whether"
echo " they require traffic segmentation/isolation via NetworkPolicy."
echo
done

Explanation of output that indicates a problem:

  • Azure networkPolicy : none or empty
    → The AKS cluster was created without a network policy engine; this does not meet the benchmark requirement to “utilize Calico or another network policy engine to segment and isolate your traffic.”

  • Total NetworkPolicy objects: 0
    → Even if a network policy engine is enabled, no Kubernetes NetworkPolicy resources exist, so traffic is not segmented/isolated by policy.

  • Under “Namespaces with zero NetworkPolicy objects”
    → Each listed namespace currently has no NetworkPolicy. For workloads that should be isolated (most non-system workloads), this is a potential misconfiguration that requires manual review and policy design.