Review public access to GKE nodes and the control plane

Review external IPs on GKE nodes and access paths to the control plane separately, and permit only required administration paths.

Description

Public access to GKE nodes and the control plane requires separate controls. Private nodes operate without external IPs, but that alone does not disable the control plane's external IP endpoint. Confirm which public paths are necessary and combine network restrictions with IAM and Kubernetes RBAC permissions.

Potential impact

  • Reachable public paths and broad firewall permissions can expose node services to unwanted connection attempts.
  • Broad control-plane access combined with misuse of credentials or permissions can lead to changes to workloads and cluster configuration. A public endpoint does not itself remove authentication.

Remediation

  1. Use private nodes for internal workloads and provide the outbound and administration paths they need.
  2. Review control-plane IP and DNS endpoints separately. Disable the external IP endpoint or limit its administration sources, and apply appropriate IAM and network controls to DNS access.
  3. Change settings through supported GKE management procedures and test access for operators, automation, and nodes. Retain strong authentication and least-privilege RBAC.

Examples

These excerpts compare settings for new clusters. Supply version-appropriate VPC, subnet, IP allocation, required control-plane CIDR, project, and authentication inputs separately. They omit basic username/password authentication, which current GKE does not support.

Before

yaml
- name: create a cluster1
  google.cloud.gcp_container_cluster:
    name: my-cluster1
    initial_node_count: 2
    node_config:
      machine_type: n1-standard-4
      disk_size_gb: 500
    location: us-central1-a
    project: "{{ project_id }}"
    auth_kind: serviceaccount
    service_account_file: "/tmp/auth.pem"
    state: present

- name: create a cluster4
  google.cloud.gcp_container_cluster:
    name: my-cluster4
    initial_node_count: 2
    node_config:
      machine_type: n1-standard-4
      disk_size_gb: 500
    location: us-central1-a
    project: "{{ project_id }}"
    auth_kind: serviceaccount
    service_account_file: "/tmp/auth.pem"
    state: present
    private_cluster_config:
      enable_private_endpoint: no
      enable_private_nodes: yes

The first configuration does not explicitly configure private networking. The second uses private nodes but does not disable the external IP endpoint.

After

yaml
- name: create a cluster
  google.cloud.gcp_container_cluster:
    name: my-cluster
    initial_node_count: 2
    node_config:
      machine_type: n1-standard-4
      disk_size_gb: 500
    location: us-central1-a
    project: "{{ project_id }}"
    auth_kind: serviceaccount
    service_account_file: /tmp/auth.pem
    state: present
    private_cluster_config:
      enable_private_endpoint: yes
      enable_private_nodes: yes

This enables both enable_private_nodes and enable_private_endpoint. Review DNS endpoint access separately. These examples create differently named clusters and do not replace the procedure for updating an existing cluster or migrating its workloads.

References