> ## 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 Admission Containers Wishing Host Network Namespace

### More Info:

Do not generally permit containers to be run with the hostNetwork flag set to true.

### 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 pods using hostNetwork (discovery)**\
           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. **Identify user workload namespaces that allow hostNetwork (review)**\
           Run on: any machine with kubectl access\
           Review which of the above pods are in user workload namespaces (exclude kube-system and other control-plane/system namespaces). For each user namespace you decide should *not* allow hostNetwork, proceed to the next step. For namespaces that legitimately need hostNetwork (e.g., CNI, ingress), document the exception instead of applying the restriction.

        3. **Create a baseline admission policy to deny hostNetwork (example Kyverno)**\
           Run on: any machine with kubectl access\
           If you use Kyverno, create a ClusterPolicy denying hostNetwork for pods in selected namespaces (replace `<NAMESPACE1>,<NAMESPACE2>` with a comma‑separated list of target namespaces):
           ```bash theme={null}
           cat << 'EOF' | kubectl apply -f -
           apiVersion: kyverno.io/v1
           kind: ClusterPolicy
           metadata:
             name: deny-hostnetwork
           spec:
             validationFailureAction: Enforce
             background: true
             rules:
               - name: deny-hostnetwork
                 match:
                   resources:
                     kinds:
                       - Pod
                     namespaces:
                       - NAMESPACE1
                       - NAMESPACE2
                 validate:
                   message: "Use of hostNetwork is not allowed in this namespace."
                   pattern:
                     spec:
                       hostNetwork: "false"
           EOF
           ```
           Adapt the tool and syntax to your existing admission controller (e.g., OPA Gatekeeper, ValidatingAdmissionPolicy) but keep the same intent: match Pods in selected namespaces and deny when `spec.hostNetwork == true`.

        4. **Handle existing hostNetwork pods in restricted namespaces (migration)**\
           Run on: any machine with kubectl access\
           For each affected namespace from step 2, list existing hostNetwork pods again and plan replacement without hostNetwork:
           ```bash theme={null}
           NAMESPACE=<TARGET_NAMESPACE>
           kubectl get pods -n "${NAMESPACE}" -o jsonpath='{range .items[?(@.spec.hostNetwork==true)]}{.metadata.name}{"\n"}{end}'
           ```
           For each listed workload (Deployment/DaemonSet/StatefulSet/Job, etc.), edit its manifest to remove or set `hostNetwork: false` under `spec.template.spec`, then apply:
           ```bash theme={null}
           # Example for a single deployment
           kubectl get deploy <DEPLOYMENT_NAME> -n "${NAMESPACE}" -o yaml > /tmp/deploy.yaml
           # Edit /tmp/deploy.yaml: delete or change 'hostNetwork: true' to 'hostNetwork: false'
           kubectl apply -f /tmp/deploy.yaml
           ```
           Replace pods created directly (not via controllers) by deleting and recreating them with hostNetwork disabled.

        5. **Optionally scope exceptions per-namespace (refine policy)**\
           Run on: any machine with kubectl access\
           For namespaces where specific workloads must use hostNetwork, narrow your policy instead of blanket denying the namespace. Example Kyverno rule that allows hostNetwork only for pods with a specific label:
           ```bash theme={null}
           cat << 'EOF' | kubectl apply -f -
           apiVersion: kyverno.io/v1
           kind: ClusterPolicy
           metadata:
             name: deny-hostnetwork-except-labeled
           spec:
             validationFailureAction: Enforce
             background: true
             rules:
               - name: deny-hostnetwork-except-labeled
                 match:
                   resources:
                     kinds:
                       - Pod
                     namespaces:
                       - NAMESPACE_REQUIRING_EXCEPTIONS
                 preconditions:
                   any:
                     - key: "{{ request.object.metadata.labels.hostnetwork-allowed || 'false' }}"
                       operator: Equals
                       value: "false"
                 validate:
                   message: "Use of hostNetwork is not allowed unless explicitly labeled."
                   pattern:
                     spec:
                       hostNetwork: "false"
           EOF
           ```
           Then explicitly label exception pods/workloads:
           ```bash theme={null}
           kubectl label deploy <DEPLOYMENT_NAME> -n NAMESPACE_REQUIRING_EXCEPTIONS hostnetwork-allowed=true
           ```

        6. **Verification (re-run the audit with expectation)**\
           Run on: any machine with kubectl access\
           Re-run the audit and confirm no pods with `spec.hostNetwork=true` exist in namespaces where you applied restrictions:
           ```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"
               echo "***pod_name: ${pod_name} pod_namespace: ${pod_namespace} is_pod_hostnetwork: ${pod_hostnetwork} is_compliant: true"
             else
               echo "***pod_name: ${pod_name} pod_namespace: ${pod_namespace} is_pod_hostnetwork: ${pod_hostnetwork} is_compliant: false"
             fi
           done
           ```
           For user namespaces meant to be restricted, ensure all lines show `is_pod_hostnetwork: false` and `is_compliant: true`; any remaining non-compliant pods should be investigated or migrated.
      </Accordion>

      <Accordion title="Using kubectl">
        ```bash theme={null}
        # 1) Create a baseline policy to DENY pods that use hostNetwork in a workload namespace
        # Run on: any machine with kubectl access

        # Example: apply to a single namespace (replace <NAMESPACE> with your workload namespace)
        cat << 'EOF' | kubectl apply -f -
        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:
                        - "<NAMESPACE>"
              validate:
                message: "Use of hostNetwork is not allowed in this namespace."
                pattern:
                  spec:
                    hostNetwork: "false"
        EOF
        ```

        ```bash theme={null}
        # 2) (Alternative) If you use Kubernetes-native ValidatingAdmissionPolicy (v1.30+),
        # first create the policy definition (cluster-wide), then a Binding for each namespace.

        # 2a) Create the ValidatingAdmissionPolicy (cluster-wide)
        cat << 'EOF' | kubectl apply -f -
        apiVersion: admissionregistration.k8s.io/v1
        kind: ValidatingAdmissionPolicy
        metadata:
          name: deny-hostnetwork
        spec:
          paramKind: {}
          matchConstraints:
            resourceRules:
              - apiGroups: [""]
                apiVersions: ["v1"]
                operations: ["CREATE", "UPDATE"]
                resources: ["pods"]
          validations:
            - expression: "!(has(object.spec.hostNetwork) && object.spec.hostNetwork == true)"
              message: "Use of hostNetwork is not allowed."
        EOF
        EOF

        # 2b) Bind the policy to a specific namespace (replace <NAMESPACE> with your workload namespace)
        cat << 'EOF' | kubectl apply -f -
        apiVersion: admissionregistration.k8s.io/v1
        kind: ValidatingAdmissionPolicyBinding
        metadata:
          name: deny-hostnetwork-<NAMESPACE>
        spec:
          policyName: deny-hostnetwork
          validationActions: ["Deny"]
          matchResources:
            namespaceSelector:
              matchLabels:
                kubernetes.io/metadata.name: "<NAMESPACE>"
        EOF
        ```

        ```bash theme={null}
        # 3) Label additional workload namespaces and re‑use the binding pattern as needed
        # Run for each workload namespace:
        kubectl label namespace PROD-NAMESPACE kubernetes.io/metadata.name=PROD-NAMESPACE --overwrite

        # Then apply a binding for that namespace (edit manifest above to use PROD-NAMESPACE)
        ```

        ```bash theme={null}
        # 4) Verification: list all pods that still have hostNetwork=true
        # Run on: any machine with kubectl access
        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
        ```
      </Accordion>

      <Accordion title="Automation">
        ```bash theme={null}
        #!/usr/bin/env bash
        #
        # Purpose:
        #   Minimize admission of Pods using hostNetwork by applying
        #   a default-deny hostNetwork Pod Security Admission label
        #   to all non-system namespaces that run user workloads.
        #
        #   This script is idempotent and safe to re-run.
        #
        # Run on:
        #   Any machine with kubectl access and current-context set
        #   to the target cluster, with cluster-admin privileges.
        #
        # Notes:
        #   - This uses Kubernetes built‑in Pod Security Admission (PSA)
        #     by labeling namespaces with:
        #       pod-security.kubernetes.io/enforce=restricted
        #       pod-security.kubernetes.io/enforce-version=latest
        #   - PSA "restricted" level forbids hostNetwork, hostPID, hostIPC, etc.
        #   - System / control-plane namespaces are excluded.

        set -euo pipefail

        # Fail early if kubectl is not available
        if ! command -v kubectl >/dev/null 2>&1; then
          echo "kubectl not found in PATH. Install kubectl and ensure it can access the cluster."
          exit 1
        fi

        # Ensure we can talk to the cluster
        if ! kubectl version --short >/dev/null 2>&1; then
          echo "kubectl cannot connect to the cluster using the current context."
          exit 1
        fi

        echo "Discovering namespaces..."

        # Define a list of namespaces to exclude (system / infrastructure)
        EXCLUDE_NAMESPACES=(
          kube-system
          kube-public
          kube-node-lease
          default        # adjust if 'default' is used for user workloads
          kube-monitoring
          istio-system
          metallb-system
          cert-manager
          local-path-storage
        )

        # Build a regex for exclusion
        EXCLUDE_REGEX="$(IFS='|'; echo "${EXCLUDE_NAMESPACES[*]}")"

        # Get target namespaces: all except excluded ones
        TARGET_NAMESPACES=$(kubectl get ns -o jsonpath='{range .items[*]}{.metadata.name}{"\n"}{end}' \
          | grep -Ev "^(${EXCLUDE_REGEX})$" || true)

        if [ -z "${TARGET_NAMESPACES}" ]; then
          echo "No target namespaces found (non-system namespaces). Nothing to do."
        else
          echo "Target namespaces (will enforce PSA 'restricted'):"
          echo "${TARGET_NAMESPACES}"
        fi

        # Apply Pod Security Admission labels to each target namespace
        for ns in ${TARGET_NAMESPACES}; do
          echo "Configuring Pod Security Admission labels on namespace: ${ns}"

          # Apply "restricted" enforce level; keep "latest" version for future-proofing
          kubectl label namespace "${ns}" \
            pod-security.kubernetes.io/enforce=restricted \
            pod-security.kubernetes.io/enforce-version=latest \
            --overwrite
        done

        echo "Namespace labeling completed."

        ###############################################################################
        # VERIFICATION
        ###############################################################################
        echo
        echo "Verifying that hostNetwork Pods are disallowed in target namespaces..."

        VERIFY_TMP_DIR=$(mktemp -d)
        trap 'rm -rf "${VERIFY_TMP_DIR}"' EXIT

        for ns in ${TARGET_NAMESPACES}; do
          echo
          echo "Testing namespace: ${ns}"

          # Create a simple Pod manifest that requests hostNetwork
          cat > "${VERIFY_TMP_DIR}/test-hostnetwork-pod.yaml" <<'EOF'
        apiVersion: v1
        kind: Pod
        metadata:
          name: psa-hostnetwork-test
        spec:
          hostNetwork: true
          containers:
          - name: pause
            image: registry.k8s.io/pause:3.9
        EOF

          # Try to create the Pod; it SHOULD FAIL if enforcement is working
          set +e
          CREATE_OUTPUT=$(kubectl apply -n "${ns}" -f "${VERIFY_TMP_DIR}/test-hostnetwork-pod.yaml" 2>&1)
          CREATE_RC=$?
          set -e

          if [ ${CREATE_RC} -eq 0 ]; then
            echo "WARNING: hostNetwork Pod was ADMITTED in namespace '${ns}'."
            echo "  This indicates Pod Security Admission is not enforcing 'restricted' as expected."
            echo "  Output:"
            echo "  ${CREATE_OUTPUT}"
            # Clean up the test pod if it was created
            kubectl delete pod psa-hostnetwork-test -n "${ns}" --ignore-not-found >/dev/null 2>&1 || true
          else
            echo "OK: hostNetwork Pod was REJECTED in namespace '${ns}' as desired."
            echo "  Admission error:"
            echo "  ${CREATE_OUTPUT}" | sed 's/^/  /'
          fi
        done

        echo
        echo "Verification complete."
        echo "Note: Existing running Pods with hostNetwork=true are not automatically evicted."
        echo "      They must be reviewed and replaced/removed manually if inappropriate."
        ```
      </Accordion>
    </AccordionGroup>
  </Tab>
</Tabs>

### Additional Reading:

* [https://kubernetes.io/docs/concepts/security/pod-security-standards/](https://kubernetes.io/docs/concepts/security/pod-security-standards/)
