> ## Documentation Index
> Fetch the complete documentation index at: https://cloudanix.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Ensure Network Policy Is Enabled And Set Appropriately

### More Info:

Enable a network policy engine such as Calico to segment and isolate pod traffic, enforcing least-privilege network communication within the cluster.

### Risk Level

High

### Address

Security

### Compliance Standards

* CIS AKS

### Triage and Remediation

<Tabs>
  <Tab title="Remediation">
    ### Remediation

    <AccordionGroup>
      <Accordion title="Manual Steps" defaultOpen="true">
        1. **Identify whether network policy is enabled on the AKS cluster**
           * Run on: any machine with Azure CLI access and permission on the subscription.
           * Command (replace the placeholders with your real values before running):
             ```bash theme={null}
             az aks show \
               --resource-group <RESOURCE_GROUP_NAME> \
               --name <CLUSTER_NAME> \
               --query '{networkPlugin:networkProfile.networkPlugin, networkPolicy:networkProfile.networkPolicy}' \
               --output table
             ```
           * Review:
             * Confirm `networkPlugin` is typically `azure` or `kubenet`.
             * Confirm `networkPolicy` is set to `calico` or `azure`. If it is `null` or empty, network policy is not enabled.

        2. **Decide if change is required based on security requirements**
           * If `networkPolicy` is not set, or set inconsistently with your standard (e.g., you mandate Calico but see `azure`), determine:
             * Compliance requirements for pod-to-pod and pod-to-external isolation.
             * Whether application teams rely on unrestricted intra-cluster communication that could be broken by restrictive policies.
           * Document the required target state (e.g., “All AKS clusters must use networkPolicy = azure” or “= calico”).

        3. **Review existing Kubernetes NetworkPolicies to understand current behavior**
           * Run on: any machine with kubectl access to the cluster.
           * Commands:
             ```bash theme={null}
             kubectl get networkpolicy --all-namespaces
             ```
           * If there are few or no policies, plan for a staged rollout: start with default-allow policies, then tighten.
           * Identify critical namespaces/workloads that must remain reachable (ingress controllers, DNS, monitoring, logging, gateways).

        4. **Plan and apply the configuration change via cloud/IaC tooling**
           * Network policy enablement on AKS is a control-plane / cluster-creation-level setting; on many cluster versions it cannot be toggled in-place without recreation.
           * If your cluster/IaC stack supports changing `networkPolicy` in-place (check your current AKS version and Azure docs):
             * Example using Azure CLI (update scenario, if supported):
               ```bash theme={null}
               az aks update \
                 --resource-group <RESOURCE_GROUP_NAME> \
                 --name <CLUSTER_NAME> \
                 --network-policy <azure|calico>
               ```
           * If in-place change is not supported, plan to:
             * Update IaC (e.g., ARM/Bicep/Terraform) to include the desired `networkPolicy` for a new cluster.
             * Migrate workloads to the new cluster following your change-management process.

        5. **Design and deploy baseline NetworkPolicies for least-privilege**
           * Using kubectl or your GitOps/IaC pipeline, implement at least:
             * Namespaced default policies (e.g., a default “deny-all-ingress” and “deny-all-egress” or “allow-necessary-egress-only”) in sensitive namespaces.
             * Explicit allow policies for:
               * DNS to kube-dns/CoreDNS.
               * Ingress from load balancer/ingress controllers to exposed services.
               * Monitoring/logging agents communicating with their backends.
           * Apply these in a test environment first, then progressively in production namespaces.

        6. **Verify and document the final state**
           * Re-run the Azure CLI check:
             ```bash theme={null}
             az aks show \
               --resource-group <RESOURCE_GROUP_NAME> \
               --name <CLUSTER_NAME> \
               --query '{networkPlugin:networkProfile.networkPlugin, networkPolicy:networkProfile.networkPolicy}' \
               --output table
             ```
           * Confirm `networkPolicy` reflects the intended engine.
           * Re-run:
             ```bash theme={null}
             kubectl get networkpolicy --all-namespaces
             ```
           * Validate that critical application paths still function and that unnecessary pod-to-pod communication is blocked according to your baseline policies. Document the result and any exceptions.
      </Accordion>

      <Accordion title="Using kubectl">
        kubectl cannot be used to enable or change the cluster-wide network policy engine in AKS; this is configured at the cloud provider / managed control plane level (for example via the Azure portal, `az aks`, or IaC such as ARM/Bicep/Terraform). Refer to the Manual Steps section for guidance on enabling and configuring a network policy provider like Calico for your cluster.
      </Accordion>

      <Accordion title="Automation">
        ```bash theme={null}
        #!/usr/bin/env bash
        # Automation: Assess AKS Network Policy Enablement and Usage
        # Requirements: az, kubectl, jq
        # Run location: any machine with Azure CLI and kubectl access

        set -euo pipefail

        echo "=== 1. CLUSTER-LEVEL: AKS networkPolicy configuration ==="

        # List all AKS clusters in the subscription with their networkPolicy setting
        echo "[INFO] Listing AKS clusters and their network policy mode..."
        az aks list -o json | jq -r '
          .[] | [
            .name,
            .resourceGroup,
            (.networkProfile.networkPolicy // "null"),
            (.networkProfile.networkPlugin // "null")
          ] | @tsv' | column -t

        cat <<'EOF'

        [INTERPRETATION]
        - networkPolicy == "azure" or "calico": a network policy engine is enabled at the AKS control-plane level.
        - networkPolicy == "null" or empty: NO network policy engine is enabled on the cluster (finding).
        - networkPlugin:
            - "azure" or "kubenet" are compatible with Azure network policies, but you must still have networkPolicy set.
        EOF

        echo
        echo "=== 2. CLUSTER-LEVEL: Detailed view for a specific cluster (optional) ==="
        read -r -p "Enter AKS resource group for a specific cluster (or leave blank to skip): " AKS_RG || true
        if [ -n "${AKS_RG:-}" ]; then
          read -r -p "Enter AKS cluster name: " AKS_NAME
          echo
          echo "[INFO] az aks show for ${AKS_NAME} in ${AKS_RG}..."
          az aks show -g "${AKS_RG}" -n "${AKS_NAME}" -o json | jq '
            {
              name: .name,
              resourceGroup: .resourceGroup,
              kubernetesVersion: .kubernetesVersion,
              networkPlugin: .networkProfile.networkPlugin,
              networkPolicy: .networkProfile.networkPolicy,
              networkMode: .networkProfile.networkMode
            }'
          cat <<'EOF'

        [INTERPRETATION]
        - If .networkPolicy is null or not present: network policies are NOT enabled on this AKS cluster (finding).
        - If .networkPolicy is "azure" or "calico": a policy engine is enabled; proceed to namespace/pod-level review.
        EOF
        fi

        echo
        echo "=== 3. IN-CLUSTER: Namespaces lacking any NetworkPolicy ==="
        echo "[INFO] Using kubectl context: $(kubectl config current-context 2>/dev/null || echo 'UNKNOWN')"

        # Get namespaces that do NOT have any NetworkPolicy objects
        echo
        echo "[INFO] Discovering namespaces with zero NetworkPolicy objects..."
        # Build a set of namespaces that have at least one NetworkPolicy
        NS_WITH_NP=$(kubectl get networkpolicy --all-namespaces -o json 2>/dev/null \
          | jq -r '.items[].metadata.namespace' | sort -u || true)

        # Get all namespaces
        ALL_NS=$(kubectl get ns -o jsonpath='{range .items[*]}{.metadata.name}{"\n"}{end}')

        echo "Namespaces with NO NetworkPolicy objects:"
        MISSING_COUNT=0
        while read -r ns; do
          if ! grep -qx "$ns" <<<"$NS_WITH_NP"; then
            echo "  - $ns"
            MISSING_COUNT=$((MISSING_COUNT + 1))
          fi
        done <<<"$ALL_NS"

        cat <<EOF

        [INTERPRETATION]
        - Any namespace listed above currently has ZERO NetworkPolicy resources.
        - This typically indicates that pod traffic in those namespaces is wide open
          (subject only to cloud-level or node-level controls), not segmented per least privilege.
        - **Finding**: Namespaces that host sensitive workloads but appear here likely violate CIS AKS 5.4.4.
        EOF

        echo
        echo "=== 4. IN-CLUSTER: Namespaces with NetworkPolicy and their default posture ==="

        echo "[INFO] Listing namespaces that have at least one NetworkPolicy and summarizing default isolation..."

        # For each namespace that has at least one NetworkPolicy, check if any policy selects all pods with default deny
        for ns in $NS_WITH_NP; do
          echo
          echo "[NAMESPACE] $ns"

          # List policies
          kubectl get networkpolicy -n "$ns" -o wide || continue

          # Identify potential 'default deny ingress' policies
          DEFAULT_DENY_INGRESS=$(
            kubectl get networkpolicy -n "$ns" -o json \
              | jq -r '.items[]
                | select(
                    ((.spec.podSelector | has("matchLabels") | not) or (.spec.podSelector.matchLabels | length == 0))
                    and ((.spec.ingress | length == 0) or (.spec.policyTypes[]? == "Ingress"))
                  )
                | .metadata.name' || true
          )

          # Identify potential 'default deny egress' policies
          DEFAULT_DENY_EGRESS=$(
            kubectl get networkpolicy -n "$ns" -o json \
              | jq -r '.items[]
                | select(
                    ((.spec.podSelector | has("matchLabels") | not) or (.spec.podSelector.matchLabels | length == 0))
                    and ((.spec.egress | length == 0) or (.spec.policyTypes[]? == "Egress"))
                  )
                | .metadata.name' || true
          )

          echo
          if [ -n "$DEFAULT_DENY_INGRESS" ]; then
            echo "  Default-deny INGRESS policy candidates:"
            sed 's/^/    - /' <<<"$DEFAULT_DENY_INGRESS"
          else
            echo "  [WARNING] No clear default-deny INGRESS policy detected in this namespace."
          fi

          if [ -n "$DEFAULT_DENY_EGRESS" ]; then
            echo "  Default-deny EGRESS policy candidates:"
            sed 's/^/    - /' <<<"$DEFAULT_DENY_EGRESS"
          else
            echo "  [WARNING] No clear default-deny EGRESS policy detected in this namespace."
          fi

          cat <<'EOF_NS'

          [INTERPRETATION]
          - Presence of at least one 'default deny' policy (for ingress and/or egress) indicates
            a stronger, least-privilege stance.
          - Absence of any default deny policies suggests that traffic may still be overly permissive,
            even though NetworkPolicy objects exist.
        EOF_NS
        done

        echo
        echo "=== 5. SUMMARY ==="
        echo "Namespaces without any NetworkPolicy: ${MISSING_COUNT}"

        cat <<'EOF'

        [WHAT INDICATES A PROBLEM?]
        1. At cluster level (az aks show / az aks list):
           - networkPolicy is null, missing, or empty:
             -> Network policy engine is NOT enabled on the AKS cluster (CIS AKS 5.4.4 finding).
        2. At namespace level (kubectl checks):
           - Namespaces with no NetworkPolicy at all:
             -> Pods in those namespaces are likely not isolated by Kubernetes NetworkPolicy.
           - Namespaces with NetworkPolicy but lacking any default-deny-style policies:
             -> Policies may be too permissive; review against least-privilege requirements.

        [NOTE]
        This script only surfaces current configuration for review. Enabling or changing the
        network policy engine for AKS must be done through Azure (az aks, portal, or IaC),
        and per-namespace policy design requires manual security review.
        EOF
        ```
      </Accordion>
    </AccordionGroup>
  </Tab>
</Tabs>
