Authenticating using Workload Identity Federation to Cloud Run, Cloud Functions

Overview

Authenticating using Workload Identity Federation to Cloud Run, Cloud Functions

This tutorial and code samples cover how customers that use Workload identity federation can authenticate to those GCP Services like Cloud Run and Cloud Functions which accept OpenID Connect (OIDC) tokens.

Basically, this walks you through a self-contained setup where you will:

  1. Configure a fake OIDC identity "provider" on Cloud Run which returns fake OIDC tokens (eg. ambient credentials)
  2. Configure GCP Workload Identity with that OIDC provider
  3. Deploy a Cloud Run application which requires Authentication.
  4. Use Workload Federation and IAM API to exchange the ambient OIDC token from step 1 for a Google-issued OIDC token
  5. Use google id_token from step 4 to access the secure Cloud Run application.

A brief background:

This article combines both where you can use your ambient workload credentials to authenticate to Cloud Run.

  • Why is this different than plain plain Workload Federation?

    Well, the token returned by GCP for workload federation is an oauth2 access_token intended to be used with GCP services

    The token we actually need to access cloud run is an id_token

  • So how do we exchange an access_token for an id_token?

    Its a bit complicated by we need to use the access_token and invoke projects.serviceAccounts.generateAccessToken endpoint.

    That IAM endpoint will generate a google-issued id_token with the user-specified audience that matches the Cloud Run service.


Other usecases

This tutorial runs through setting a fake OIDC server just used for testing...the OIDC token issued by this server is simply used for use with workload federation; it cannot be used for authentication to Cloud Run. To authenticate to Cloud Run we need a google-issued id_token

  • gRPC: If what your ultimately interested in is an id_token for gRPC, follow the step to get an id_token and then supply that to

  • SignedURL If what you really want to use do is issue GCS Signed URLs using workload identity, you need to invoke projects.serviceAccounts.signBlob using the correct payload

  • Domain-wide Delegation: If what want to do is issue a domain-wide delegated credentials (which IMO should be really rare), use projects.serviceAccounts.signJwt with the JWT payload and sub field for the new identity.

For more info see Using Federated Tokens to sign signJWT or get gcp idtokens


Setup

As mentioned, there are several preliminary steps involved here which are numbered accordingly.

You will need a GCP project and access to deploy to cloud run (ofcourse)

export PROJECT_ID=`gcloud config get-value core/project`
export PROJECT_NUMBER=`gcloud projects describe $PROJECT_ID --format='value(projectNumber)'`

## Create service account that the google_issued id_token will use
gcloud iam service-accounts create oidc-federated

1. Fake OIDC server

The following will build and deploy the fake OIDC server and allow the service account associated with the federated identity to access the service

cd idp_server/

gcloud run deploy   --platform=managed  \
 --region=us-central1   --allow-unauthenticated  \
 --source .   idp-on-cloud-run

The fake oidc server's

  • /token endpoint will sign whatever well-formed JSON file is sent via POST

  • .well-known/openid-configuration endpoint will print out the standard oidc configuration

  • /certs will return the JWK formatted public key used for JWT verification

/tmp/oidccred.txt">
gcloud run services describe idp-on-cloud-run --format="value(status.url)"

# export some environment variables
export URL=`gcloud run services describe idp-on-cloud-run --format="value(status.url)"`
export IAT=`date -u +%s`
export EXP=`date -u +%s -d "+3600 seconds"`
export EMAIL="[email protected]"
export SUB="[email protected]"
export ISS=$URL
export NAME="alice"
export WF_AUD="https://iam.googleapis.com/projects/$PROJECT_NUMBER/locations/global/workloadIdentityPools/oidc-pool-run/providers/oidc-provider-1"

## print a sample fake id_token 

curl -s -X POST -d "{  \"name\":\"$NAME\",  \"isadmin\":\"true\", \"mygroups\": [ \"group1\",\"group2\"], \"iss\":\"$ISS\", \"aud\":\"$WF_AUD\",  \"sub\":\"$SUB\", \"iat\":$IAT, \"exp\":$EXP,  \"email\":\"$EMAIL\",  \"email_verified\":true }"  $URL/token  > /tmp/oidccred.txt

You can view the contents of the JWT by decoding /tmp/oidccred.txt using jwt.io debugger

A sample JWT may look like

{
  "alg": "RS256",
  "kid": "123456",
  "typ": "JWT"
}
{
  "aud": "https://iam.googleapis.com/projects/1071284184436/locations/global/workloadIdentityPools/oidc-pool-run/providers/oidc-provider-1",
  "email": "[email protected]",
  "email_verified": true,
  "exp": 1644598160,
  "iat": 1644594560,
  "isadmin": "true",
  "iss": "https://idp-on-cloud-run-6w42z6vi3q-uc.a.run.app",
  "mygroups": [
    "group1",
    "group2"
  ],
  "name": "alice",
  "sub": "[email protected]"
}

2. Configure Workload Identity

Now configure workload identity to use the fake oidc server's JWT's

gcloud iam workload-identity-pools create oidc-pool-run  \
   --location="global" \
   --description="OIDC Pool"  \
   --display-name="OIDC Pool" \
   --project $PROJECT_ID


gcloud iam workload-identity-pools providers create-oidc oidc-provider-1  \
     --workload-identity-pool="oidc-pool-run"     --issuer-uri="$ISS"   \
      --location="global"  \
      --attribute-mapping="google.subject=assertion.sub,attribute.isadmin=assertion.isadmin,attribute.aud=assertion.aud" \
      --attribute-condition="attribute.isadmin=='true'" \
      --project $PROJECT_ID

# write the GOOGLE_APPLICATION_CREDENTIAL file to /tmp/sts.creds
gcloud iam workload-identity-pools create-cred-config \
     projects/$PROJECT_NUMBER/locations/global/workloadIdentityPools/oidc-pool-run/providers/oidc-provider-1  \
     --output-file=/tmp/sts-creds.json  \
     --credential-source-file=/tmp/oidccred.txt


## Associate the federated identity (ali[email protected]) the permission to impersonate the service account
gcloud iam service-accounts add-iam-policy-binding oidc-federated@$PROJECT_ID.iam.gserviceaccount.com \
    --role roles/iam.workloadIdentityUser \
    --member "principal://iam.googleapis.com/projects/$PROJECT_NUMBER/locations/global/workloadIdentityPools/oidc-pool-run/subject/[email protected]"

Note that the /tmp/sts-creds.json file does NOT specify a service account since IAMCredentials API support direct federation. Also note that were instructing the credential to find the ambient credential set at /tmp/oidccred.txt

{
  "type": "external_account",
  "audience": "//iam.googleapis.com/projects/1071284184436/locations/global/workloadIdentityPools/oidc-pool-run/providers/oidc-provider-1",
  "subject_token_type": "urn:ietf:params:oauth:token-type:jwt",
  "token_url": "https://sts.googleapis.com/v1/token",
  "credential_source": {
    "file": "/tmp/oidccred.txt"
  }
}

If you're on the cloud console, your configuration should look like

images/provider_details.png

3. Deploy secure Cloud Run application

Now deploy an application that is secure. This is the app we want to access using the google id_token

cd server

gcloud run deploy   --platform=managed \
   --region=us-central1  \
   --no-allow-unauthenticated \
   --source .   federated-auth-cloud-run

export TEST_URL=`gcloud run services describe federated-auth-cloud-run --format="value(status.url)"`

# verify that you can't access the service
curl -s $TEST_URL

# allow the service account we will eventually use for access to the cloud run service
gcloud run services add-iam-policy-binding federated-auth-cloud-run \
  --member="serviceAccount:oidc-federated@$PROJECT_ID.iam.gserviceaccount.com" \
  --role="roles/run.invoker"

4. Use Workload Federation and IAM API to create a google id_token

GCP Auth libraries automatically 'understand' the specific external identity provided by federation.

For us, export the variable

export GOOGLE_APPLICATION_CREDENTIALS=/tmp/sts-creds.json 

Then when application default is used to call generateIdToken()....well,

see the flow described here

5. Use google id_token to access cloud_run

Now that we have a Google-issued id_token, use that to access Cloud Run

The full flow in python is like this"

#!/usr/bin/python
from google.auth import credentials
from google.cloud import  iam_credentials_v1

import google.auth
import google.oauth2.credentials

from google.auth.transport.requests import AuthorizedSession, Request

url = "https://federated-auth-cloud-run-6w42z6vi3q-uc.a.run.app/dump"
aud = "https://federated-auth-cloud-run-6w42z6vi3q-uc.a.run.app"
service_account = '[email protected]'

client = iam_credentials_v1.services.iam_credentials.IAMCredentialsClient()

name = "projects/-/serviceAccounts/{}".format(service_account)
id_token = client.generate_id_token(name=name,audience=aud, include_email=True)

print(id_token.token)

creds = google.oauth2.credentials.Credentials(id_token.token)
authed_session = AuthorizedSession(creds)
r = authed_session.get(url)
print(r.status_code)
print(r.text)

Test Clients

This repo woudn't be a repo without samples, see the clients/ folder for a language of your choice.

Note that for each, you must edit the source file and specify the url audience and service account you used.

Also remember to set export GOOGLE_APPLICATION_CREDENTIALS=/tmp/sts-creds.json

You might also like...
a Framework for creating mesh networks using technologies and design patterns of Erlang/OTP in Golang
a Framework for creating mesh networks using technologies and design patterns of Erlang/OTP in Golang

Ergo Framework Implementation of Erlang/OTP in Golang. Up to x5 times faster than original Erlang/OTP. The easiest drop-in replacement for your hot no

Golang Mongodb Jwt Auth Example Using Echo
Golang Mongodb Jwt Auth Example Using Echo

Golang Mongodb Jwt Auth Example Using Echo Golang Mongodb Rest Api Example Using Echo Prerequisites Golang 1.16.x Docker 19.03+ Docker Compose 1.25+ I

Scaffold to help building Terraform Providers using AWS IAM authentication.

Terraform Provider Scaffolding This repository is a template for a Terraform provider. It is intended as a starting point for creating Terraform provi

A demo using go and redis to implement a token manager

使用go-redis实现一个令牌管理器 需求描述 假设我们当前的所有服务需要一个第三方的认证,认证形式为:在发送请求的时候带上第三方颁发的令牌,该令牌具有一个时效性 第三方的令牌可以通过某个接口获取,但是该接口做了单位时间内的同一ip的请求频率的限制,因此在并发的场景下,我们需要控制令牌获取接口的频

telegram authorization in telegram without using a widget

TGAH - telegram Authorization Example of authorization in telegram without using a widget Installation go get -d github.com/tioffs/[email protected] Setti

Create the Provider for Zoom API and automate the creation of zoom user using terraform.

Create the Provider for Zoom API and automate the creation of zoom user using terraform.

auth0 is a package helping to authenticate using the Auth0 service.

auth0 auth0 is a package helping to authenticate using the Auth0 service. Installation go get github.com/auth0-community/go-auth0 Client Credentials

A demo of authentication and authorization using jwt
A demo of authentication and authorization using jwt

Nogopy Hi, this a demo of how to use jwt for authentication in microservices Keep in mind that this is a demo of how to authenticate using jwt, we don

Go module that allows you to authenticate to Azure with a well known client ID using interactive logon and grab the token

azureimposter Go module that pretends to be any clientID and grabs an authentication token from Azure using interactive login (w/mfa if enabled) and r

Owner
null
Identity-service - An OAuth2 identity provider that operates over gRPC

Identity-service - An OAuth2 identity provider that operates over gRPC

Otter Social 2 May 2, 2022
Identity - An OAuth2 identity provider that operates over gRPC

Otter Social > Identity Provider An OAuth2 identity provider that operates over

Otter Social 2 May 2, 2022
ZITADEL - Identity Experience Platform

What Is ZITADEL ZITADEL is a "Cloud Native Identity and Access Management" solution built for the cloud era. ZITADEL uses a modern software stack cons

CAOS 2k Jan 1, 2023
It is a JWT based implement of identity server.

JWTAuth 安裝說明 基本需求 安裝 docker 服務 安裝 OpenSSL 安裝指令 建立 OS 系統的 jwtauth 帳號 sudo useradd -m jwtauth 給予 JWTAuth 帳號可以操作 docker 的權限 sudo usermod -aG docker jwtau

null 1 Aug 10, 2022
Demonstration of sharing secret data between an OAuth/OIDC client and an Identity Providers web client.

OAuth / OIDC Cubbyhole Share secret data between client applications. This is mostly a demonstration of some of the work I've been evaluating at Storj

mya 3 Mar 21, 2022
Run multiple auth functions by relation

Relation Run multiple auth functions by relation. Signatures func New(relation string, conditions ...func(c *fiber.Ctx) bool) fiber.Handler Import imp

Eren BALCI 4 Oct 31, 2021
Cookie - Cookie helper functions for golang

Cookie Cookie helper functions. package main import ( "net/http" "github.co

infinite loop 0 Feb 10, 2022
Cocos2d-x texture unpacker, primarily for Cookie Run.

boofunpack Cocos2d-x texture unpacker, primarily for Cookie Run: OvenBreak and Cookie Run for Kakao/LINE (though it likely works for other .plist form

null 3 Oct 11, 2022
An authentication proxy for Google Cloud managed databases

db-auth-gateway An authentication proxy for Google Cloud managed databases. Based on the ideas of cloudsql-proxy but intended to be run as a standalon

null 25 Dec 5, 2022
an SSO and OAuth / OIDC login solution for Nginx using the auth_request module

Vouch Proxy An SSO solution for Nginx using the auth_request module. Vouch Proxy can protect all of your websites at once. Vouch Proxy supports many O

Vouch 2.1k Jan 4, 2023