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

# Minimize The Admission Of Containers Sharing The Host Network Namespace

### More Info:

Sharing the host network namespace gives a container access to host network interfaces and local services, bypassing network controls. Restrict it.

### Risk Level

High

### Address

Security

### Compliance Standards

* CIS Kubernetes

### Triage and Remediation

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

    <AccordionGroup>
      <Accordion title="Manual Steps" defaultOpen="true">
        1. List all Pods using `hostNetwork` (run on any machine with kubectl access):
           ```bash theme={null}
           kubectl get pods --all-namespaces -o jsonpath='{range .items[?(@.spec.hostNetwork==true)]}{.metadata.namespace}{" "}{.metadata.name}{"\n"}{end}'
           ```

        2. For each affected Pod, identify its owning workload (run on any machine with kubectl access). Replace NAMESPACE and POD with real values from step 1:
           ```bash theme={null}
           NAMESPACE=example-namespace
           POD=example-pod

           kubectl get pod "$POD" -n "$NAMESPACE" -o jsonpath='{.metadata.ownerReferences}' | jq
           ```
           Use the `kind` and `name` fields to determine if it is controlled by a Deployment, DaemonSet, StatefulSet, Job, etc., or is a standalone Pod.

        3. For each *standalone* Pod that should not use host networking, edit the Pod spec and plan a recreation (run on any machine with kubectl access):
           ```bash theme={null}
           # Export the Pod spec (without cluster-assigned fields)
           kubectl get pod "$POD" -n "$NAMESPACE" -o yaml \
             | sed '/^\s*uid:/d;/^\s*resourceVersion:/d;/^\s*selfLink:/d;/^\s*creationTimestamp:/d;/^\s*status:/d' \
             > "/tmp/${NAMESPACE}-${POD}-pod.yaml"

           # Edit hostNetwork to false (or remove the field)
           sed -i 's/hostNetwork: true/hostNetwork: false/' "/tmp/${NAMESPACE}-${POD}-pod.yaml"

           # Delete and recreate the Pod from the modified manifest
           kubectl delete pod "$POD" -n "$NAMESPACE"
           kubectl apply -f "/tmp/${NAMESPACE}-${POD}-pod.yaml"
           ```

        4. For each *controller-managed* workload (Deployment/DaemonSet/StatefulSet/Job) that should not use host networking, edit the controller spec (run on any machine with kubectl access). Example for a Deployment:
           ```bash theme={null}
           NAMESPACE=example-namespace
           DEPLOYMENT=example-deployment

           kubectl -n "$NAMESPACE" get deployment "$DEPLOYMENT" -o yaml > "/tmp/${NAMESPACE}-${DEPLOYMENT}.yaml"
           sed -i 's/hostNetwork: true/hostNetwork: false/' "/tmp/${NAMESPACE}-${DEPLOYMENT}.yaml"
           kubectl apply -f "/tmp/${NAMESPACE}-${DEPLOYMENT}.yaml"
           ```
           Repeat with `deployment` replaced by `daemonset`, `statefulset`, or `job` as appropriate.

        5. Add a restrictive admission policy in each user-workload namespace to prevent new `hostNetwork` Pods (run on any machine with kubectl access). Example using a Kubernetes-native `PodSecurityPolicy`-like Gatekeeper constraint is cluster-specific; if you do not have an admission controller already in place, document and implement one via your chosen policy engine (e.g., Kyverno, Gatekeeper) that rejects Pods with `spec.hostNetwork: true` in user namespaces, with explicit exceptions for justified system workloads.

        6. Verify no remaining Pods use `hostNetwork` (run on any machine with kubectl access):
           ```bash theme={null}
           kubectl get pods --all-namespaces -o custom-columns=POD_NAME:.metadata.name,POD_NAMESPACE:.metadata.namespace --no-headers | while read -r pod_name pod_namespace
           do
             pod_hostnetwork=$(kubectl get pod "${pod_name}" --namespace "${pod_namespace}" -o jsonpath='{.spec.hostNetwork}' 2>/dev/null)
             if [ -z "${pod_hostnetwork}" ]; then
               pod_hostnetwork="false"
             fi
             echo "***pod_name: ${pod_name} pod_namespace: ${pod_namespace} is_pod_hostnetwork: ${pod_hostnetwork} is_compliant: $([ "${pod_hostnetwork}" = "true" ] && echo false || echo true)"
           done | grep 'is_pod_hostnetwork: true' || echo "All pods compliant (no hostNetwork: true)"
           ```
      </Accordion>

      <Accordion title="Using kubectl">
        ```bash theme={null}
        # 1) Identify pods using hostNetwork (any machine with kubectl access)
        kubectl get pods --all-namespaces -o=jsonpath='{range .items[?(@.spec.hostNetwork==true)]}{.metadata.namespace}{" "}{.metadata.name}{"\n"}{end}'

        # 2) For each NON‑system namespace with hostNetwork pods, create a restrictive NetworkPolicy or AdmissionPolicy.
        # Example: deny hostNetwork in a user namespace "production"

        # 2a) (Preferred, if you have a validating admission controller such as Kyverno)
        # Save this as deny-hostnetwork-kyverno.yaml and apply it.
        cat << 'EOF' > deny-hostnetwork-kyverno.yaml
        apiVersion: kyverno.io/v1
        kind: ClusterPolicy
        metadata:
          name: disallow-hostnetwork
        spec:
          validationFailureAction: enforce
          background: true
          rules:
          - name: disallow-hostnetwork
            match:
              any:
              - resources:
                  kinds:
                  - Pod
                  namespaces:
                  - production
            validate:
              message: "Use of hostNetwork is not allowed in this namespace."
              pattern:
                spec:
                  =(hostNetwork): "false"
        EOF

        kubectl apply -f deny-hostnetwork-kyverno.yaml

        # 2b) Example Gatekeeper (OPA) constraint to disallow hostNetwork in a namespace
        # (Assumes the corresponding ConstraintTemplate exists in the cluster.)
        cat << 'EOF' > k8sdisallowhostnetwork-constraint.yaml
        apiVersion: constraints.gatekeeper.sh/v1beta1
        kind: K8sDisallowHostNetwork
        metadata:
          name: disallow-hostnetwork-production
        spec:
          match:
            kinds:
            - apiGroups: [""]
              kinds: ["Pod"]
            namespaces:
            - production
        EOF

        kubectl apply -f k8sdisallowhostnetwork-constraint.yaml

        # 3) Remove or edit existing manifests that set hostNetwork: true (any machine with kubectl access)
        # Example: export, edit, and reapply one offending pod in a user namespace:
        kubectl get pod <POD_NAME> -n <NAMESPACE> -o yaml > /tmp/pod-no-hostnetwork.yaml

        # Edit /tmp/pod-no-hostnetwork.yaml:
        # - Remove `hostNetwork: true` or change it to `hostNetwork: false`
        # - Remove fields not allowed on Pod create (status, metadata.resourceVersion, etc.)

        # Then delete and recreate:
        kubectl delete pod <POD_NAME> -n <NAMESPACE>
        kubectl apply -f /tmp/pod-no-hostnetwork.yaml

        # 4) Verification (any machine with kubectl access)
        kubectl get pods --all-namespaces -o jsonpath='{range .items[*]}{.metadata.namespace}{" "}{.metadata.name}{" hostNetwork="}{.spec.hostNetwork}{"\n"}{end}' \
          | grep "hostNetwork=true" || echo "No pods with hostNetwork=true found"
        ```
      </Accordion>

      <Accordion title="Automation">
        ```bash theme={null}
        #!/usr/bin/env bash
        #
        # Restrict hostNetwork usage with PodSecurityStandard policies.
        # - Labels all non-system namespaces with a high-privilege policy that disallows hostNetwork.
        # - Safe to re-run: all operations are idempotent.
        #
        # Requirements:
        #   - Run on any machine with kubectl access and cluster-admin privileges.
        #   - Kubernetes v1.25+ with Pod Security Admission enabled (standard for recent clusters).

        set -euo pipefail

        # ---------- Configuration ----------

        # Namespaces to IGNORE (typically system/control-plane)
        IGNORED_NAMESPACES=(
          kube-system
          kube-public
          kube-node-lease
          default    # remove this if you intentionally run user workloads in "default"
        )

        # Pod Security Admission labels that prohibit hostNetwork
        PSA_LEVEL="restricted"
        PSA_VERSION="latest"

        # ---------- Helper functions ----------

        ns_ignored() {
          local ns="$1"
          for ign in "${IGNORED_NAMESPACES[@]}"; do
            if [[ "$ns" == "$ign" ]]; then
              return 0
            fi
          done
          return 1
        }

        label_namespace_psa() {
          local ns="$1"

          echo "Ensuring Pod Security Admission labels on namespace: ${ns}"

          # Add or update labels; these commands are idempotent
          kubectl label namespace "${ns}" \
            "pod-security.kubernetes.io/enforce=${PSA_LEVEL}" \
            --overwrite >/dev/null

          kubectl label namespace "${ns}" \
            "pod-security.kubernetes.io/enforce-version=${PSA_VERSION}" \
            --overwrite >/dev/null

          kubectl label namespace "${ns}" \
            "pod-security.kubernetes.io/warn=${PSA_LEVEL}" \
            --overwrite >/dev/null

          kubectl label namespace "${ns}" \
            "pod-security.kubernetes.io/warn-version=${PSA_VERSION}" \
            --overwrite >/dev/null
        }

        # ---------- Main: apply policy ----------

        echo "Discovering namespaces..."
        ALL_NAMESPACES=$(kubectl get ns -o jsonpath='{range .items[*]}{.metadata.name}{"\n"}{end}')

        for ns in ${ALL_NAMESPACES}; do
          if ns_ignored "${ns}"; then
            echo "Skipping ignored namespace: ${ns}"
            continue
          fi
          label_namespace_psa "${ns}"
        done

        # ---------- Verification ----------

        echo
        echo "Verifying that no pods are running with spec.hostNetwork=true..."

        NON_COMPLIANT=false

        # Reuse the benchmark-style audit to list pods with hostNetwork=true
        kubectl get pods --all-namespaces -o custom-columns=POD_NAME:.metadata.name,POD_NAMESPACE:.metadata.namespace --no-headers | \
        while read -r pod_name pod_namespace; do
          pod_hostnetwork=$(kubectl get pod "${pod_name}" --namespace "${pod_namespace}" -o jsonpath='{.spec.hostNetwork}' 2>/dev/null || true)
          if [[ "${pod_hostnetwork}" == "true" ]]; then
            NON_COMPLIANT=true
            echo "NON-COMPLIANT: pod_name=${pod_name} pod_namespace=${pod_namespace} hostNetwork=true"
          fi
        done

        # Note: the subshell above cannot modify NON_COMPLIANT in the parent directly.
        # Run a second, direct check that is easy to parse for automation purposes.

        HOSTNETWORK_PODS=$(kubectl get pods --all-namespaces \
          -o jsonpath='{range .items[?(@.spec.hostNetwork==true)]}{.metadata.namespace}{" "}{.metadata.name}{"\n"}{end}')

        echo
        if [[ -z "${HOSTNETWORK_PODS}" ]]; then
          echo "Result: COMPLIANT - no pods currently have spec.hostNetwork=true."
        else
          echo "Result: NON-COMPLIANT - the following pods still have spec.hostNetwork=true:"
          echo "${HOSTNETWORK_PODS}"
          echo
          echo "Note: Pod Security Admission prevents NEW hostNetwork pods in labeled namespaces,"
          echo "but existing pods with hostNetwork=true must be manually reviewed/updated or deleted."
        fi
        ```
      </Accordion>
    </AccordionGroup>
  </Tab>
</Tabs>
