Skip to main content

More Info:

Public Kubernetes API endpoints are continuously scanned and brute forced. Restrict the API server to private endpoints reachable only via VCN, bastions or Service Gateway to dramatically reduce attack surface.

Risk Level

Critical

Address

Compliance, Security

Compliance Standards

  • CIS OKE

Triage and Remediation

Remediation

Using Console

Below are the steps to disable the public Kubernetes API endpoint for an OCI OKE cluster using the OCI Console, and move it to a private endpoint only.
Note: Some older / “Basic” clusters or early-generation clusters may not support changing endpoint type in-place. In that case, you must recreate the cluster with a private-only endpoint. I’ll include both paths.

1. Prerequisites

Before disabling the public endpoint, make sure:
  1. You have VCN connectivity from your admin environment (bastion host / VPN / FastConnect / OCI Cloud Shell) to the private subnet where the API will reside.
  2. You have or will create a private subnet in your VCN for the Kubernetes API endpoint.
  3. You have required IAM permissions to manage OKE clusters and networking.

2. Check if Your Cluster Allows Editing the Endpoint

  1. In the OCI Console, go to:
    • Main menu → Developer Services → Kubernetes Clusters (OKE).
  2. Select your Compartment.
  3. Click your Cluster name.
  4. On the Cluster details page:
    • Look for a button like Edit Kubernetes API endpoint, Update cluster, or similar under More actions.
    • If you see an option to change the Kubernetes API endpoint access, you can modify it in place.
    • If not, you will need to create a new cluster (see Section 4).
Proceed with Section 3 if endpoint edit is available.

3. Change an Existing Cluster to Private Endpoint Only

3.1 Prepare a Private Subnet (if not existing)

  1. Go to Networking → Virtual Cloud Networks.
  2. Select the VCN used by your OKE cluster.
  3. Under Subnets, create a new private subnet (if you don’t already have one suitable):
    • Subnet type: Regional
    • Private subnet: Enabled (no public IPs)
    • Add appropriate route table and security lists/NSGs so your admins can reach it.

3.2 Edit the Cluster Endpoint

  1. Go to Kubernetes Clusters (OKE).
  2. Select the Compartment and click your Cluster.
  3. On the Cluster details page, click:
    • More actions → Edit cluster or
    • Edit Kubernetes API endpoint (wording can differ slightly by region / console version).
  4. In the Kubernetes API endpoint access section:
    • Change to Private endpoint only (or uncheck “Public endpoint” if both are enabled).
    • Select the VCN and Private Subnet for the API endpoint.
    • (Optional) Attach Network Security Groups restricting which IPs / subnets can reach the endpoint.
  5. Click Save changes / Update.
The cluster control plane will update. This can take several minutes. The public endpoint will be removed once the update completes.

3.3 Update Your kubeconfig / Access Method

Once the endpoint is private-only:
  1. From a host that has network access to the private subnet (bastion, over VPN, etc.), run:
    • In OCI Console → Cluster details → Access Cluster → copy and run the oci ce cluster create-kubeconfig command.
  2. Confirm:
    • kubectl get nodes works from a network path that reaches the private subnet.
    • Access from the internet without VPN/bastion should no longer be possible.

4. If You Cannot Edit the Endpoint (Recreate Cluster as Private-Only)

If the cluster does not allow editing the endpoint:

4.1 Create a New OKE Cluster with Private-Only API Endpoint

  1. Go to Kubernetes Clusters (OKE)Create cluster.
  2. Choose Quick create or Custom create (Custom recommended for control).
  3. In the Kubernetes API endpoint access section:
    • Select Private endpoint (or deselect public so only private is enabled).
    • Choose the VCN and appropriate private subnet for the API endpoint.
  4. Complete other cluster settings (version, node pools, shapes, etc.).
  5. Create the cluster and wait until its status is Active.

4.2 Migrate Workloads

  1. Export current workloads from the old cluster (e.g., kubectl get all -A -o yaml or your manifests/Helm charts).
  2. Configure kubeconfig for the new cluster (via Access Cluster in cluster details).
  3. Apply manifests / reinstall Helm charts on the new cluster.
  4. Test workloads, ingress, services, and networking.
  5. Decommission the old cluster:
    • Drain and delete node pools.
    • Delete the old OKE cluster.

5. Validate That the Public Endpoint Is Disabled

  1. On Cluster details, confirm:
    • API Endpoint shows only a private IP / private FQDN.
    • No public endpoint is listed.
  2. From the public internet (without VPN/bastion), verify:
    • kubectl cannot reach the cluster.
    • Any previous public FQDN or IP is no longer responsive.
This fully remediates the issue: the Kubernetes API for OCI OKE is no longer exposed via a public endpoint and is accessible only over private network paths.
To disable the public Kubernetes API endpoint for an existing OKE cluster using OCI CLI, you update the cluster’s endpoint-config and set isPublicIpEnabled to false.Prereqs
  • OCI CLI installed and configured (oci setup config)
  • OCID of the OKE cluster
  • OCID of the subnet where the private endpoint will live (usually a private subnet in the same VCN)

Note the current endpoint-config values (especially subnetId and any nsgIds).

2. Build the new endpoint-config JSON

You want the same subnet and NSGs, but with isPublicIpEnabled set to false.Example (adjust OCIDs and NSGs as needed):
If you are not using NSGs, omit the nsgIds array:

3. Update the cluster to disable the public endpoint

This updates the control plane endpoint to private only in the specified subnet.

4. Verify the change

Ensure:

5. Update your access method

Once public access is disabled, you must:
  • Access the API from within the VCN (e.g., bastion host, VPN, FastConnect, VCN peering), and
  • Regenerate or update your kubeconfig as needed:
To remediate “OCI OKE Kubernetes API Public Endpoint Should Be Disabled” using Python, you need to update the OKE cluster’s endpoint configuration so that isPublicIpEnabled is set to False.Below are the minimal practical steps and a working Python example using the OCI Python SDK.

1. Prerequisites

  1. Install OCI Python SDK (if not already):
  2. Ensure you have:
    • A working OCI CLI/config file (typically at ~/.oci/config) with a profile that has permissions to update OKE clusters.
    • The OCID of the OKE cluster you want to remediate.
    • A private subnet OCID for the OKE endpoint (if your cluster is not already using a suitable subnet).
      • This subnet must:
        • Be in the same VCN/region as the cluster.
        • Have appropriate route tables and security lists/NSGs to allow access from your admin nodes/jump hosts.

2. Core Python Script to Disable Public Endpoint


3. High-Level Step-by-Step

  1. Identify the OKE cluster: Get its OCID from the console or CLI.
  2. Select/prepare a private subnet in the same VCN/region for the Kubernetes API endpoint.
  3. Configure OCI Python SDK:
    • Ensure ~/.oci/config exists and the profile has ContainerEngine permissions (e.g., MANAGE CLUSTER).
  4. Run the Python script:
    • It:
      • Fetches the cluster.
      • Sets endpoint_config.subnet_id to your private subnet.
      • Sets endpoint_config.is_public_ip_enabled = False.
      • Calls update_cluster.
  5. Verify:
    • In the OCI Console → Developer Services → Kubernetes Clusters → your cluster:
      • Confirm the API endpoint is now private-only (no public IP).
This change effectively disables the public Kubernetes API endpoint and forces access via the private network.
This change switches the Kubernetes API endpoint to use only a private IP; Terraform will update the cluster endpoint configuration in place (no resource replacement, but expect API control-plane unavailability during the update).To verify, terraform plan should show endpoint_config.is_public_ip_enabled changing from true to false on oci_containerengine_cluster.oke_cluster and no -/+ replacement indicator for the resource.