> ## 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.

# Every Non-System Namespace Should Have A Default-Deny NetworkPolicy

### More Info:

Verifies each application namespace has a default-deny ingress NetworkPolicy. Without one, every pod is reachable from every other pod.

### Risk Level

High

### Address

Security

### Compliance Standards

* Cloudanix Best Practice

### Triage and Remediation

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

    <AccordionGroup>
      <Accordion title="Manual Steps" defaultOpen="true">
        1. List non-system namespaces that are missing a default-deny ingress NetworkPolicy (run on any machine with kubectl access):
           ```sh theme={null}
           { kubectl get networkpolicies --all-namespaces -o json \
             kubectl get namespaces -o json; } | jq -rs '
             .[0] as $nps | .[1] |
             [ .items[]
             | select(.metadata.name as $n | ["kube-system","kube-public","kube-node-lease"] | index($n) | not)
             | .metadata as $m
             | ([ $nps.items[]
                  | select(.metadata.namespace == $m.name)
                  | select((.spec.podSelector == {}) or (.spec.podSelector.matchLabels == null and .spec.podSelector.matchExpressions == null))
                  | select((.spec.policyTypes // []) | index("Ingress")) ] | length) as $deny
             | select($deny == 0)
             | .name ' -r
           ```

        2. For one non-compliant namespace (replace `your-namespace` with the actual name), create a manifest file defining a default-deny ingress NetworkPolicy (run on any machine with kubectl access):
           ```sh theme={null}
           cat > default-deny-ingress-your-namespace.yaml << 'EOF'
           apiVersion: networking.k8s.io/v1
           kind: NetworkPolicy
           metadata:
             name: default-deny-ingress
             namespace: your-namespace
           spec:
             podSelector: {}
             policyTypes:
             - Ingress
           EOF
           ```

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

        4. Repeat steps 2–3 for each non-system namespace reported in step 1, changing the filename and the `namespace:` field (run on any machine with kubectl access).

        5. (Optional but recommended) Define additional, more specific NetworkPolicies in each namespace to allow only the necessary ingress flows for your applications (run on any machine with kubectl access, using your own manifests and requirements):
           ```sh theme={null}
           kubectl apply -f your-allow-policy.yaml
           ```

        6. Verify that every non-system namespace now has at least one default-deny ingress NetworkPolicy (run on any machine with kubectl access):
           ```sh theme={null}
           { kubectl get networkpolicies --all-namespaces -o json \
             kubectl get namespaces -o json; } | jq -rs '
             .[0] as $nps | .[1] |
             [ .items[]
             | select(.metadata.name as $n | ["kube-system","kube-public","kube-node-lease"] | index($n) | not)
             | .metadata as $m
             | ([ $nps.items[]
                  | select(.metadata.namespace == $m.name)
                  | select((.spec.podSelector == {}) or (.spec.podSelector.matchLabels == null and .spec.podSelector.matchExpressions == null))
                  | select((.spec.policyTypes // []) | index("Ingress")) ] | length) as $deny
             | "kind=Namespace name=\($m.name) defaultDenyPolicies=\($deny)"
               + " is_compliant=\(if $deny > 0 then "true" else "false" end)"
             ] as $rows
             | if ($rows | map(select(. | test("is_compliant=false"))) | length) == 0
               then "is_compliant=true"
               else $rows[]
               end'
           ```
      </Accordion>

      <Accordion title="Using kubectl">
        ```bash theme={null}
        # 1) List non-system namespaces and see which lack default-deny
        # Run on: any machine with kubectl access
        kubectl get ns

        # 2) For each *application* namespace that should be isolated, create a default-deny NetworkPolicy.
        # Replace <NAMESPACE> with the target namespace name.

        cat <<'EOF' | kubectl apply -f -
        apiVersion: networking.k8s.io/v1
        kind: NetworkPolicy
        metadata:
          name: default-deny-ingress
          namespace: <NAMESPACE>
        spec:
          podSelector: {}
          policyTypes:
            - Ingress
        EOF

        # Example for namespace "payments"
        cat <<'EOF' | kubectl apply -f -
        apiVersion: networking.k8s.io/v1
        kind: NetworkPolicy
        metadata:
          name: default-deny-ingress
          namespace: payments
        spec:
          podSelector: {}
          policyTypes:
            - Ingress
        EOF

        # 3) (Optional but recommended) Store the manifest in Git/IaC.
        # Example manifest file you can commit, parameterized per namespace:

        # file: networkpolicy-default-deny-ingress-payments.yaml
        apiVersion: networking.k8s.io/v1
        kind: NetworkPolicy
        metadata:
          name: default-deny-ingress
          namespace: payments
        spec:
          podSelector: {}
          policyTypes:
            - Ingress

        # Apply it:
        kubectl apply -f networkpolicy-default-deny-ingress-payments.yaml
        ```

        Verification (adapted from the audit):

        ```bash theme={null}
        # Run on: any machine with kubectl access
        { kubectl get networkpolicies --all-namespaces -o json \
          kubectl get namespaces -o json; } | jq -rs '
          .[0] as $nps | .[1] |
          [ .items[]
          | select(.metadata.name as $n | ["kube-system","kube-public","kube-node-lease"] | index($n) | not)
          | .metadata as $m
          | (($m.labels // {}) | to_entries | map("\(.key):\(.value)") | join(",")) as $labels
          | ([ $nps.items[]
               | select(.metadata.namespace == $m.name)
               | select((.spec.podSelector == {}) or (.spec.podSelector.matchLabels == null and .spec.podSelector.matchExpressions == null))
               | select((.spec.policyTypes // []) | index("Ingress")) ] | length) as $deny
          | "kind=Namespace name=\($m.name) uid=\($m.uid) apiVersion=v1"
            + (if ($m.creationTimestamp // "") == "" then "" else " created=\($m.creationTimestamp)" end)
            + (if $labels == "" then "" else " labels=\($labels)" end)
            + " defaultDenyPolicies=\($deny)"
            + " is_compliant=\(if $deny > 0 then "true" else "false" end)"
          ] as $rows
          | if ($rows | length) == 0 then "is_compliant=true" else $rows[] end'
        ```
      </Accordion>

      <Accordion title="Automation">
        ```bash theme={null}
        #!/usr/bin/env bash
        #
        # Ensure every non-system namespace in a GKE cluster has a default-deny
        # ingress NetworkPolicy, per CBP C3.1.
        #
        # Requirements:
        # - Run on any machine with kubectl access and sufficient RBAC
        # - kubectl configured for the target GKE cluster/context
        #
        # Safe to re-run: uses create --dry-run=client | apply for idempotency.

        set -euo pipefail

        # Name of the default-deny policy to enforce in each namespace
        POLICY_NAME="default-deny-ingress"

        echo "Discovering non-system namespaces..."

        # Get all namespaces except the standard system ones
        mapfile -t NAMESPACES < <(
          kubectl get namespaces -o jsonpath='{range .items[*]}{.metadata.name}{"\n"}{end}' \
          | grep -Ev '^(kube-system|kube-public|kube-node-lease)$' \
          || true
        )

        if [ "${#NAMESPACES[@]}" -eq 0 ]; then
          echo "No non-system namespaces found."
        else
          for ns in "${NAMESPACES[@]}"; do
            [ -z "$ns" ] && continue
            echo "Ensuring default-deny ingress NetworkPolicy in namespace: ${ns}"

            # Create-or-update a default-deny ingress NetworkPolicy:
            # - empty podSelector => applies to all pods in the namespace
            # - policyTypes: [Ingress] => denies all ingress by default
            kubectl create networkpolicy "${POLICY_NAME}" \
              --namespace "${ns}" \
              --pod-selector='' \
              --ingress='{}' \
              --dry-run=client -o yaml \
            | kubectl apply -f -
          done
        fi

        echo
        echo "Verification: checking that every non-system namespace has at least one"
        echo "default-deny ingress NetworkPolicy (empty podSelector, policyTypes includes Ingress)."
        echo

        { kubectl get networkpolicies --all-namespaces -o json
          kubectl get namespaces -o json
        } | jq -rs '
          .[0] as $nps | .[1] |
          [ .items[]
          | select(.metadata.name as $n | ["kube-system","kube-public","kube-node-lease"] | index($n) | not)
          | .metadata as $m
          | (($m.labels // {}) | to_entries | map("\(.key):\(.value)") | join(",")) as $labels
          | ([ $nps.items[]
               | select(.metadata.namespace == $m.name)
               | select((.spec.podSelector == {}) or (.spec.podSelector.matchLabels == null and .spec.podSelector.matchExpressions == null))
               | select((.spec.policyTypes // []) | index("Ingress")) ] | length) as $deny
          | "kind=Namespace name=\($m.name) uid=\($m.uid) apiVersion=v1"
            + (if ($m.creationTimestamp // "") == "" then "" else " created=\($m.creationTimestamp)" end)
            + (if $labels == "" then "" else " labels=\($labels)" end)
            + " defaultDenyPolicies=\($deny)"
            + " is_compliant=\(if $deny > 0 then "true" else "false" end)"
          ] as $rows
          | if ($rows | length) == 0 then "is_compliant=true" else $rows[] end'
        ```
      </Accordion>
    </AccordionGroup>
  </Tab>
</Tabs>
