> ## 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 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 GKE
* 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 are missing NetworkPolicies (run on any machine with kubectl access):
           ```bash theme={null}
           (kubectl get ns -o json; kubectl get networkpolicy -A -o json) \
           | jq -rs '
             (.[0].items | map(.metadata.name)
              | map(select(.!="kube-system" and .!="kube-public" and .!="kube-node-lease"))) as $ns
             |
             ( (.[1].items // [])
               | sort_by(.metadata.namespace)
               | group_by(.metadata.namespace)
               | map({key: .[0].metadata.namespace, value: length})
               | from_entries
             ) as $np
             |
             [ $ns[] | select( ($np[.] // 0) == 0 ) ] as $missing
             |
             $missing[]'
           ```
           Note the namespace names returned; each needs at least one NetworkPolicy.

        2. For each namespace without a NetworkPolicy, create a default deny-all NetworkPolicy manifest file on your local machine (with kubectl access). Example for namespace `example-namespace`:
           ```bash theme={null}
           cat > default-deny-all-example-namespace.yaml <<'EOF'
           apiVersion: networking.k8s.io/v1
           kind: NetworkPolicy
           metadata:
             name: default-deny-all
             namespace: example-namespace
           spec:
             podSelector: {}
             policyTypes:
               - Ingress
               - Egress
           EOF
           ```

        3. Apply the NetworkPolicy for that namespace (run on any machine with kubectl access):
           ```bash theme={null}
           kubectl apply -f default-deny-all-example-namespace.yaml
           ```

        4. (Optional but recommended) For application namespaces where you need traffic, design and apply more granular NetworkPolicies that allow required ingress/egress. Example allow ingress from same namespace for `example-namespace`:
           ```bash theme={null}
           cat > allow-same-namespace-example-namespace.yaml <<'EOF'
           apiVersion: networking.k8s.io/v1
           kind: NetworkPolicy
           metadata:
             name: allow-same-namespace
             namespace: example-namespace
           spec:
             podSelector: {}
             policyTypes:
               - Ingress
             ingress:
               - from:
                   - podSelector: {}
           EOF

           kubectl apply -f allow-same-namespace-example-namespace.yaml
           ```

        5. Repeat steps 2–4 for each namespace reported in step 1, adjusting the `namespace:` field and filenames accordingly.

        6. Verification (run on any machine with kubectl access):
           ```bash theme={null}
           (kubectl get ns -o json; kubectl get networkpolicy -A -o json) \
           | jq -rs '
             (.[0].items | map(.metadata.name)
              | map(select(.!="kube-system" and .!="kube-public" and .!="kube-node-lease"))) as $ns
             |
             ( (.[1].items // [])
               | sort_by(.metadata.namespace)
               | group_by(.metadata.namespace)
               | map({key: .[0].metadata.namespace, value: length})
               | from_entries
             ) as $np
             |
             [ $ns[] | select( ($np[.] // 0) == 0 ) ] as $missing
             |
             if ($missing|length)>0
             then ($missing[] | "FOUND_NAMESPACE_WITHOUT_NETWORKPOLICY:"+.)
             else "ALL_NAMESPACES_HAVE_NETWORK_POLICIES"
             end
           '
           ```
           Confirm the output is:
           ```text theme={null}
           "ALL_NAMESPACES_HAVE_NETWORK_POLICIES"
           ```
      </Accordion>

      <Accordion title="Using kubectl">
        ```bash theme={null}
        # 1) Identify namespaces missing NetworkPolicies
        # Run on: any machine with kubectl access
        (kubectl get ns -o json; kubectl get networkpolicy -A -o json) \
        | jq -rs '
          (.[0].items | map(.metadata.name)
           | map(select(.!="kube-system" and .!="kube-public" and .!="kube-node-lease"))) as $ns
          |
          ( (.[1].items // [])
            | sort_by(.metadata.namespace)
            | group_by(.metadata.namespace)
            | map({key: .[0].metadata.namespace, value: length})
            | from_entries
          ) as $np
          |
          [ $ns[] | select( ($np[.] // 0) == 0 ) ] as $missing
          |
          if ($missing|length)>0
          then ($missing[] | "FOUND_NAMESPACE_WITHOUT_NETWORKPOLICY:"+.)
          else "ALL_NAMESPACES_HAVE_NETWORK_POLICIES"
          end
        '
        ```

        Create a baseline “default-deny ingress” NetworkPolicy for each application namespace that is missing one. Adjust namespaces and allowed traffic as appropriate for your environment.

        Example: if the audit output contains:

        * `FOUND_NAMESPACE_WITHOUT_NETWORKPOLICY:dev`
        * `FOUND_NAMESPACE_WITHOUT_NETWORKPOLICY:prod`

        create policies like below.

        ```bash theme={null}
        # 2) Create a default-deny ingress NetworkPolicy for namespace 'dev'
        # Run on: any machine with kubectl access
        cat <<'EOF' | kubectl apply -f -
        apiVersion: networking.k8s.io/v1
        kind: NetworkPolicy
        metadata:
          name: default-deny-ingress
          namespace: dev
        spec:
          podSelector: {}
          policyTypes:
            - Ingress
          ingress: []
        EOF

        # 3) Create a default-deny ingress NetworkPolicy for namespace 'prod'
        cat <<'EOF' | kubectl apply -f -
        apiVersion: networking.k8s.io/v1
        kind: NetworkPolicy
        metadata:
          name: default-deny-ingress
          namespace: prod
        spec:
          podSelector: {}
          policyTypes:
            - Ingress
          ingress: []
        EOF
        ```

        If you want to allow intra-namespace traffic but still isolate from other namespaces, use this pattern instead:

        ```bash theme={null}
        # Example allow-same-namespace ingress for namespace 'dev'
        cat <<'EOF' | kubectl apply -f -
        apiVersion: networking.k8s.io/v1
        kind: NetworkPolicy
        metadata:
          name: allow-same-namespace-ingress
          namespace: dev
        spec:
          podSelector: {}
          policyTypes:
            - Ingress
          ingress:
            - from:
                - podSelector: {}
        EOF
        ```

        Repeat for each non-excluded namespace reported by the audit until all have at least one appropriate NetworkPolicy.

        ```bash theme={null}
        # 4) Verification: confirm all non-system namespaces now have NetworkPolicies
        # Run on: any machine with kubectl access
        (kubectl get ns -o json; kubectl get networkpolicy -A -o json) \
        | jq -rs '
          (.[0].items | map(.metadata.name)
           | map(select(.!="kube-system" and .!="kube-public" and .!="kube-node-lease"))) as $ns
          |
          ( (.[1].items // [])
            | sort_by(.metadata.namespace)
            | group_by(.metadata.namespace)
            | map({key: .[0].metadata.namespace, value: length})
            | from_entries
          ) as $np
          |
          [ $ns[] | select( ($np[.] // 0) == 0 ) ] as $missing
          |
          if ($missing|length)>0
          then ($missing[] | "FOUND_NAMESPACE_WITHOUT_NETWORKPOLICY:"+.)
          else "ALL_NAMESPACES_HAVE_NETWORK_POLICIES"
          end
        '
        ```
      </Accordion>

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

        # This script:
        # - Detects namespaces without any NetworkPolicy (excluding kube-system, kube-public, kube-node-lease)
        # - Creates a default deny-all ingress/egress NetworkPolicy per such namespace
        # - Is safe to re-run (it will not overwrite an existing policy)
        # - Verifies that all namespaces now have at least one NetworkPolicy

        # Run from any machine with kubectl access and the desired context set.

        # 1. Detect namespaces missing NetworkPolicies
        echo "[*] Detecting namespaces without any NetworkPolicy..."

        missing_ns=$(
          (kubectl get ns -o json; kubectl get networkpolicy -A -o json) \
          | jq -rs '
              (.[0].items | map(.metadata.name)
               | map(select(.!="kube-system" and .!="kube-public" and .!="kube-node-lease"))) as $ns
              |
              ( (.[1].items // [])
                | sort_by(.metadata.namespace)
                | group_by(.metadata.namespace)
                | map({key: .[0].metadata.namespace, value: length})
                | from_entries
              ) as $np
              |
              [ $ns[] | select( ($np[.] // 0) == 0 ) ] as $missing
              |
              $missing[]
            ' 2>/dev/null || true
        )

        if [[ -z "${missing_ns}" ]]; then
          echo "[*] ALL_NAMESPACES_HAVE_NETWORK_POLICIES (no changes required)"
        else
          echo "[*] Namespaces without NetworkPolicy:"
          printf '  - %s\n' ${missing_ns}

          # 2. Create a default deny-all NetworkPolicy in each missing namespace
          #    This follows the benchmark remediation: create NetworkPolicy objects as needed.
          #    You may later refine these policies to meet your application's needs.
          echo "[*] Creating default deny-all NetworkPolicy in each missing namespace..."

          # Template for the policy (namespaced via kubectl -n)
          read -r -d '' NP_TEMPLATE <<'EOF'
        apiVersion: networking.k8s.io/v1
        kind: NetworkPolicy
        metadata:
          name: default-deny-all
        spec:
          podSelector: {}
          policyTypes:
          - Ingress
          - Egress
        EOF

          for ns in ${missing_ns}; do
            echo "  -> Processing namespace: ${ns}"

            # Idempotency safeguard: if *any* NetworkPolicy already exists (race condition), skip
            if kubectl get networkpolicy -n "${ns}" >/dev/null 2>&1; then
              echo "     Skipping: namespace ${ns} now has at least one NetworkPolicy"
              continue
            fi

            # Create the default deny-all NetworkPolicy if it does not exist
            if ! kubectl get networkpolicy default-deny-all -n "${ns}" >/dev/null 2>&1; then
              echo "     Creating NetworkPolicy default-deny-all in ${ns}"
              printf '%s\n' "${NP_TEMPLATE}" | kubectl apply -n "${ns}" -f -
            else
              echo "     NetworkPolicy default-deny-all already exists in ${ns}, skipping"
            fi
          done
        fi

        # 3. Verification: re-run the audit to ensure compliance
        echo "[*] Verifying that all namespaces now have at least one NetworkPolicy..."

        (kubectl get ns -o json; kubectl get networkpolicy -A -o json) \
        | jq -rs '
          (.[0].items | map(.metadata.name)
           | map(select(.!="kube-system" and .!="kube-public" and .!="kube-node-lease"))) as $ns
          |
          ( (.[1].items // [])
            | sort_by(.metadata.namespace)
            | group_by(.metadata.namespace)
            | map({key: .[0].metadata.namespace, value: length})
            | from_entries
          ) as $np
          |
          [ $ns[] | select( ($np[.] // 0) == 0 ) ] as $missing
          |
          if ($missing|length)>0
          then ($missing[] | "FOUND_NAMESPACE_WITHOUT_NETWORKPOLICY:"+.)
          else "ALL_NAMESPACES_HAVE_NETWORK_POLICIES"
          end
        '
        ```
      </Accordion>
    </AccordionGroup>
  </Tab>
</Tabs>

### Additional Reading:

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