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
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
- Sign in to the OCI Console.
- From the left menu: Developer Services → Kubernetes Clusters (OKE).
- Select the Compartment that contains your cluster.
- Click the name of the cluster you want to secure.
2. Enable / configure the Gatekeeper add‑on
-
In the cluster details page, go to the Add‑ons (or Add‑ons & Security) tab.
-
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.
- If Gatekeeper is not enabled:
-
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 usuallyallowPrivilegeEscalation: true) is enabled/enforced.
- Choose the policy profile that blocks privileged containers. Depending on the UI version, this is typically:
-
Click Save, Update, or Apply to reconfigure the cluster.
- The cluster control plane will roll out the updated admission policy.
3. Confirm enforcement
- After the add‑on update completes, try to deploy (or redeploy) a pod that uses:
securityContext:privileged: true
- 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:
- In the console, under the cluster, go to Workloads or Deployments.
- Identify any pods/deployments/DaemonSets that:
- Use HostPath volumes with root access and
- Have Privileged containers (visible in the workload details).
- Edit or redeploy those workloads (via your normal CI/CD or
kubectl) to remove:securityContext:privileged: trueallowPrivilegeEscalation: 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
kubectlconfigured for the cluster (oci ce cluster create-kubeconfig)
2. Enable the Admission Controller (OPA Gatekeeper) via OCI CLI
- 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
- 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:
- Auditing for privileged containers.
- Patching workloads to remove
privileged: true. - Optionally enforcing Kubernetes Pod Security “restricted” mode at namespace level.
This uses the official Kubernetes Python client against your OKE cluster.
1. Prerequisites
- Ensure you can run
kubectlagainst your OKE cluster:kubectl get nodes - Install Kubernetes Python client:
pip install kubernetes
- 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.privilegedtofalse. - 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_setapps.read_namespaced_daemon_set/patch_namespaced_daemon_setbatch.read_namespaced_job/patch_namespaced_job
4. Enforce “No Privileged” Using Pod Security Admission (Recommended)
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: truewill be rejected by the API server.
5. Operational Flow
- Audit: Run the audit script to identify all privileged containers.
- Discuss/validate: Confirm with app owners which workloads (if any) truly need elevated privileges.
- Patch: Use the patch script to remove
privileged: truefrom those that don’t need it. - Enforce: Label namespaces with Pod Security restricted using the last script so future privileged pods are blocked in OKE.
- 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.