> ## 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 That All Namespaces Have Network Policies Defined

### More Info:

Use network policies to isolate traffic in your cluster network.

### Risk Level

Low

### Address

Security

### Compliance Standards

* APRA CPS 234 (Australia)
* BSI C5 (Germany)
* Brazil LGPD
* CCPA / CPRA (California)
* CIS Critical Security Controls v8
* CIS EKS
* CMMC 2.0
* CSA Cloud Controls Matrix v4
* DPDPA
* Digital Operational Resilience Act (EU)
* Essential 8
* ISO/IEC 27017
* ISO/IEC 27018
* ISO/IEC 27701
* KSA PDPL
* MAS Technology Risk Management (Singapore)
* MITRE ATT\&CK (Cloud)
* 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

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

    <AccordionGroup>
      <Accordion title="Manual Steps" defaultOpen="true">
        1. List namespaces that currently lack any NetworkPolicy (run on any machine with kubectl access):
           ```sh theme={null}
           ns_without_np=$(kubectl get namespaces -o json | jq -r '.items[].metadata.name' | while read ns; do
             count=$(kubectl get networkpolicy -n "$ns" --no-headers 2>/dev/null | wc -l)
             if [ "$count" -eq 0 ]; then echo "$ns"; fi
           done)
           echo "$ns_without_np"
           ```

        2. For each namespace in the list, decide the default isolation behavior you want:
           * **Most restrictive** (recommended starting point): deny all ingress and egress by default, then create additional NetworkPolicies later to allow required flows.
           * **Ingress-only isolation**: deny all ingress but allow all egress.
           * **Custom**: define specific allowed selectors/ports/namespaces as needed.

        3. To apply a **default deny all ingress and egress** NetworkPolicy for one namespace (replace `TARGET_NAMESPACE` with the namespace name; run on any machine with kubectl access):
           ```sh theme={null}
           kubectl apply -f - <<'EOF'
           apiVersion: networking.k8s.io/v1
           kind: NetworkPolicy
           metadata:
             name: default-deny-all
             namespace: TARGET_NAMESPACE
           spec:
             podSelector: {}
             policyTypes:
               - Ingress
               - Egress
           EOF
           ```

        4. If you prefer to **only deny ingress** and leave egress open for a namespace (replace `TARGET_NAMESPACE`; run on any machine with kubectl access):
           ```sh theme={null}
           kubectl apply -f - <<'EOF'
           apiVersion: networking.k8s.io/v1
           kind: NetworkPolicy
           metadata:
             name: default-deny-ingress
             namespace: TARGET_NAMESPACE
           spec:
             podSelector: {}
             policyTypes:
               - Ingress
           EOF
           ```

        5. For critical namespaces (for example `kube-system`, monitoring, logging), review application requirements before applying default deny:
           * List pods and labels to plan selectors:
             ```sh theme={null}
             kubectl get pods -n TARGET_NAMESPACE --show-labels
             ```
           * Start with default deny (Step 3 or 4), then iteratively add additional NetworkPolicies that:
             * Select specific pods via `podSelector.matchLabels`
             * Allow required `ingress`/`egress` based on `from`/`to` (e.g., namespaceSelector, podSelector, ipBlock) and `ports`.

        6. Verify that all namespaces now have at least one NetworkPolicy (run on any machine with kubectl access):
           ```sh theme={null}
           ns_without_np=$(kubectl get namespaces -o json | jq -r '.items[].metadata.name' | while read ns; do
             count=$(kubectl get networkpolicy -n "$ns" --no-headers 2>/dev/null | wc -l)
             if [ "$count" -eq 0 ]; then echo "$ns"; fi
           done)
           if [ -z "$ns_without_np" ]; then
             echo "ALL_NAMESPACES_HAVE_NETWORK_POLICIES"
           else
             echo "NAMESPACES_WITHOUT_NETWORK_POLICIES: $ns_without_np"
           fi
           ```
      </Accordion>

      <Accordion title="Using kubectl">
        On any machine with kubectl access:

        1. Identify namespaces without NetworkPolicies (reuse the audit logic)

        ```bash theme={null}
        ns_without_np=$(kubectl get namespaces -o json | jq -r '.items[].metadata.name' | while read ns; do
          count=$(kubectl get networkpolicy -n "$ns" --no-headers 2>/dev/null | wc -l)
          if [ "$count" -eq 0 ]; then echo "$ns"; fi
        done)

        echo "$ns_without_np"
        ```

        2. For each listed namespace, create at least one NetworkPolicy. Below is a conservative default‑deny ingress and allow‑all egress policy you can apply per namespace (replace NAMESPACE\_HERE each time):

        Create a manifest file, for example:

        ```bash theme={null}
        cat << 'EOF' > default-netpol-namespace-here.yaml
        apiVersion: networking.k8s.io/v1
        kind: NetworkPolicy
        metadata:
          name: default-deny-ingress-allow-all-egress
          namespace: NAMESPACE_HERE
        spec:
          podSelector: {}
          policyTypes:
            - Ingress
            - Egress
          ingress: []
          egress:
            - {}
        EOF
        ```

        Apply it to the target namespace:

        ```bash theme={null}
        kubectl apply -f default-netpol-namespace-here.yaml
        ```

        Repeat editing `namespace: NAMESPACE_HERE` and applying for each namespace in `$ns_without_np`. Example loop to generate and apply identical policy to every namespace missing one:

        ```bash theme={null}
        for ns in $ns_without_np; do
          cat << EOF | kubectl apply -f -
        apiVersion: networking.k8s.io/v1
        kind: NetworkPolicy
        metadata:
          name: default-deny-ingress-allow-all-egress
          namespace: $ns
        spec:
          podSelector: {}
          policyTypes:
            - Ingress
            - Egress
          ingress: []
          egress:
            - {}
        EOF
        done
        ```

        3. Verification (same machine with kubectl):

        ```bash theme={null}
        ns_without_np=$(kubectl get namespaces -o json | jq -r '.items[].metadata.name' | while read ns; do
          count=$(kubectl get networkpolicy -n "$ns" --no-headers 2>/dev/null | wc -l)
          if [ "$count" -eq 0 ]; then echo "$ns"; fi
        done)
        if [ -z "$ns_without_np" ]; then
          echo "ALL_NAMESPACES_HAVE_NETWORK_POLICIES"
        else
          echo "NAMESPACES_WITHOUT_NETWORK_POLICIES: $ns_without_np"
        fi
        ```
      </Accordion>

      <Accordion title="Automation">
        ```bash theme={null}
        #!/usr/bin/env bash
        set -euo pipefail

        # This script:
        # - Finds all namespaces without any NetworkPolicy
        # - Creates a default-deny NetworkPolicy in each such namespace
        # - Is safe to re-run (it uses kubectl apply)
        # - Verifies that all namespaces now have at least one NetworkPolicy
        #
        # Run on: any machine with kubectl access and jq installed.

        # Fail fast if required tools are missing
        for cmd in kubectl jq; do
          if ! command -v "$cmd" >/dev/null 2>&1; then
            echo "ERROR: $cmd is required but not installed or not in PATH." >&2
            exit 1
          fi
        done

        # Optional: restrict to "active" namespaces (ignore those in Terminating phase)
        namespaces_json=$(kubectl get namespaces -o json)

        # Find namespaces with zero NetworkPolicies
        ns_without_np=()
        while IFS= read -r ns; do
          # Skip namespaces that are Terminating
          phase=$(echo "$namespaces_json" | jq -r ".items[] | select(.metadata.name==\"$ns\") | .status.phase")
          if [ "$phase" != "Active" ]; then
            continue
          fi

          count=$(kubectl get networkpolicy -n "$ns" --no-headers 2>/dev/null | wc -l | tr -d ' ')
          if [ "$count" -eq 0 ]; then
            ns_without_np+=("$ns")
          fi
        done < <(echo "$namespaces_json" | jq -r '.items[].metadata.name')

        if [ "${#ns_without_np[@]}" -eq 0 ]; then
          echo "ALL_NAMESPACES_ALREADY_HAVE_NETWORK_POLICIES"
        else
          echo "NAMESPACES_MISSING_NETWORK_POLICIES: ${ns_without_np[*]}"
          echo "Creating default-deny NetworkPolicy in each missing namespace..."

          for ns in "${ns_without_np[@]}"; do
            cat <<EOF | kubectl apply -n "$ns" -f -
        apiVersion: networking.k8s.io/v1
        kind: NetworkPolicy
        metadata:
          name: default-deny-all
        spec:
          podSelector: {}
          policyTypes:
          - Ingress
          - Egress
        EOF
          done
        fi

        echo "Verifying that all namespaces have at least one NetworkPolicy..."

        verify_ns_without_np=$(kubectl get namespaces -o json | jq -r '.items[].metadata.name' | while read -r ns; do
          # Skip namespaces that are Terminating
          phase=$(kubectl get namespace "$ns" -o jsonpath='{.status.phase}' 2>/dev/null || echo "")
          if [ "$phase" != "Active" ]; then
            continue
          fi
          count=$(kubectl get networkpolicy -n "$ns" --no-headers 2>/dev/null | wc -l | tr -d ' ')
          if [ "$count" -eq 0 ]; then echo "$ns"; fi
        done)

        if [ -z "$verify_ns_without_np" ]; then
          echo "ALL_NAMESPACES_HAVE_NETWORK_POLICIES"
          exit 0
        else
          echo "NAMESPACES_STILL_WITHOUT_NETWORK_POLICIES: $verify_ns_without_np" >&2
          exit 1
        fi
        ```
      </Accordion>
    </AccordionGroup>
  </Tab>
</Tabs>

### Additional Reading:

* [https://kubernetes.io/docs/concepts/services-networking/networkpolicies/](https://kubernetes.io/docs/concepts/services-networking/networkpolicies/)
