Skip to main content

OCI OKE Should Minimize Containers Sharing the Host PID

More Info:

hostPID=true allows a container to view and signal every process on the node, providing trivial paths to escape isolation. Reject pods with hostPID by default in admission policy.

Risk Level

High

Address

Compliance, Security

Compliance Standards

  • CIS OKE

Triage and Remediation

Remediation

Using Console

In OKE this setting comes from the Kubernetes pod spec (hostPID: true). There is no single “toggle” in the OCI Console; you remediate by (1) finding the offending workloads and (2) redeploying them without hostPID, and optionally (3) enforcing a policy so it can’t be re‑introduced.

Below are the steps, keeping everything driven from the OCI Console as much as possible.


1. Identify pods using the host PID namespace

  1. Sign in to the OCI Console.
  2. Go to Developer Services → Kubernetes Clusters (OKE).
  3. Select the Compartment, then click your Cluster.
  4. In the cluster details page, in the left menu, choose Workloads (if available in your console region/version):
    • Look at the Pod YAML (or the parent Deployment/DaemonSet/StatefulSet YAML) for suspicious workloads.
    • Check each pod’s spec for:
      hostPID: true
  5. If you don’t see it clearly in the GUI, use Cloud Shell from the console:
    • Click the Cloud Shell icon (top‑right).
    • Configure kubectl for your cluster by clicking Access Cluster in the cluster details page and following the on‑screen instructions to download and use the kubeconfig in Cloud Shell.
    • Then in Cloud Shell run:
      kubectl get pods -A -o=jsonpath='{range .items[?(@.spec.hostPID==true)]}{.metadata.namespace}{"\t"}{.metadata.name}{"\n"}{end}'
    • This lists all pods with hostPID: true.

Note down which namespaces and controller types (Deployment, DaemonSet, Job, etc.) are responsible for those pods.


2. Remove hostPID: true and redeploy

For each offending controller (Deployment/DaemonSet/Job/etc.):

  1. In the OCI Console → OKE → your cluster → Workloads:

    • Locate the workload (Deployment/DaemonSet/Job) generating the pod.
    • Use View YAML to see its manifest.
  2. Open Cloud Shell again (from the OCI Console) and edit the manifest via kubectl:

    • Export the existing manifest:
      kubectl -n <namespace> get deployment <name> -o yaml > deployment.yaml
      # or: daemonset/statefulset/job as appropriate
    • Edit the file in Cloud Shell (e.g., using vi):
      • Find any line:
        hostPID: true
        and either remove it (default is false) or explicitly set:
        hostPID: false
    • Apply the updated manifest:
      kubectl apply -f deployment.yaml
  3. For controllers you created via Helm or another CI/CD pipeline, update the source (Helm chart values or Git repo) to:

    • Remove/disable hostPID: true in their templates or values.
    • Redeploy from that system to avoid it being re‑introduced.
  4. Verify that no pods in the cluster now use the host PID namespace:

    kubectl get pods -A -o=jsonpath='{range .items[?(@.spec.hostPID==true)]}{.metadata.namespace}{"\t"}{.metadata.name}{"\n"}{end}'

    If this returns nothing, the configuration issue is remediated.


OKE doesn’t offer a direct “disallow hostPID” switch in the console, but you can enforce it using Kubernetes’ built‑in Pod Security Admission (for clusters on recent Kubernetes versions):

  1. In Cloud Shell, label namespaces with a strict Pod Security level that disallows host namespaces (e.g., restricted):

    kubectl label namespace <namespace> pod-security.kubernetes.io/enforce=restricted --overwrite

    The restricted profile prohibits host namespace sharing (including hostPID).

  2. For system namespaces (like kube-system) you may need less strict policies; focus on your application namespaces.

  3. Test by trying to deploy a pod with hostPID: true in that namespace—it should now be rejected by the API server.


Summary of what you must do in OCI Console–driven flow

  • Use OKE cluster page + Cloud Shell to:
    • Discover pods with hostPID: true.
    • Edit and re‑apply their controller manifests to remove hostPID.
    • Optionally label namespaces with pod-security.kubernetes.io/enforce=restricted so future hostPID usage is blocked.

If you share your OKE/Kubernetes version, I can give the exact kubectl commands and sample manifests aligned to that version.

Using CLI

To remediate “Containers sharing the host PID namespace” in OCI OKE, you need to ensure hostPID: false (or absent) in all Pod specs. Using OCI CLI, the flow is:


1. Configure kubectl access via OCI CLI

If you don’t already have kubeconfig for the cluster:

# Variables
REGION="<your-region>" # e.g. us-ashburn-1
CLUSTER_OCID="<your-oke-cluster-ocid>"
KUBECONFIG_PATH="$HOME/.kube/oke-config"

# Generate kubeconfig via OCI CLI
oci ce cluster create-kubeconfig \
--cluster-id "$CLUSTER_OCID" \
--file "$KUBECONFIG_PATH" \
--region "$REGION" \
--token-version 2.0.0 \
--kube-endpoint PUBLIC_ENDPOINT

export KUBECONFIG="$KUBECONFIG_PATH"

2. Find Pods/Workloads using hostPID: true

Check current Pods:

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

Check higher‑level objects (Deployments, DaemonSets, StatefulSets, etc.) that might be creating such Pods:

for kind in deployment daemonset statefulset job cronjob; do
echo "Checking $kind..."
kubectl get $kind --all-namespaces -o yaml | \
yq '.items[] | select(.spec.template.spec.hostPID == true) | .metadata.namespace + " " + .metadata.name'
done

(Assumes yq is installed; if not, you can inspect YAML manually.)


3. Remove / disable hostPID in the workload specs

For each workload identified:

Option A: Patch with kubectl (fastest)

Set hostPID: false on the Pod template:

# Example for a Deployment
NAMESPACE="<namespace>"
DEPLOYMENT_NAME="<deployment-name>"

kubectl patch deployment "$DEPLOYMENT_NAME" -n "$NAMESPACE" \
--type='merge' \
-p '{"spec":{"template":{"spec":{"hostPID":false}}}}'

Similar for other kinds:

# DaemonSet
kubectl patch daemonset "<ds-name>" -n "<namespace>" \
--type='merge' \
-p '{"spec":{"template":{"spec":{"hostPID":false}}}}'

# StatefulSet
kubectl patch statefulset "<sts-name>" -n "<namespace>" \
--type='merge' \
-p '{"spec":{"template":{"spec":{"hostPID":false}}}}'

# Job
kubectl patch job "<job-name>" -n "<namespace>" \
--type='merge' \
-p '{"spec":{"template":{"spec":{"hostPID":false}}}}'

# CronJob (batch/v1)
kubectl patch cronjob "<cronjob-name>" -n "<namespace>" \
--type='merge' \
-p '{"spec":{"jobTemplate":{"spec":{"template":{"spec":{"hostPID":false}}}}}}'

You can drive this fully from OCI CLI by first generating kubeconfig (step 1) and then running these kubectl commands in the same shell.

Option B: Edit manifests and re‑apply

If you manage manifests/Helm charts in Git:

  1. In each Pod template, ensure:

    spec:
    hostPID: false # or simply remove hostPID entirely (default is false)
  2. Re‑deploy:

    kubectl apply -f <your-manifest>.yaml

4. Optionally enforce at policy level (prevent future drift)

OKE uses upstream Kubernetes; you can use Pod Security Admission (recommended) or Gatekeeper/OPA. Example (Kubernetes v1.25+ with Pod Security Admission):

Create a namespace label to enforce restricted (which disallows hostPID):

kubectl label namespace <ns> \
pod-security.kubernetes.io/enforce=restricted \
pod-security.kubernetes.io/audit=restricted \
pod-security.kubernetes.io/warn=restricted

This can also be done after kubeconfig creation from OCI CLI.


5. Verify remediation

Re‑run the check:

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

No output means no Pods are using hostPID: true.

Using Python

In OKE this risk comes from pods that set hostPID: true in the pod spec. You remediate by finding all such workloads and patching them to hostPID: false (or removing the field), then enforcing a policy to prevent new ones.

Below are step‑by‑step instructions and Python examples using the Kubernetes Python client against your OKE cluster.


1. Prereqs

  1. Install tools:

    pip install kubernetes
  2. Make sure your kubectl is already configured for the OKE cluster (e.g. via OCI Console “Access Cluster” instructions).
    The Python client will reuse that kubeconfig.

  3. Verify:

    kubectl get nodes

2. Python: Identify all resources using hostPID: true

This script scans common workload types (Pods, Deployments, StatefulSets, DaemonSets, ReplicaSets, Jobs, CronJobs) in all namespaces and prints where hostPID is enabled.

from kubernetes import client, config
from kubernetes.client import ApiException

def has_host_pid(pod_spec):
# pod_spec is a V1PodSpec or None
return bool(pod_spec and getattr(pod_spec, "host_pid", False))

def main():
# Load kubeconfig from ~/.kube/config (default)
config.load_kube_config()

core_v1 = client.CoreV1Api()
apps_v1 = client.AppsV1Api()
batch_v1 = client.BatchV1Api()
batch_v1beta1 = client.BatchV1Api() # for CronJobs in newer clusters

print("=== Scanning Pods ===")
pods = core_v1.list_pod_for_all_namespaces().items
for p in pods:
if has_host_pid(p.spec):
print(f"Pod {p.metadata.namespace}/{p.metadata.name} has hostPID: true")

print("=== Scanning Deployments ===")
deps = apps_v1.list_deployment_for_all_namespaces().items
for d in deps:
if has_host_pid(d.spec.template.spec):
print(f"Deployment {d.metadata.namespace}/{d.metadata.name} has hostPID: true")

print("=== Scanning StatefulSets ===")
ssets = apps_v1.list_stateful_set_for_all_namespaces().items
for s in ssets:
if has_host_pid(s.spec.template.spec):
print(f"StatefulSet {s.metadata.namespace}/{s.metadata.name} has hostPID: true")

print("=== Scanning DaemonSets ===")
dsets = apps_v1.list_daemon_set_for_all_namespaces().items
for ds in dsets:
if has_host_pid(ds.spec.template.spec):
print(f"DaemonSet {ds.metadata.namespace}/{ds.metadata.name} has hostPID: true")

print("=== Scanning ReplicaSets ===")
rsets = apps_v1.list_replica_set_for_all_namespaces().items
for rs in rsets:
if has_host_pid(rs.spec.template.spec):
print(f"ReplicaSet {rs.metadata.namespace}/{rs.metadata.name} has hostPID: true")

print("=== Scanning Jobs ===")
jobs = batch_v1.list_job_for_all_namespaces().items
for j in jobs:
if has_host_pid(j.spec.template.spec):
print(f"Job {j.metadata.namespace}/{j.metadata.name} has hostPID: true")

# CronJobs in newer K8s are batch/v1 CronJob
try:
print("=== Scanning CronJobs ===")
cronjobs = batch_v1.list_cron_job_for_all_namespaces().items
for cj in cronjobs:
if has_host_pid(cj.spec.job_template.spec.template.spec):
print(f"CronJob {cj.metadata.namespace}/{cj.metadata.name} has hostPID: true")
except ApiException as e:
if e.status != 404:
raise

if __name__ == "__main__":
main()

Run this to see all offenders.


3. Python: Remediate by patching hostPID to false

You should ideally fix the original manifests in Git/Helm first. But if you need to remediate live workloads via script, you can patch them like this.

Below is an example for Deployments and StatefulSets (you can extend to other controllers similarly):

from kubernetes import client, config

def main():
config.load_kube_config()
apps_v1 = client.AppsV1Api()

# ---- Patch Deployments ----
deployments = apps_v1.list_deployment_for_all_namespaces().items
for d in deployments:
ns = d.metadata.namespace
name = d.metadata.name
spec = d.spec.template.spec

if spec and getattr(spec, "host_pid", False):
print(f"Patching Deployment {ns}/{name} to hostPID: false")
patch_body = {
"spec": {
"template": {
"spec": {
"hostPID": False
}
}
}
}
apps_v1.patch_namespaced_deployment(name=name, namespace=ns, body=patch_body)

# ---- Patch StatefulSets ----
ssets = apps_v1.list_stateful_set_for_all_namespaces().items
for s in ssets:
ns = s.metadata.namespace
name = s.metadata.name
spec = s.spec.template.spec

if spec and getattr(spec, "host_pid", False):
print(f"Patching StatefulSet {ns}/{name} to hostPID: false")
patch_body = {
"spec": {
"template": {
"spec": {
"hostPID": False
}
}
}
}
apps_v1.patch_namespaced_stateful_set(name=name, namespace=ns, body=patch_body)

if __name__ == "__main__":
main()

You can add similar blocks for:

  • apps_v1.patch_namespaced_daemon_set
  • apps_v1.patch_namespaced_replica_set
  • batch_v1.patch_namespaced_job
  • batch_v1.patch_namespaced_cron_job
  • Or patch individual Pods (not usually needed if controlled by a higher-level resource).

4. Prevent new hostPID usage (policy)

For long‑term remediation, you should block hostPID: true at admission time:

  1. If using Gatekeeper / OPA (or Kyverno), add a policy that denies any pod with spec.hostPID: true.
  2. Or use Kubernetes Pod Security Admission (PSA) with at least baseline / restricted profiles (which disallow host namespaces).

In OKE, you’d typically:

  • Enable Pod Security Admission in the cluster (if supported by your OKE/K8s version).

  • Set the namespace label, e.g.:

    kubectl label namespace <ns> pod-security.kubernetes.io/enforce=restricted

This will prevent future pods from using hostPID.


5. Validate

After the script and/or policy:

  1. Re-run the scanning script — it should find no hostPID: true.
  2. Try to deploy a test pod with hostPID: true; it should be rejected by policy (if configured).

If you share which controllers/resources you’re using (Helm, raw YAML, Operators), I can tailor a minimal Python script that only targets those.

Using Terraform

This setting cannot be configured on the oci_containerengine_cluster (OKE cluster) resource in Terraform; OKE does not expose admission policy / hostPID controls at the cluster resource level.

Rejecting pods with hostPID: true must be done via Kubernetes admission control objects inside the cluster (for example, Pod Security Admission, ValidatingAdmissionPolicy, or a validating webhook such as Gatekeeper/Kyverno), created with kubectl or via a Kubernetes Terraform provider. In the OCI Console you would:

  1. Get credentials for the OKE cluster and configure kubectl.
  2. Apply an admission policy (e.g., a ValidatingAdmissionPolicy or webhook) that denies any pod where spec.hostPID == true.