Enabling GKE Workload Identity
Tags: googlecloud, devops, kubernetes, gcp
Published: 2019-12-21 16:33:00

*Originally published at [pbhadani.com](https://pbhadani.com/posts/gke-workload-identity/)*
<br>
In this blog, I will talk about the GKE Workload Identity feature and why to use this feature.

![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/jxwpgdkm0cusoodo6wgw.jpg)
<center><font size="1"> Photo by [chuttersnap](https://unsplash.com/@chuttersnap) on [Unsplash](https://unsplash.com)</font></center>


## What's the Problem?
An application running on GKE must authenticate to use Google Services such as Google Cloud Storage (GCS), Cloud SQL, BigQuery, etc.
Authentication can be done by providing a service account key JSON file to an application using Kubernetes Secret space or a different method such as Vault.
But in these approaches, service account key JSON (which has 10years of a lifetime) must be stored in plain text within the pod or base64 encoded in Kubernetes secret space.
Also, the key rotation process must be in a place that is not a fun process.

We can avoid using the service account key by attaching a service account to Kubernetes Node but then all the pods running on the Node gets the same permission which is not an ideal thing to do.


## Goal?
We want to assign a service account to a Pod so we can isolate permissions for different pods.

Hurray, we have Workload Identity feature available in beta which solves this problem on GKE.

## So, What is Workload Identity?
As per Google documentation, "*Workload Identity is the recommended way to access Google Cloud services from within GKE due to its improved security properties and manageability.*"

GKE Workload identity allows us to attach the service account to the Kubernetes pod and remove the hassle to manage the service account credentials JSON file within the pod or cluster.


## Let's use Workload Identity in a GKE cluster

### Prerequisites
1. If you have not setup `gcloud` on your workstation, then refer my [previous blog](https://pbhadani.com/posts/getting-started-wth-google-cloud-sdk/) to get it up and running quickly.  
    Alternatively, you can use [Google Cloud Shell](https://cloud.google.com/shell/) to run the commands.

2. Make sure you are a Project Editor or Project Owner or have enough permissions to run the below commands.

### Setup a GKE Cluster
Follow the below step to create a new GKE Cluster and enable Workload Identity.

**Step 1:** Enable the [Cloud IAM API](https://console.cloud.google.com/apis/api/iamcredentials.googleapis.com/).

**Step 2:** Install and configure `gke-gcloud-auth-plugin`.  
`gke-gcloud-auth-plugin` is the new Kubectl authentication plugin for GKE. Please read the [documentation](https://cloud.google.com/blog/products/containers-kubernetes/kubectl-auth-changes-in-gke) for more details.

 * Install plugin
```bash
gcloud components install gke-gcloud-auth-plugin
```
 **Note:** If `gcloud CLI component manager` is disabled, use the `yum` or `apt` package to install this plugin.
 For Debian:
 ```bash
sudo apt-get install google-cloud-sdk-gke-gcloud-auth-plugin
 ```

 * Configure plugin
```bash
echo "export USE_GKE_GCLOUD_AUTH_PLUGIN=True" >> ~/.bashrc
source ~/.bashrc
```

**Step 3:** Set GCP defaults.
   * Set GCP Project
  ```bash
  export GCP_PROJECT_ID=<YOUR_GCP_PROJECT_ID>
  
  gcloud config set project $GCP_PROJECT_ID
  ```
   
   * Set default region and zone
  ```bash
  gcloud config set compute/region europe-west1

  gcloud config set compute/zone europe-west1-b
  ```

**Step 4:** Make sure you have `kubectl` command installed.
   ```bash
   sudo apt-get install kubectl
   ```
   Run following to verify
   ```bash
   kubectl help
   ```
**Note:** Please refer documentation: [External package managers](https://cloud.google.com/sdk/docs/components#external_package_managers)


**Step 5:** Create a new Google Service Account (GSA).
  ```bash
  gcloud iam service-accounts create workload-identity-test
  ```
  **Notes:**
  You can use the existing service account.
  Permission Required: `iam.serviceAccounts.create` on the GCP Project.

**Step 6:** Add permissions to the Google Service Account required by an application. For example, `roles/storage.objectViewer`
  ```bash
  gcloud projects add-iam-policy-binding $GCP_PROJECT_ID \
  --member serviceAccount:workload-identity-test@${GCP_PROJECT_ID}.iam.gserviceaccount.com \
  --role roles/storage.objectViewer
  ```

**Step 7:** Setup a GKE cluster with *Workload Identity* enabled.
  ```bash
  export GKE_CLUSTER_NAME=gke-wi
  ```
  ```bash
  gcloud container clusters create $GKE_CLUSTER_NAME \
  --cluster-version=1.24 \
  --workload-pool=$GCP_PROJECT_ID.svc.id.goog
  ```
  **Notes:**
  GKE Cluster could take 5-10mins to become fully functional.
  Permission required: `container.clusters.create` on the GCP Project.

**Step 8:** Configure `kubectl` command on your terminal.
  ```bash
  gcloud container clusters get-credentials $GKE_CLUSTER_NAME
  ```
  **Notes:**
  This will populate `~/.kube/config` file.
  Permission Required: `container.clusters.get` on the GCP Project.

**Step 9:** (Optional) Create a Kubernetes namespace if you don't want to use `default` namespace.
  ```bash
  kubectl create namespace newspace
  ```

**Step 10:** Create Kubernetes Service Account (KSA).
  ```bash
  kubectl create serviceaccount \
 --namespace newspace \
 workload-identity-test-ksa
```

**Step 11:** Bind the Google Service Account (GSA) and Kubernetes Service Account (KSA), so that KSA can use the permissions granted to GSA.
  ```bash
  gcloud iam service-accounts add-iam-policy-binding \
  --role roles/iam.workloadIdentityUser \
  --member "serviceAccount:${GCP_PROJECT_ID}.svc.id.goog[newspace/workload-identity-test-ksa]" \
  workload-identity-test@${GCP_PROJECT_ID}.iam.gserviceaccount.com
  ```

**Step 12:** Add annotation
  ```bash
  kubectl annotate serviceaccount \
  --namespace newspace \
  workload-identity-test-ksa \
  iam.gke.io/gcp-service-account=workload-identity-test@${GCP_PROJECT_ID}.iam.gserviceaccount.com
  ```

**Step 13:** Create a Pod with the KSA created to verify.
  ```bash
  kubectl run --rm -it test-pod \
  --image google/cloud-sdk:slim \
  --namespace newspace \
  --overrides='{ "spec": { "serviceAccount": "workload-identity-test-ksa" }  }' sh
  ```
  Running above command will login to Pod and provides its bash shell.
  Now run below command to see which service account this pod is configured with.
  ```bash
  gcloud auth list
  ```

  This should print the GSA name.
  ```
                           Credentialed Accounts
    ACTIVE  ACCOUNT
    *       workload-identity-test@workshop-demo-namwcb.iam.gserviceaccount.com
  ```

### Cleanup
Don't forget to cleanup the resources, once you no longer need it.  
Run the following commands:

**Step 1:** Delete the GKE cluster.
  ```bash
  gcloud container clusters delete $GKE_CLUSTER_NAME
  ```

**Step 2:** Delete the Google Service Account (GSA).
  ```bash
  gcloud iam service-accounts delete workload-identity-test@${GCP_PROJECT_ID}.iam.gserviceaccount.com
  ```

<br>
Below is the terminal recording:
{% asciinema 510097 %}

*Hope this blog helps you get familiar with Workload Identity and securely deploy apps on GKE.*

If you have feedback or questions, please reach out to me on [LinkedIn](https://linkedin.com/in/pradeepbhadani) or [Twitter](https://twitter.com/bhadanipradeep)