> ## 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. Identify non-system namespaces that lack a default-deny NetworkPolicy (run on any machine with kubectl access):
           ```bash 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
             | (($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)"
             ][]' | grep 'is_compliant=false' || echo "All non-system namespaces are compliant"
           ```

        2. For each non-compliant application namespace (replace `YOUR_NAMESPACE`), create a default-deny ingress NetworkPolicy manifest (run on any machine with kubectl access):
           ```bash theme={null}
           cat > deny-all-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 to the target namespace (run on any machine with kubectl access):
           ```bash theme={null}
           kubectl apply -f deny-all-ingress-YOUR_NAMESPACE.yaml
           ```

        4. (Optional but recommended) For each application namespace, create additional NetworkPolicies that explicitly allow only the required ingress flows for your workloads (run on any machine with kubectl access). Example skeleton to edit before applying:
           ```bash theme={null}
           cat > allow-required-ingress-YOUR_NAMESPACE.yaml << 'EOF'
           apiVersion: networking.k8s.io/v1
           kind: NetworkPolicy
           metadata:
             name: allow-required-ingress
             namespace: YOUR_NAMESPACE
           spec:
             podSelector:
               matchLabels:
                 app: YOUR_APP_LABEL
             policyTypes:
               - Ingress
             ingress:
               - from:
                   - namespaceSelector:
                       matchLabels:
                         name: ALLOWED_NAMESPACE
           EOF

           kubectl apply -f allow-required-ingress-YOUR_NAMESPACE.yaml
           ```

        5. Repeat steps 2–4 for each non-compliant application namespace you need to protect.

        6. Verify that every non-system namespace now has at least one default-deny ingress NetworkPolicy (run on any machine with kubectl access):
           ```bash 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
             | (($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)"
             ][]'
           ```
           Confirm there are no lines with `is_compliant=false`.
      </Accordion>

      <Accordion title="Using kubectl">
        Run these steps from any machine with kubectl access.

        ```bash theme={null}
        kubectl get namespaces \
          --no-headers \
          -o custom-columns='NAME:.metadata.name' \
          | grep -Ev '^(kube-system|kube-public|kube-node-lease)$' \
          | while read ns; do
            cat <<EOF | kubectl apply -n "$ns" -f -
        apiVersion: networking.k8s.io/v1
        kind: NetworkPolicy
        metadata:
          name: default-deny-ingress
        spec:
          podSelector: {}
          policyTypes:
          - Ingress
        EOF
          done
        ```

        If you prefer to apply to a specific namespace only, for example `production`:

        ```bash theme={null}
        cat <<EOF | kubectl apply -n production -f -
        apiVersion: networking.k8s.io/v1
        kind: NetworkPolicy
        metadata:
          name: default-deny-ingress
        spec:
          podSelector: {}
          policyTypes:
          - Ingress
        EOF
        ```

        Verification (same automated check logic):

        ```bash 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
          | (($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
        # Purpose: Ensure every non-system namespace in an EKS cluster has a default-deny
        #          ingress NetworkPolicy. Safe to re-run (idempotent).
        # Runs on: Any machine with kubectl access to the cluster.

        set -euo pipefail

        # 1. Discover target namespaces (exclude system namespaces)
        echo "Discovering non-system namespaces..."
        NAMESPACES=$(kubectl get namespaces -o jsonpath='{range .items[*]}{.metadata.name}{"\n"}{end}' | \
          grep -vE '^(kube-system|kube-public|kube-node-lease)$' || true)

        if [ -z "${NAMESPACES}" ]; then
          echo "No non-system namespaces found. Nothing to do."
          exit 0
        fi

        # 2. Apply/ensure default-deny ingress NetworkPolicy in each namespace
        #    - Empty podSelector: applies to all pods
        #    - policyTypes: [Ingress]
        #    - No ingress rules: deny all ingress
        for ns in ${NAMESPACES}; do
          echo "Ensuring default-deny ingress NetworkPolicy in namespace: ${ns}"

          # Use a consistent name so it's easy to manage later
          # This is idempotent: apply will create or update as needed.
          cat <<EOF | kubectl apply -f -
        apiVersion: networking.k8s.io/v1
        kind: NetworkPolicy
        metadata:
          name: default-deny-ingress
          namespace: ${ns}
          labels:
            security.cloudanix.com/default-deny: "true"
        spec:
          podSelector: {}
          policyTypes:
          - Ingress
        EOF

        done

        # 3. Verification (adapted from the audit command)
        echo "Verifying default-deny ingress NetworkPolicy presence in all non-system namespaces..."
        {
          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'

        echo "Automation complete."
        ```
      </Accordion>
    </AccordionGroup>
  </Tab>
</Tabs>
