Protecting Cluster Metadata

Overview

GKE uses instance metadata to configure node VMs, but some of this metadata is potentially sensitive and should be protected from workloads running on the cluster.

Before you begin

To prepare for this task, perform the following steps:

  • Ensure that you have enabled the Google Kubernetes Engine API.
  • Enable Google Kubernetes Engine API
  • Ensure that you have installed the Cloud SDK.
  • Set your default project ID:
    gcloud config set project [PROJECT_ID]
  • If you are working with zonal clusters, set your default compute zone:
    gcloud config set compute/zone [COMPUTE_ZONE]
  • If you are working with regional clusters, set your default compute region:
    gcloud config set compute/region [COMPUTE_REGION]
  • Update gcloud to the latest version:
    gcloud components update

Configure node service account

Because each node's service account credentials will continue to be exposed to workloads, you should ensure that you have configured a service account with the minimal permissions it needs. Then, attach this service account to your nodes, so that an attacker cannot circumvent GKE's metadata protections by using the Compute Engine API to access the node instances directly.

Do not use a service account that has compute.instances.get permission, the Compute Instance Admin role, or other similar permissions, as they allow potential attackers to obtain instance metadata using the Compute Engine API. The best practice is to restrict the permissions of a node VM by using service account permissions, not access scopes. For more information, see Compute Engine's service accounts documentation.

gcloud

If you don't have a node service account, you can create one using the following commands:

export NODE_SA_NAME=gke-node-sa
gcloud iam service-accounts create $NODE_SA_NAME \
  --display-name "Node Service Account"
export NODE_SA_EMAIL=gcloud iam service-accounts list --format='value(email)' \
  --filter='displayName:Node Service Account'

To configure your service account with the necessary roles and permissions, run the following commands. PROJECT is your project ID:

export PROJECT=gcloud config get-value project

gcloud projects add-iam-policy-binding $PROJECT \ --member serviceAccount:$NODE_SA_EMAIL \ --role roles/monitoring.metricWriter gcloud projects add-iam-policy-binding $PROJECT \ --member serviceAccount:$NODE_SA_EMAIL \ --role roles/monitoring.viewer gcloud projects add-iam-policy-binding $PROJECT \ --member serviceAccount:$NODE_SA_EMAIL \ --role roles/logging.logWriter

Additionally, if your cluster pulls private images from Container Registry, add the storage.objectViewer role:

gcloud projects add-iam-policy-binding $PROJECT \
  --member serviceAccount:$NODE_SA_EMAIL \
  --role roles/storage.objectViewer

Disabling legacy metadata APIs

Compute Engine's instance metadata server exposes legacy /0.1/ and /v1beta1/ endpoints, which do not enforce metadata query headers. This is a feature in the /v1/ APIs which makes it more difficult for a potential attacker to retrieve instance metadata. Unless specifically required, we recommend you disable these legacy APIs.

Creating a new node pool with legacy metadata APIs disabled

After creating a service account, you can create a new node pool (or a default node pool in a new cluster) with legacy metadata APIs disabled by using the gcloud command-line tool.

gcloud

To create a new node pool with legacy metadata APIs disabled, use the --metadata disable-legacy-endpoints=true flag. For example:

gcloud container node-pools create [POOL_NAME] \
  --service-account=$NODE_SA_EMAIL \
  --metadata disable-legacy-endpoints=true

A new cluster can be created with legacy metadata APIs disabled in the default node pool using the same flag. For example:

gcloud container clusters create [CLUSTER_NAME] \
  --service-account=$NODE_SA_EMAIL \
  --metadata disable-legacy-endpoints=true

Updating an existing cluster to disable legacy metadata APIs

After creating a new node pool with legacy metadata APIs disabled, you can update an existing cluster to use it by following the node pool migration guide.

Verifying that legacy metadata APIs are disabled

When the legacy instance metadata APIs are disabled, requests to /0.1/ and /v1beta1/ metadata server endpoints will return 403 Forbidden.

To verify that the legacy metadata APIs have been disabled, you can run a curl command from within a Pod:

cURL

root@pod-name# curl -H 'Metadata-Flavor: Google' \
'http://metadata.google.internal/computeMetadata/v1/instance/attributes/disable-legacy-endpoints'
true
root@pod-name# curl 'http://metadata.google.internal/computeMetadata/v1beta1/instance/id'
... Error 403 (Forbidden) ... Legacy metadata endpoint accessed: /computeMetadata/v1beta1/instance/id Legacy metadata endpoints are disabled. Please use the /v1/ endpoint. ...

Metadata concealment

GKE's metadata concealment protects some potentially sensitive system metadata from user workloads running on your cluster.

In Kubernetes v1.9.3 and higher, you can enable metadata concealment to prevent user Pods from accessing certain VM metadata for your cluster's nodes, such as Kubelet credentials and VM instance information. Specifically, metadata concealment protects access to kube-env (which contains Kubelet credentials) and the VM's instance identity token.

Metadata concealment firewalls traffic from user Pods (Pods not running on HostNetwork) to the cluster metadata server, only allowing safe queries. The firewall prevents user Pods from using Kubelet credentials for privilege escalation attacks, or from using VM identity for instance escalation attacks.

Limitations

  • Metadata concealment only protects access to kube-env and the node's instance identity token.
  • Metadata concealment does not restrict access to the node's service account.
  • Metadata concealment does not restrict access to other related instance metadata.
  • Metadata concealment does not restrict access to other legacy metadata APIs.

Creating a new cluster or node pool with metadata concealment

After creating a service account, you can create a new cluster with metadata concealment enabled by using the gcloud command-line tool.

gcloud

To create a cluster with metadata concealment enabled, run the following
command in your shell or terminal window:

gcloud beta container clusters create [CLUSTER_NAME] \ --workload-metadata-from-node=SECURE \ --service-account=$NODE_SA_EMAIL \ --metadata disable-legacy-endpoints=true \ --cluster-version=1.9 [additional parameters and flags omitted]

where:

  • [CLUSTER_NAME] is the name of the cluster to be created.
  • --workload-metadata-from-node is set to SECURE; setting the flag to EXPOSED or UNSPECIFIED disables metadata concealment.

Verifying identity token metadata concealed from cluster's workload

When you conceal metadata, it should not be possible to request a signature via the node's instance identity token. To verify that requests explicitly inform users of concealed metadata, you can run a curl command from

cURL

root@pod-name# curl -H "Metadata-Flavor: Google" \
'http://metadata/computeMetadata/v1/instance/service-accounts/default/identity?audience=https://www.example.com'
This metadata endpoint is concealed.

Was this page helpful? Let us know how we did:

Send feedback about...

Kubernetes Engine