Skip to main content

OCI OKE Should Minimize Admission of Privileged Containers

More Info:

Privileged containers run with all Linux capabilities and bypass most container isolation. They must be denied at admission time and only allowed via narrow exceptions tied to specific signed workloads.

Risk Level

Critical

Address

Compliance, Security

Compliance Standards

  • CIS OKE

Triage and Remediation

Remediation

Using Console

To minimize admission of privileged containers in an OCI OKE cluster using the OCI Console, you do this by enabling and configuring the OPA Gatekeeper add‑on with restrictive policies.

1. Open your OKE cluster in the OCI Console

  1. Sign in to the OCI Console.
  2. From the left menu: Developer ServicesKubernetes Clusters (OKE).
  3. Select the Compartment that contains your cluster.
  4. Click the name of the cluster you want to secure.

2. Enable / configure the Gatekeeper add‑on

  1. In the cluster details page, go to the Add‑ons (or Add‑ons & Security) tab.

  2. Look for Gatekeeper or Policy / Security related add‑on:

    • If Gatekeeper is not enabled:
      • Click Enable / Install Add‑on.
      • Choose Gatekeeper.
    • If Gatekeeper is already enabled:
      • Click Edit configuration or the equivalent action for that add‑on.
  3. In the Gatekeeper configuration:

    • Choose the policy profile that blocks privileged containers. Depending on the UI version, this is typically:
      • Restricted (or similar) Pod Security profile, or
      • A checkbox / toggle like Disallow privileged containers, Block privileged containers, or Disallow privilege escalation.
    • Make sure the setting that forbids securityContext.privileged: true (and usually allowPrivilegeEscalation: true) is enabled/enforced.
  4. Click Save, Update, or Apply to reconfigure the cluster.

    • The cluster control plane will roll out the updated admission policy.

3. Confirm enforcement

  1. After the add‑on update completes, try to deploy (or redeploy) a pod that uses:
    securityContext:
    privileged: true
  2. The deployment should now be rejected by admission control with an error from Gatekeeper / policy enforcement.

4. Clean up existing workloads (if any)

Admission control only blocks new or updated workloads:

  1. In the console, under the cluster, go to Workloads or Deployments.
  2. Identify any pods/deployments/DaemonSets that:
    • Use HostPath volumes with root access and
    • Have Privileged containers (visible in the workload details).
  3. Edit or redeploy those workloads (via your normal CI/CD or kubectl) to remove:
    securityContext:
    privileged: true
    allowPrivilegeEscalation: true

If you can share what you see under Add‑ons or Security for the cluster in the console (names of toggles / profiles), I can map it to the exact click-path and profile name for your tenancy’s OKE version.

Using CLI

To minimize admission of privileged containers on OCI OKE, you use the OPA Gatekeeper admission controller and define a policy that denies pods with securityContext.privileged: true.

Below are the steps, with OCI CLI where applicable.


1. Prerequisites

  • OCI CLI installed and configured (oci setup config)
  • You have permissions to update the OKE cluster
  • kubectl configured for the cluster (oci ce cluster create-kubeconfig)

2. Enable the Admission Controller (OPA Gatekeeper) via OCI CLI

  1. Get the OKE cluster OCID (if you don’t already have it):
oci ce cluster list --compartment-id <compartment_ocid> \
--query 'data[].{"name":name,"ocid":id}' --output table
  1. Enable the admission controller:
oci ce cluster update \
--cluster-id <cluster_ocid> \
--cluster-options '{
"admissionControllerOptions": {
"isAdmissionControllerEnabled": true
}
}' \
--force --wait-for-state ACTIVE

Verify it’s enabled:

oci ce cluster get --cluster-id <cluster_ocid> \
--query 'data.options.admissionControllerOptions'

3. Configure kubectl Access (once per admin machine)

oci ce cluster create-kubeconfig \
--cluster-id <cluster_ocid> \
--file $HOME/.kube/config-oke \
--region <region> \
--token-version 2
export KUBECONFIG=$HOME/.kube/config-oke

4. Create a Gatekeeper ConstraintTemplate to Deny Privileged Containers

Save as ct-deny-privileged-containers.yaml:

apiVersion: templates.gatekeeper.sh/v1beta1
kind: ConstraintTemplate
metadata:
name: k8sprivilegedcontainer
spec:
crd:
spec:
names:
kind: K8sPrivilegedContainer
targets:
- target: admission.k8s.gatekeeper.sh
rego: |
package k8sprivilegedcontainer

violation[{"msg": msg}] {
container := input.review.object.spec.containers[_]
container.securityContext.privileged == true
msg := sprintf("Privileged containers are not allowed: %v", [container.name])
}

violation[{"msg": msg}] {
container := input.review.object.spec.initContainers[_]
container.securityContext.privileged == true
msg := sprintf("Privileged initContainers are not allowed: %v", [container.name])
}

Apply:

kubectl apply -f ct-deny-privileged-containers.yaml

5. Create a Constraint to Enforce the Template Cluster-wide

Save as c-deny-privileged-containers.yaml:

apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sPrivilegedContainer
metadata:
name: deny-privileged-containers
spec:
match:
kinds:
- apiGroups: [""]
kinds: ["Pod"]
# Optionally restrict to certain namespaces:
# namespaces: ["prod", "staging"]

Apply:

kubectl apply -f c-deny-privileged-containers.yaml

6. Test the Policy

Try to create a privileged pod:

# test-privileged-pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: privileged-test
spec:
containers:
- name: busybox
image: busybox
command: ["sleep", "3600"]
securityContext:
privileged: true
kubectl apply -f test-privileged-pod.yaml

You should see an admission error from Gatekeeper denying the pod.


7. (Optional) Scope / Soften the Policy

  • To allow specific namespaces, add them under spec.match.namespaces.
  • To exclude system namespaces:
spec:
match:
kinds:
- apiGroups: [""]
kinds: ["Pod"]
excludedNamespaces:
- kube-system
- gatekeeper-system

Re-apply the constraint if you modify it:

kubectl apply -f c-deny-privileged-containers.yaml

That configuration (enabled via OCI CLI and enforced via OPA Gatekeeper) ensures OKE minimizes and typically blocks admission of privileged containers.

Using Python

Below is a practical way to remediate “privileged containers” in OCI OKE using Python, by:

  1. Auditing for privileged containers.
  2. Patching workloads to remove privileged: true.
  3. Optionally enforcing Kubernetes Pod Security “restricted” mode at namespace level.

This uses the official Kubernetes Python client against your OKE cluster.


1. Prerequisites

  1. Ensure you can run kubectl against your OKE cluster:
    kubectl get nodes
  2. Install Kubernetes Python client:
    pip install kubernetes
  3. Make sure your kubeconfig is available (typically ~/.kube/config) and points to the OKE cluster.

2. Python: Find All Privileged Containers

This script inspects Pods, Deployments, StatefulSets, DaemonSets, and Jobs for securityContext.privileged: true at:

  • container level
  • pod-level securityContext (for whole pod)
from kubernetes import client, config

def is_privileged_container(container):
sc = getattr(container, "security_context", None)
return bool(sc and getattr(sc, "privileged", False))

def is_privileged_pod_spec(pod_spec):
# pod-level securityContext (if ever used for privileged escalation)
psc = getattr(pod_spec, "security_context", None)
if psc and getattr(psc, "privileged", None):
return True
# containers
for c in getattr(pod_spec, "containers", []):
if is_privileged_container(c):
return True
# initContainers
for c in getattr(pod_spec, "init_containers", []):
if is_privileged_container(c):
return True
return False

def main():
config.load_kube_config() # or config.load_incluster_config()

core = client.CoreV1Api()
apps = client.AppsV1Api()
batch = client.BatchV1Api()

print("Checking Pods...")
for ns in [n.metadata.name for n in core.list_namespace().items]:
pods = core.list_namespaced_pod(ns)
for p in pods.items:
if is_privileged_pod_spec(p.spec):
print(f"[POD] {ns}/{p.metadata.name} has privileged containers")

print("Checking Deployments...")
for ns in [n.metadata.name for n in core.list_namespace().items]:
deps = apps.list_namespaced_deployment(ns)
for d in deps.items:
if is_privileged_pod_spec(d.spec.template.spec):
print(f"[DEPLOYMENT] {ns}/{d.metadata.name} has privileged containers")

print("Checking StatefulSets...")
for ns in [n.metadata.name for n in core.list_namespace().items]:
ssets = apps.list_namespaced_stateful_set(ns)
for s in ssets.items:
if is_privileged_pod_spec(s.spec.template.spec):
print(f"[STATEFULSET] {ns}/{s.metadata.name} has privileged containers")

print("Checking DaemonSets...")
for ns in [n.metadata.name for n in core.list_namespace().items]:
dsets = apps.list_namespaced_daemon_set(ns)
for d in dsets.items:
if is_privileged_pod_spec(d.spec.template.spec):
print(f"[DAEMONSET] {ns}/{d.metadata.name} has privileged containers")

print("Checking Jobs...")
for ns in [n.metadata.name for n in core.list_namespace().items]:
jobs = batch.list_namespaced_job(ns)
for j in jobs.items:
if is_privileged_pod_spec(j.spec.template.spec):
print(f"[JOB] {ns}/{j.metadata.name} has privileged containers")

if __name__ == "__main__":
main()

Run it and review output. Confirm which workloads truly need privilege (ideally none).


3. Python: Patch Workloads to Remove privileged: true

Below is a targeted patch for Deployments; you can adapt the same logic for StatefulSets, DaemonSets, and Jobs.

This:

  • Loads the Deployment.
  • Iterates containers and initContainers.
  • Deletes or sets securityContext.privileged to false.
  • Patches the Deployment.
from kubernetes import client, config
from copy import deepcopy

def remove_privileged_from_container_dict(c_dict):
sc = c_dict.get("securityContext")
if sc is None:
return
# Remove only the privileged flag
sc.pop("privileged", None)
# Clean empty securityContext
if not sc:
c_dict.pop("securityContext", None)

def patch_deployment_remove_privileged(namespace, name):
config.load_kube_config()
apps = client.AppsV1Api()

dep = apps.read_namespaced_deployment(name=name, namespace=namespace)
tmpl_spec = dep.spec.template.spec

# Build patch by converting to dict and editing
dep_dict = dep.to_dict()
tmpl = dep_dict["spec"]["template"]["spec"]

changed = False

for c in tmpl.get("containers", []):
before = deepcopy(c)
remove_privileged_from_container_dict(c)
if before != c:
changed = True

for c in tmpl.get("init_containers", []) or []:
before = deepcopy(c)
remove_privileged_from_container_dict(c)
if before != c:
changed = True

# If pod-level securityContext has "privileged", remove it
psc = tmpl.get("security_context")
if psc and "privileged" in psc:
psc.pop("privileged", None)
if not psc:
tmpl.pop("security_context", None)
changed = True

if not changed:
print(f"No privileged containers found in deployment {namespace}/{name}")
return

patch_body = {
"spec": {
"template": {
"spec": tmpl
}
}
}

resp = apps.patch_namespaced_deployment(
name=name,
namespace=namespace,
body=patch_body,
)
print(f"Patched deployment {namespace}/{name}, new generation: {resp.metadata.generation}")

if __name__ == "__main__":
# Example usage
patch_deployment_remove_privileged("default", "my-deployment")

Extend this pattern for other controller types by using:

  • apps.read_namespaced_stateful_set / patch_namespaced_stateful_set
  • apps.read_namespaced_daemon_set / patch_namespaced_daemon_set
  • batch.read_namespaced_job / patch_namespaced_job

For Kubernetes 1.25+ (where PodSecurityPolicy is removed), use Pod Security Admission labels.

At the namespace level, you can enforce the restricted profile (which denies privileged containers) using Python:

from kubernetes import client, config

def label_namespace_restricted(namespace):
config.load_kube_config()
core = client.CoreV1Api()

body = {
"metadata": {
"labels": {
"pod-security.kubernetes.io/enforce": "restricted",
"pod-security.kubernetes.io/enforce-version": "latest"
}
}
}

resp = core.patch_namespace(name=namespace, body=body)
print(f"Namespace {namespace} labeled for restricted Pod Security; resourceVersion={resp.metadata.resource_version}")

if __name__ == "__main__":
# Example: apply to non-system namespaces
config.load_kube_config()
core = client.CoreV1Api()
for ns in core.list_namespace().items:
name = ns.metadata.name
if name in ("kube-system", "kube-public", "oci-system", "oracle-system"):
continue
label_namespace_restricted(name)

After applying:

  • Any new Pod/Deployment/Job with securityContext.privileged: true will be rejected by the API server.

5. Operational Flow

  1. Audit: Run the audit script to identify all privileged containers.
  2. Discuss/validate: Confirm with app owners which workloads (if any) truly need elevated privileges.
  3. Patch: Use the patch script to remove privileged: true from those that don’t need it.
  4. Enforce: Label namespaces with Pod Security restricted using the last script so future privileged pods are blocked in OKE.
  5. CI/CD integration (optional): Run the audit-or-fail script in your pipeline to prevent regressions.

If you share your Kubernetes version and whether you’re already using Gatekeeper/OPA on OKE, I can tailor this to that setup as well.

Using Terraform
# There is currently no argument on `oci_containerengine_cluster` (the
# Terraform resource behind the "oci-containers-oke-cluster" surface)
# that can deny privileged containers at admission time.
#
# OKE enforces this via Kubernetes-level admission controls (e.g. Pod
# Security Admission labels, Gatekeeper/OPA policies, or equivalent),
# which must be configured inside the cluster, not on the cluster
# resource itself.

# Example: create the OKE cluster (no field here can block privileged pods)
resource "oci_containerengine_cluster" "oke" {
name = "MY_OKE_CLUSTER_NAME" # substitute your cluster name
compartment_id = "OCID_OF_COMPARTMENT" # substitute your compartment OCID
vcn_id = "OCID_OF_VCN" # substitute your VCN OCID

kubernetes_version = "v1.30.1" # example version

options {
service_lb_subnet_ids = [
"OCID_OF_SUBNET_1",
"OCID_OF_SUBNET_2",
]
}
}

# To actually minimize admission of privileged containers you must:
# - Use a Kubernetes provider/Helm in Terraform to install and configure:
# - Pod Security Admission (PSA) labels on namespaces, and/or
# - Gatekeeper/OPA or another admission controller with policies that
# `deny` pods setting `securityContext.privileged: true`, except for
# narrowly-scoped, signed workloads.
#
# Those controls are expressed as Kubernetes manifests, not as fields on
# `oci_containerengine_cluster`, so they cannot be implemented on that
# exact resource type.

# Verification:
# - `terraform plan` against the `oci_containerengine_cluster` resource
# will show no changes related to privileged-container admission,
# because the provider does not expose such a setting on this resource.