gke-security
google/skills
Hardens Google Kubernetes Engine (GKE) clusters with Workload Identity, Secret Manager, RBAC, Binary Authorization, Network Policies, and Pod Security Standards.
...Expand allGKE Security
This reference covers security configuration for GKE clusters. The golden path enforces a hardened security posture by default.
MCP Tools:
get_cluster,check_k8s_auth,get_k8s_resource,apply_k8s_manifest,update_cluster
Golden Path Security Defaults
| Setting | Golden Path Value | Day-0/1 | Notes |
|---|---|---|---|
workloadIdentityConfig.workloadPool |
|
Day-0 | Workload Identity Federation for Pods |
secretManagerConfig.enabled |
true |
Day-1 | Google Secret Manager integration |
secretManagerConfig.rotationConfig |
enabled: true, rotationInterval: 120s |
Day-1 | Automatic secret rotation |
rbacBindingConfig.enableInsecureBindingSystemAuthenticated |
false |
Day-0 | Blocks legacy system:authenticated bindings |
rbacBindingConfig.enableInsecureBindingSystemUnauthenticated |
false |
Day-0 | Blocks legacy system:unauthenticated bindings |
nodeConfig.shieldedInstanceConfig.enableSecureBoot |
true |
Day-0 | Verifiable boot integrity |
nodeConfig.shieldedInstanceConfig.enableIntegrityMonitoring |
true |
Day-0 | Runtime integrity checks |
nodeConfig.workloadMetadataConfig.mode |
GKE_METADATA |
Day-0 | Blocks legacy metadata API, enforces Workload Identity |
| Private cluster + Dataplane V2 settings | See the gke-networking skill |
Day-0 | Private nodes, private endpoint enforcement, ADVANCED_DATAPATH |
Workload Identity Federation
Workload Identity is the recommended way for pods to access Google Cloud APIs. It eliminates the need for static service account keys.
Setup
# 1. Create a Google Service Account (GSA)
gcloud iam service-accounts create \
--project \
--display-name "Workload Identity SA" \
--quiet
# 2. Grant IAM roles to the GSA
gcloud projects add-iam-policy-binding \
--member "serviceAccount:@.iam.gserviceaccount.com" \
--role "" \
--quiet
# 3. Create Kubernetes Service Account (KSA)
kubectl create namespace
kubectl create serviceaccount --namespace
# 4. Bind KSA to GSA
gcloud iam service-accounts add-iam-policy-binding \
@.iam.gserviceaccount.com \
--role roles/iam.workloadIdentityUser \
--member "serviceAccount:.svc.id.goog[/]" \
--quiet
# 5. Annotate KSA
kubectl annotate serviceaccount \
--namespace \
iam.gke.io/gcp-service-account=@.iam.gserviceaccount.com
See assets/workload-identity-pod.yaml for a test pod.
Verification
kubectl run workload-identity-test \
--image=gcr.io/google.com/cloudsdktool/cloud-sdk:slim \
--serviceaccount= --namespace= \
--rm -it -- gcloud auth list --quiet
Secret Manager Integration
The golden path enables Secret Manager with automatic rotation. Secrets are synced to Kubernetes Secrets.
# Verify Secret Manager is enabled on cluster
gcloud container clusters describe --region \
--format="value(secretManagerConfig.enabled)" \
--quiet
# Enable if not already (Day-1 change)
gcloud container clusters update --region \
--enable-secret-manager \
--secret-manager-rotation-interval=120s \
--quiet
Mounting Secrets via CSI Volume (Deployment Example)
Once the Secret Manager add-on is enabled, workloads can mount secrets as volumes using the Secrets Store CSI driver. This requires two steps:
- Define a
SecretProviderClassto specify which secrets to retrieve from Secret Manager. - Mount the volume in a
Deploymentreferencing that class.
[!IMPORTANT] Production Best Practice: Always demonstrate workload integrations (like Secret Manager CSI) using production-standard
Deploymentmanifests rather than rawPodmanifests.
Step 1: Create the SecretProviderClass
apiVersion: secrets-store.csi.x-k8s.io/v1
kind: SecretProviderClass
metadata:
name: app-secrets-provider
namespace: default
spec:
provider: gke # Identifies GKE managed provider
parameters:
secrets: |
- resourceName: "projects//secrets/db-password/versions/latest"
fileName: "db-password.txt"
Step 2: Mount the secret in a Deployment
apiVersion: apps/v1
kind: Deployment
metadata:
name: secure-app
namespace: default
spec:
replicas: 2
selector:
matchLabels:
app: secure-app
template:
metadata:
labels:
app: secure-app
spec:
serviceAccountName: secure-ksa # Must be bound to GSA with Secret Manager Secret Accessor role
containers:
- name: app
image:
volumeMounts:
- name: secrets-volume
mountPath: "/var/secrets"
readOnly: true
volumes:
- name: secrets-volume
csi:
driver: secrets-store.csi.k8s.io
readOnly: true
volumeAttributes:
secretProviderClass: "app-secrets-provider"
RBAC Hardening
The golden path disables insecure legacy RBAC bindings that grant broad access
to system:authenticated and system:unauthenticated groups.
# Verify insecure bindings are disabled
gcloud container clusters describe --region \
--format="yaml(rbacBindingConfig)" \
--quiet
Best practices for RBAC:
- Use namespace-scoped Roles over cluster-wide ClusterRoles
- Bind to specific Groups or ServiceAccounts, never to
system:authenticated - Audit permissions via MCP:
check_k8s_auth(parent="...", verb="list", resourceType="pods", namespace="...")(orkubectl auth can-i --list --as=) - Review bindings via MCP:
get_k8s_resource(parent="...", resourceType="clusterrolebinding")(orkubectl get clusterrolebindings,rolebindings --all-namespaces)
See the
gke-multitenancyskill for enterprise RBAC planning and https://docs.cloud.google.com/kubernetes-engine/docs/best-practices/rbac.md.txt
Binary Authorization
Not enabled in golden path by default but recommended for production image provenance:
# Enable Binary Authorization
gcloud container clusters update --region \
--binauthz-evaluation-mode=PROJECT_SINGLETON_POLICY_ENFORCE \
--quiet
Network Policies
Dataplane V2 (golden path) provides built-in Network Policy enforcement. Apply default-deny per namespace:
# MCP (preferred)
apply_k8s_manifest(parent="...", yamlManifest="")
# kubectl fallback
kubectl apply -f ./assets/default-deny-netpol.yaml -n
GKE Sandbox (gVisor)
For running untrusted workloads in an isolated sandbox:
# Enable on cluster (Standard clusters)
gcloud container clusters update --region --enable-gke-sandbox --quiet
# Use in pod spec
# Add: runtimeClassName: gvisor
Pod Security Standards (Golden Path)
Pod Security Standards define three profiles that restrict what pods can do. The
restricted profile is the golden path default for production namespaces.
| Profile | Level | Use Case |
|---|---|---|
privileged |
Unrestricted | System namespaces (kube-system), |
| : : : infrastructure controllers : | ||
baseline |
Minimally restrictive | Shared/dev namespaces, legacy apps |
| : : : being migrated : | ||
restricted |
Golden path | Production workloads -- blocks |
| : : : privilege escalation, host access, : | ||
| : : : root : |
Enforce via namespace labels (Pod Security Admission):
apiVersion: v1
kind: Namespace
metadata:
name: production
labels:
pod-security.kubernetes.io/enforce: restricted
pod-security.kubernetes.io/warn: restricted
pod-security.kubernetes.io/audit: restricted
Gradual rollout strategy:
- Start with
warn+auditon existing namespaces to identify violations - Fix non-compliant workloads (remove
privileged,hostNetwork, root user, etc.) - Enable
enforceonce all workloads pass
restricted blocks: running as root, privilege escalation, host
networking/PID/IPC, host path volumes, and most capabilities. The golden path
workload-identity-pod.yaml already complies.
Network Policy Logging (Recommended)
With Dataplane V2 (golden path), you can enable logging for Network Policy decisions. Not a golden path default -- recommended for security auditing.
gcloud container clusters update --region \
--enable-network-policy-logging \
--quiet
This logs allowed and denied connections, useful for troubleshooting Network Policy rules and auditing traffic flows.
Common IAM Roles
The five most common predefined IAM roles for GKE:
| Role | Purpose | When to Use |
|---|---|---|
roles/container.admin |
Full control over | Platform team admins |
| : : clusters and : managing cluster : | ||
| : : Kubernetes : lifecycle : | ||
| : : resources : : | ||
roles/container.clusterAdmin |
Manage clusters but | Cluster operators |
| : : not project-level : who create/delete : | ||
| : : IAM : clusters : | ||
roles/container.developer |
Deploy workloads | Application |
| : : (pods, services, : developers deploying : | ||
| : : deployments) : to existing clusters : | ||
roles/container.viewer |
Read-only access to | Monitoring, |
| : : clusters and : auditing, or : | ||
| : : Kubernetes : read-only dashboards : | ||
| : : resources : : | ||
roles/container.clusterViewer |
List and get | CI/CD pipelines that |
| : : cluster details : need cluster : | ||
| : : only : metadata : |
Principle of least privilege: Start with
roles/container.viewerorroles/container.developerand escalate only as needed. Avoid grantingroles/container.adminbroadly.
Service Accounts & Agents
- GKE Service Agent
(
service-): Automatically created. Manages nodes, networking, and cluster operations on your behalf. Do not remove or modify its permissions.@container-engine-robot.iam.gserviceaccount.com - Node Service Account: By default, nodes use the Compute Engine default service account. For production, create a dedicated SA with minimal permissions and assign it via node pool config.
- Workload Identity: The recommended way for pods to access Google Cloud APIs. Maps a Kubernetes ServiceAccount to a Google IAM ServiceAccount — see Workload Identity setup above.
Cross-Service Authentication Patterns
Common patterns for granting GKE workloads access to other Google Cloud services:
# Grant a GKE workload access to Cloud Storage
gcloud projects add-iam-policy-binding \
--member "serviceAccount:@.iam.gserviceaccount.com" \
--role "roles/storage.objectViewer" \
--quiet
# Grant a GKE workload access to Cloud SQL
gcloud projects add-iam-policy-binding \
--member "serviceAccount:@.iam.gserviceaccount.com" \
--role "roles/cloudsql.client" \
--quiet
# Grant a GKE workload access to Pub/Sub
gcloud projects add-iam-policy-binding \
--member "serviceAccount:@.iam.gserviceaccount.com" \
--role "roles/pubsub.subscriber" \
--quiet
In all cases, the GSA must be bound to a KSA via Workload Identity (see setup above). The pod then uses the KSA to authenticate as the GSA.
---
name: gke-security
description: Hardens Google Kubernetes Engine (GKE) clusters with Workload Identity, Secret Manager, RBAC, Binary Authorization, Network Policies, and Pod Security Standards.
---
# GKE Security
This reference covers security configuration for GKE clusters. The golden path
enforces a hardened security posture by default.
> **MCP Tools:** `get_cluster`, `check_k8s_auth`, `get_k8s_resource`,
> `apply_k8s_manifest`, `update_cluster`
## Golden Path Security Defaults
Setting | Golden Path Value | Day-0/1 | Notes
-------------------------------------------------------------- | --------------------------------------- | ------- | -----
`workloadIdentityConfig.workloadPool` | `<PROJECT>.svc.id.goog` | Day-0 | Workload Identity Federation for Pods
`secretManagerConfig.enabled` | `true` | Day-1 | Google Secret Manager integration
`secretManagerConfig.rotationConfig` | `enabled: true, rotationInterval: 120s` | Day-1 | Automatic secret rotation
`rbacBindingConfig.enableInsecureBindingSystemAuthenticated` | `false` | Day-0 | Blocks legacy `system:authenticated` bindings
`rbacBindingConfig.enableInsecureBindingSystemUnauthenticated` | `false` | Day-0 | Blocks legacy `system:unauthenticated` bindings
`nodeConfig.shieldedInstanceConfig.enableSecureBoot` | `true` | Day-0 | Verifiable boot integrity
`nodeConfig.shieldedInstanceConfig.enableIntegrityMonitoring` | `true` | Day-0 | Runtime integrity checks
`nodeConfig.workloadMetadataConfig.mode` | `GKE_METADATA` | Day-0 | Blocks legacy metadata API, enforces Workload Identity
Private cluster + Dataplane V2 settings | See the `gke-networking` skill | Day-0 | Private nodes, private endpoint enforcement, ADVANCED_DATAPATH
## Workload Identity Federation
Workload Identity is the recommended way for pods to access Google Cloud APIs.
It eliminates the need for static service account keys.
### Setup
```bash
# 1. Create a Google Service Account (GSA)
gcloud iam service-accounts create <GSA_NAME> \
--project <PROJECT_ID> \
--display-name "Workload Identity SA" \
--quiet
# 2. Grant IAM roles to the GSA
gcloud projects add-iam-policy-binding <PROJECT_ID> \
--member "serviceAccount:<GSA_NAME>@<PROJECT_ID>.iam.gserviceaccount.com" \
--role "<ROLE>" \
--quiet
# 3. Create Kubernetes Service Account (KSA)
kubectl create namespace <NAMESPACE>
kubectl create serviceaccount <KSA_NAME> --namespace <NAMESPACE>
# 4. Bind KSA to GSA
gcloud iam service-accounts add-iam-policy-binding \
<GSA_NAME>@<PROJECT_ID>.iam.gserviceaccount.com \
--role roles/iam.workloadIdentityUser \
--member "serviceAccount:<PROJECT_ID>.svc.id.goog[<NAMESPACE>/<KSA_NAME>]" \
--quiet
# 5. Annotate KSA
kubectl annotate serviceaccount <KSA_NAME> \
--namespace <NAMESPACE> \
iam.gke.io/gcp-service-account=<GSA_NAME>@<PROJECT_ID>.iam.gserviceaccount.com
```
> See [assets/workload-identity-pod.yaml](./assets/workload-identity-pod.yaml)
> for a test pod.
### Verification
```bash
kubectl run workload-identity-test \
--image=gcr.io/google.com/cloudsdktool/cloud-sdk:slim \
--serviceaccount=<KSA_NAME> --namespace=<NAMESPACE> \
--rm -it -- gcloud auth list --quiet
```
## Secret Manager Integration
The golden path enables Secret Manager with automatic rotation. Secrets are
synced to Kubernetes Secrets.
```bash
# Verify Secret Manager is enabled on cluster
gcloud container clusters describe <CLUSTER_NAME> --region <REGION> \
--format="value(secretManagerConfig.enabled)" \
--quiet
# Enable if not already (Day-1 change)
gcloud container clusters update <CLUSTER_NAME> --region <REGION> \
--enable-secret-manager \
--secret-manager-rotation-interval=120s \
--quiet
```
### Mounting Secrets via CSI Volume (Deployment Example)
Once the Secret Manager add-on is enabled, workloads can mount secrets as
volumes using the Secrets Store CSI driver. This requires two steps:
1. **Define a `SecretProviderClass`** to specify which secrets to retrieve from
Secret Manager.
2. **Mount the volume in a `Deployment`** referencing that class.
> [!IMPORTANT] **Production Best Practice**: Always demonstrate workload
> integrations (like Secret Manager CSI) using production-standard
> **`Deployment`** manifests rather than raw `Pod` manifests.
#### Step 1: Create the SecretProviderClass
```yaml
apiVersion: secrets-store.csi.x-k8s.io/v1
kind: SecretProviderClass
metadata:
name: app-secrets-provider
namespace: default
spec:
provider: gke # Identifies GKE managed provider
parameters:
secrets: |
- resourceName: "projects/<PROJECT_ID>/secrets/db-password/versions/latest"
fileName: "db-password.txt"
```
#### Step 2: Mount the secret in a Deployment
```yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: secure-app
namespace: default
spec:
replicas: 2
selector:
matchLabels:
app: secure-app
template:
metadata:
labels:
app: secure-app
spec:
serviceAccountName: secure-ksa # Must be bound to GSA with Secret Manager Secret Accessor role
containers:
- name: app
image: <IMAGE>
volumeMounts:
- name: secrets-volume
mountPath: "/var/secrets"
readOnly: true
volumes:
- name: secrets-volume
csi:
driver: secrets-store.csi.k8s.io
readOnly: true
volumeAttributes:
secretProviderClass: "app-secrets-provider"
```
## RBAC Hardening
The golden path disables insecure legacy RBAC bindings that grant broad access
to `system:authenticated` and `system:unauthenticated` groups.
```bash
# Verify insecure bindings are disabled
gcloud container clusters describe <CLUSTER_NAME> --region <REGION> \
--format="yaml(rbacBindingConfig)" \
--quiet
```
**Best practices for RBAC:**
- Use namespace-scoped Roles over cluster-wide ClusterRoles
- Bind to specific Groups or ServiceAccounts, never to `system:authenticated`
- Audit permissions via MCP: `check_k8s_auth(parent="...", verb="list",
resourceType="pods", namespace="...")` (or `kubectl auth can-i --list
--as=<user>`)
- Review bindings via MCP: `get_k8s_resource(parent="...",
resourceType="clusterrolebinding")` (or `kubectl get
clusterrolebindings,rolebindings --all-namespaces`)
> See the `gke-multitenancy` skill for enterprise RBAC planning and
> https://docs.cloud.google.com/kubernetes-engine/docs/best-practices/rbac.md.txt
## Binary Authorization
Not enabled in golden path by default but recommended for production image
provenance:
```bash
# Enable Binary Authorization
gcloud container clusters update <CLUSTER_NAME> --region <REGION> \
--binauthz-evaluation-mode=PROJECT_SINGLETON_POLICY_ENFORCE \
--quiet
```
## Network Policies
Dataplane V2 (golden path) provides built-in Network Policy enforcement. Apply
default-deny per namespace:
```
# MCP (preferred)
apply_k8s_manifest(parent="...", yamlManifest="<contents of default-deny-netpol.yaml>")
# kubectl fallback
kubectl apply -f ./assets/default-deny-netpol.yaml -n <NAMESPACE>
```
## GKE Sandbox (gVisor)
For running untrusted workloads in an isolated sandbox:
```bash
# Enable on cluster (Standard clusters)
gcloud container clusters update <CLUSTER_NAME> --region <REGION> --enable-gke-sandbox --quiet
# Use in pod spec
# Add: runtimeClassName: gvisor
```
## Pod Security Standards (Golden Path)
Pod Security Standards define three profiles that restrict what pods can do. The
**`restricted` profile is the golden path default** for production namespaces.
| Profile | Level | Use Case |
| ------------ | --------------------- | ---------------------------------- |
| `privileged` | Unrestricted | System namespaces (`kube-system`), |
: : : infrastructure controllers :
| `baseline` | Minimally restrictive | Shared/dev namespaces, legacy apps |
: : : being migrated :
| `restricted` | **Golden path** | Production workloads -- blocks |
: : : privilege escalation, host access, :
: : : root :
**Enforce via namespace labels (Pod Security Admission):**
```yaml
apiVersion: v1
kind: Namespace
metadata:
name: production
labels:
pod-security.kubernetes.io/enforce: restricted
pod-security.kubernetes.io/warn: restricted
pod-security.kubernetes.io/audit: restricted
```
**Gradual rollout strategy:**
1. Start with `warn` + `audit` on existing namespaces to identify violations
2. Fix non-compliant workloads (remove `privileged`, `hostNetwork`, root user,
etc.)
3. Enable `enforce` once all workloads pass
`restricted` blocks: running as root, privilege escalation, host
networking/PID/IPC, host path volumes, and most capabilities. The golden path
`workload-identity-pod.yaml` already complies.
## Network Policy Logging (Recommended)
With Dataplane V2 (golden path), you can enable logging for Network Policy
decisions. **Not a golden path default** -- recommended for security auditing.
```bash
gcloud container clusters update <CLUSTER_NAME> --region <REGION> \
--enable-network-policy-logging \
--quiet
```
This logs allowed and denied connections, useful for troubleshooting Network
Policy rules and auditing traffic flows.
## Common IAM Roles
The five most common predefined IAM roles for GKE:
| Role | Purpose | When to Use |
| ------------------------------- | ------------------- | -------------------- |
| `roles/container.admin` | Full control over | Platform team admins |
: : clusters and : managing cluster :
: : Kubernetes : lifecycle :
: : resources : :
| `roles/container.clusterAdmin` | Manage clusters but | Cluster operators |
: : not project-level : who create/delete :
: : IAM : clusters :
| `roles/container.developer` | Deploy workloads | Application |
: : (pods, services, : developers deploying :
: : deployments) : to existing clusters :
| `roles/container.viewer` | Read-only access to | Monitoring, |
: : clusters and : auditing, or :
: : Kubernetes : read-only dashboards :
: : resources : :
| `roles/container.clusterViewer` | List and get | CI/CD pipelines that |
: : cluster details : need cluster :
: : only : metadata :
> **Principle of least privilege**: Start with `roles/container.viewer` or
> `roles/container.developer` and escalate only as needed. Avoid granting
> `roles/container.admin` broadly.
## Service Accounts & Agents
- **GKE Service Agent**
(`service-<PROJECT_NUMBER>@container-engine-robot.iam.gserviceaccount.com`):
Automatically created. Manages nodes, networking, and cluster operations on
your behalf. Do not remove or modify its permissions.
- **Node Service Account**: By default, nodes use the Compute Engine default
service account. For production, create a dedicated SA with minimal
permissions and assign it via node pool config.
- **Workload Identity**: The recommended way for pods to access Google Cloud
APIs. Maps a Kubernetes ServiceAccount to a Google IAM ServiceAccount — see
[Workload Identity setup](#workload-identity-federation) above.
## Cross-Service Authentication Patterns
Common patterns for granting GKE workloads access to other Google Cloud
services:
```bash
# Grant a GKE workload access to Cloud Storage
gcloud projects add-iam-policy-binding <PROJECT_ID> \
--member "serviceAccount:<GSA_NAME>@<PROJECT_ID>.iam.gserviceaccount.com" \
--role "roles/storage.objectViewer" \
--quiet
# Grant a GKE workload access to Cloud SQL
gcloud projects add-iam-policy-binding <PROJECT_ID> \
--member "serviceAccount:<GSA_NAME>@<PROJECT_ID>.iam.gserviceaccount.com" \
--role "roles/cloudsql.client" \
--quiet
# Grant a GKE workload access to Pub/Sub
gcloud projects add-iam-policy-binding <PROJECT_ID> \
--member "serviceAccount:<GSA_NAME>@<PROJECT_ID>.iam.gserviceaccount.com" \
--role "roles/pubsub.subscriber" \
--quiet
```
In all cases, the GSA must be bound to a KSA via Workload Identity (see setup
above). The pod then uses the KSA to authenticate as the GSA.
All Files
0 filesInstall gke-security
Download and extract the skill files to your .claude/skills/ directory.
Download ZIPClone the repository and copy the skill files to your project.
git clone https://github.com/google/skills/tree/main/skills/cloud/gke-security # Copy SKILL.md to your .claude/skills/ directory
Copy





Home
