Loading...
Loading...
Plans, configures, and hardens Google Kubernetes Engine (GKE) security. Covers Workload Identity Federation, Secret Manager integration, RBAC hardening, Binary Authorization, Network Policies (Dataplane V2), Pod Security Standards, and IAM roles. Use when securing GKE clusters, setting up Workload Identity, hardening RBAC configurations, or configuring GKE secrets. Don't use for general network routing configuration (use gke-networking instead).
npx skill4agent add google/skills gke-securityMCP Tools:,get_cluster,check_k8s_auth,get_k8s_resource,apply_k8s_manifestupdate_cluster
| Setting | Golden Path Value | Day-0/1 | Notes |
|---|---|---|---|
| | Day-0 | Workload Identity Federation for Pods |
| | Day-1 | Google Secret Manager integration |
| | Day-1 | Automatic secret rotation |
| | Day-0 | Blocks legacy |
| | Day-0 | Blocks legacy |
| | Day-0 | Verifiable boot integrity |
| | Day-0 | Runtime integrity checks |
| | Day-0 | Blocks legacy metadata API, enforces Workload Identity |
| Private cluster + Dataplane V2 settings | See the | Day-0 | Private nodes, private endpoint enforcement, ADVANCED_DATAPATH |
# 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.comSee assets/workload-identity-pod.yaml for a test pod.
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# 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 \
--quietSecretProviderClassDeployment[!IMPORTANT] Production Best Practice: Always demonstrate workload integrations (like Secret Manager CSI) using production-standardmanifests rather than rawDeploymentmanifests.Pod
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"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"system:authenticatedsystem:unauthenticated# Verify insecure bindings are disabled
gcloud container clusters describe <CLUSTER_NAME> --region <REGION> \
--format="yaml(rbacBindingConfig)" \
--quietsystem:authenticatedcheck_k8s_auth(parent="...", verb="list", resourceType="pods", namespace="...")kubectl auth can-i --list --as=<user>get_k8s_resource(parent="...", resourceType="clusterrolebinding")kubectl get clusterrolebindings,rolebindings --all-namespacesSee theskill for enterprise RBAC planning and https://docs.cloud.google.com/kubernetes-engine/docs/best-practices/rbac.md.txtgke-multitenancy
# Enable Binary Authorization
gcloud container clusters update <CLUSTER_NAME> --region <REGION> \
--binauthz-evaluation-mode=PROJECT_SINGLETON_POLICY_ENFORCE \
--quiet# 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># Enable on cluster (Standard clusters)
gcloud container clusters update <CLUSTER_NAME> --region <REGION> --enable-gke-sandbox --quiet
# Use in pod spec
# Add: runtimeClassName: gvisorrestricted| Profile | Level | Use Case |
|---|---|---|
| Unrestricted | System namespaces ( |
| : : : infrastructure controllers : | ||
| Minimally restrictive | Shared/dev namespaces, legacy apps |
| : : : being migrated : | ||
| Golden path | Production workloads -- blocks |
| : : : privilege escalation, host access, : | ||
| : : : root : |
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: restrictedwarnauditprivilegedhostNetworkenforcerestrictedworkload-identity-pod.yamlgcloud container clusters update <CLUSTER_NAME> --region <REGION> \
--enable-network-policy-logging \
--quiet| Role | Purpose | When to Use |
|---|---|---|
| Full control over | Platform team admins |
| : : clusters and : managing cluster : | ||
| : : Kubernetes : lifecycle : | ||
| : : resources : : | ||
| Manage clusters but | Cluster operators |
| : : not project-level : who create/delete : | ||
| : : IAM : clusters : | ||
| Deploy workloads | Application |
| : : (pods, services, : developers deploying : | ||
| : : deployments) : to existing clusters : | ||
| Read-only access to | Monitoring, |
| : : clusters and : auditing, or : | ||
| : : Kubernetes : read-only dashboards : | ||
| : : resources : : | ||
| List and get | CI/CD pipelines that |
| : : cluster details : need cluster : | ||
| : : only : metadata : |
Principle of least privilege: Start withorroles/container.viewerand escalate only as needed. Avoid grantingroles/container.developerbroadly.roles/container.admin
service-<PROJECT_NUMBER>@container-engine-robot.iam.gserviceaccount.com# 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