Using Kubernetes Workload Identity for client-server authorization

tudip-logo

Tudip

07 April 2020

Kubernetes service accounts are always the primary identification method in the Kubernetes clusters. Historically, these credentials have been scoped globally, and have been subject to relatively high replay risk and not available outside the cluster sense.

To make the use of this identity system easier for application developers, the mechanism can be made more transparent to both the client and the server. On the client side, a derived authorized HTTP client can be used that automatically injects the service account token into all outgoing HTTP requests. On the server side, authorization middleware can use OIDC discovery and the cluster’s public key to verify the request, before passing on the business logic of the function/handler. This tutorial demonstrates the use of these conveniences in the Go programming language.

Create the cluster

gcloud beta container clusters create $CLUSTER \
--identity-namespace=$PROJECT.svc.id.goog

The identity-namespace flag is part of the enablement of the Workload Identity feature. Currently only the single, project-level namespace is supported.

Creation of the cluster can take several minutes.

Deploy the server with cloud run

gcloud run deploy --image gcr.io/${PROJECT}/auth-server 
--allow-unauthenticated --platform managed auth-server 
--set-env-vars="ID_ISSUER=${ISSUER},JWT_AUDIENCE=TBD"

Cloud Run provides a convenient way to deploy HTTPS services and also offers its own authorization scheme which is covered in a later section of this tutorial.

Understanding the authorization middleware

The package and middleware perform the following steps:

  • Uses the ID_ISSUER environment variable to retrieve the issuer’s public keys through OIDC Discovery. GKE publishes the public keys at a public URL (jwks_uri link in the discovery document at https://[issuer]/.well-known/openid-configuration).
  • Verifies that the token has not expired.
  • Verifies that the signature on the JSON Web Token (JWT) sent as a header by the workload was signed by the retrieved issuer’s public key.

  • Verifies that the AUD (audience) claim inside the JWT payload matches the service URL set as the JWT_AUDIENCE environment variable.

The authorization middleware does not carry out any authorization actions based on which the identity of the workload has been verified — only 1) that it is a legitimate identity provided by a trusted issuer and 2) that the token was created for use with this target service.

Deploy the client to the cluster

Deploy the client to the cluster Because Workload Identity is available for a running workload, a local curl command doesn’t easily demonstrate this. Instead, you deploy a basic workload in this tutorial, which loops and allows requests for HTTP to the server.

Using Cloud Run Invoker IAM authorization with Workload Identity

Cloud Run offers an integrated authorization feature which acts as an alternative to the middleware used in previous sections of this tutorial.The Cloud Run service conducts the following tests when the Cloud Run Invoker IAM function is employed:

  • Is the JWT in an Authorization header issued (signed) by https://accounts.google.com?
  • Is the token un-expired?
  • Does the audience claim in the token match the target service?
  • Is the sub (subject), or principal, of the request a member of the service’s IAM invoker role?

The last test – against the IAM invoker function of the service – is an additional non-present authorization review in the middleware mentioned in previous parts of this tutorial, and it tests specific service accounts against a list or membership of Google Group.

Creating a service account to connect with Workload Identity

A primary use of GKE Workload Identity is to provide a way to act as a Google Cloud service account for accessing Google APIs to a Kubernetes service account.

Reconfigure the client to use the Google-issued identity

The main.go client program contains a switch statement that builds an authenticated HTTP client using the credential provided by the metadata server. In this section, you change an environment variable and then update the client configuration.

Add the Google Cloud service account to the invoker policy

Check client access

After letting the permissions propagate for a moment, check the output of the client:

kubectl logs -f auth-client -n id-namespace

Request a quote