{"id":21354864,"url":"https://github.com/salrashid123/cloud_run_grpc_auth","last_synced_at":"2025-07-12T22:32:20.222Z","repository":{"id":91309790,"uuid":"219848975","full_name":"salrashid123/cloud_run_grpc_auth","owner":"salrashid123","description":"Cloud Run authentication with gRPC","archived":false,"fork":false,"pushed_at":"2024-07-23T08:50:37.000Z","size":169,"stargazers_count":4,"open_issues_count":0,"forks_count":0,"subscribers_count":3,"default_branch":"master","last_synced_at":"2024-07-30T17:41:39.784Z","etag":null,"topics":["authentication","cloud-run","golang","google-cloud-platform","grpc","oidc"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/salrashid123.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-11-05T20:57:03.000Z","updated_at":"2024-07-23T08:50:41.000Z","dependencies_parsed_at":null,"dependency_job_id":"5a05c25a-267d-4019-8b67-178b8b03fa77","html_url":"https://github.com/salrashid123/cloud_run_grpc_auth","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/salrashid123%2Fcloud_run_grpc_auth","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/salrashid123%2Fcloud_run_grpc_auth/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/salrashid123%2Fcloud_run_grpc_auth/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/salrashid123%2Fcloud_run_grpc_auth/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/salrashid123","download_url":"https://codeload.github.com/salrashid123/cloud_run_grpc_auth/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":225839601,"owners_count":17532308,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["authentication","cloud-run","golang","google-cloud-platform","grpc","oidc"],"created_at":"2024-11-22T04:14:46.940Z","updated_at":"2024-11-22T04:14:47.605Z","avatar_url":"https://github.com/salrashid123.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"\n# gRPC Authentication with Cloud Run\n\nA couple months back I was happy to assist the [Cloud Run](https://cloud.google.com/run/) (managed) team in validating gRPC support on that platform.  The testing/validation covered writing a simple deployable gRPC client and server that also performed OpenIDConnect (OIDC) Authentication over gRPC (i.,e. Cloud Run Authentication).   In the course of developing that, i gained an understanding of how gRPC authentication headers are handled and manged directly with gRPC.   This article explains how to connect to a secure gRPC service running on Cloud Run using native gRPC library constructs.\n\nThe links cited in the Reference section discusses gRPC on Cloud Run but these do not cover either authentication at all or do not specify authentication using gRPC-centric constructs with Google Cloud Auth client libraries.\n\nThis article covers a simple client-server you can deploy on Cloud run that includes gRPC authentication _using google cloud credentials_ .   We specifically use `ServiceAccount Credentials` but the library cited below will work while running on GCE, GKE or even on Cloud RUn itself.\n\n![images/icon.png](images/icon.png)\n\n---\n\n### OIDC Basics for GCP Services and gRPC\n\nThis article does not go into details about OpenID Connect tokens and how to use them with gRPC and GCP.  As background please see\n\n- [https://github.com/salrashid123/grpc_google_id_tokens](https://github.com/salrashid123/grpc_google_id_tokens)\n- [Authenticating using Google OpenID Connect Tokens](https://medium.com/google-cloud/authenticating-using-google-openid-connect-tokens-e7675051213b)\n- [\"google.golang.org/api/idtoken\"](https://pkg.go.dev/google.golang.org/api@v0.23.0/idtoken)  \u003c\u003c use this!\n\nYou can inject a TokenSource into a grpc call by aupplyinng it into `grpc.WithPerRPCCredentials()`, thats it:\n\n```golang\nimport \"google.golang.org/api/idtoken\"\n...\n...\n\tidTokenSource, err := idtoken.NewTokenSource(ctx, targetAudience, idtoken.WithCredentialsFile(serviceAccount))\n\n\ttok, err := idTokenSource.Token()\n\n    ce := credentials.NewTLS(\u0026tlsCfg)\n\t\tconn, err = grpc.Dial(*address,\n\t\t\tgrpc.WithTransportCredentials(ce),\n\t\t\tgrpc.WithPerRPCCredentials(\n\t\t\t\toauth.TokenSource{\n\t\t\t\t\tidTokenSource,\n\t\t\t\t}),\n\t\t)\n```\n\n\u003e For equivalent samples in other languages see [gRPC Authentication with Google OpenID Connect tokens](https://github.com/salrashid123/grpc_google_id_tokens).\n\nAnyway, lets go directly into the details on deploying to cloud run\n\nI'm assuming you have Cloud Run setup and relatively above with gRPC and the auth concepts cited above\n\n\n#### Setup Env Vars \n\n```bash\n    export PROJECT_ID=`gcloud config get-value core/project`\n    gcloud config set run/region us-central1\n    gcloud config set run/platform managed\n```\n\n#### Build and deploy gRPC Server Image\n\nThe fofllowing assume you an cloud run can access artifact registry `us-central1-docker.pkg.dev/$PROJECT_ID/repo1/`\n```bash\n    docker build -t us-central1-docker.pkg.dev/$PROJECT_ID/repo1/grpc_run_serve -f Dockerfile.server .\n    \n    docker push us-central1-docker.pkg.dev/$PROJECT_ID/repo1/grpc_run_serve \n    gcloud run deploy grpc --image us-central1-docker.pkg.dev/$PROJECT_ID/repo1/grpc_run_serve  --no-allow-unauthenticated\n```\n\n#### Create Client SA\n\nNow create the service account that will have access to invoke the Cloud Run service\n\n```bash\n    mkdir -p certs\n    gcloud iam service-accounts create grpc-client-account --display-name \"gRPC Client Service Account\"\n    gcloud iam service-accounts keys create certs/grpc_client.json --iam-account=grpc-client-account@$PROJECT_ID.iam.gserviceaccount.com\n```\n\n#### Set IAM Permission for `roles/run.invoker`:\n\n```bash\ncat \u003c\u003cEOT \u003e\u003e iam_policy.json\nbindings:\n- members:\n  - serviceAccount:grpc-client-account@$PROJECT_ID.iam.gserviceaccount.com\n  role: roles/run.invoker\nversion: 1\nEOT\n\ngcloud run services set-iam-policy grpc iam_policy.json \n```\n\n## Build Client\n\nAt this point, the gRPC service is secure by default and would require an OIDC token with the correct `audience` field and IAM permissions to get through\n\nThe audience filed for cloud run needs to be the fully qualified name with the protocol (custom domain aud fields is currently not supported)\n\n```bash\n    export AUDIENCE=`gcloud run services describe grpc --format=\"value(status.url)\"`\n    export ADDRESS=`echo $AUDIENCE |  awk -F[/:] '{print $4}'`\n    echo $AUDIENCE\n    echo $ADDRESS\n```\n\n\n## RUN gRPC Client\n\nNow run the grpc client and specify the serviceAccount json file that is mounted inside the container (note: you should cd to the root of this repo so that the path to `certs/` is mounted):\n\n\n``bash\ngo run src/grpc_client.go \\\n  --address $ADDRESS:443 --usetls=true  \\\n  --servername $ADDRESS --audience $AUDIENCE \\\n  --serviceAccount certs/grpc_client.json\n```\n\nThe output of `grpc_run_client` will show the OIDC token sent to the cloud run instance which you can decode at [jwt.io](jwt.io).  Note the `aud:`, `email` and `iss` fields \n\n```json\n{\n  \"iss\": \"https://accounts.google.com\",\n  \"aud\": \"https://grpc-6w42z6vi3q-uc.a.run.app\",\n  \"azp\": \"grpc-client-account@mineral-minutia-820.iam.gserviceaccount.com\",\n  \"sub\": \"101659512549165144150\",\n  \"email\": \"grpc-client-account@mineral-minutia-820.iam.gserviceaccount.com\",\n  \"email_verified\": true,\n  \"iat\": 1572983749,\n  \"exp\": 1572987349\n}\n```\n\nThe second portion is 5 unary responses back from the GRPC service that displays the `K_REVISION` env variable from Cloud RUn\n\n```log\n2019/11/05 20:52:14 RPC Response: 0 message:\"Hello unary RPC msg   from K_REVISION grpc-tnslx\" \n2019/11/05 20:52:15 RPC Response: 1 message:\"Hello unary RPC msg   from K_REVISION grpc-tnslx\" \n2019/11/05 20:52:16 RPC Response: 2 message:\"Hello unary RPC msg   from K_REVISION grpc-tnslx\" \n2019/11/05 20:52:17 RPC Response: 3 message:\"Hello unary RPC msg   from K_REVISION grpc-tnslx\" \n2019/11/05 20:52:18 RPC Response: 4 message:\"Hello unary RPC msg   from K_REVISION grpc-tnslx\" \n```\n\nThe final output is a buffered form Server-side Streaming messages back (i.,e the server sends back two responses back on the single request).\nAt the time of writing `11/5/19`, server streaming is _not_ officially supported as its not true streaming but a buffered response anyway \n\n```log\n2019/11/05 20:52:18 Stream Header: %!(EXTRA metadata.MD=map[alt-svc:[quic=\":443\"; ma=2592000; v=\"46,43\",h3-Q049=\":443\"; ma=2592000,h3-Q048=\":443\"; ma=2592000,h3-Q046=\":443\"; ma=2592000,h3-Q043=\":443\"; ma=2592000] content-type:[application/grpc] streamheaderkey:[val] x-cloud-trace-context:[7928b8ab5aa6b2dc759ca6ff7fa5bb4c] date:[Tue, 05 Nov 2019 20:52:19 GMT] server:[Google Frontend] content-length:[52]])\n\n2019/11/05 20:52:18 Message: %!(EXTRA string=Msg1 Stream RPC msg)\n\n2019/11/05 20:52:18 Stream Header: %!(EXTRA metadata.MD=map[date:[Tue, 05 Nov 2019 20:52:19 GMT] server:[Google Frontend] content-length:[52] alt-svc:[quic=\":443\"; ma=2592000; v=\"46,43\",h3-Q049=\":443\"; ma=2592000,h3-Q048=\":443\"; ma=2592000,h3-Q046=\":443\"; ma=2592000,h3-Q043=\":443\"; ma=2592000] content-type:[application/grpc] streamheaderkey:[val] x-cloud-trace-context:[7928b8ab5aa6b2dc759ca6ff7fa5bb4c]])\n\n2019/11/05 20:52:18 Message: %!(EXTRA string=Msg2 Stream RPC msg)\n\n2019/11/05 20:52:18 Stream Trailer:  map[]\n```\n\n\n\nenjoy grpc-ing!\n\n\n### References\n- Cloud Run\n  - [Serverless gRPC with Cloud Run](https://medium.com/@petomalina/%EF%B8%8Fserverless-grpc-with-cloud-run-bab3622a47da)\n  - [gRPC Authentication on Cloud Run](https://ahmet.im/blog/grpc-auth-cloud-run/)\n\n- Misc\n  - [Calling Cloud Composer to Cloud Functions and back again, securely](https://medium.com/google-cloud/calling-cloud-composer-to-cloud-functions-and-back-again-securely-8e65d783acce)\n  - [Automatic OIDC: Using Cloud Scheduler, Tasks, and PubSub to make authenticated calls to Cloud Run, Cloud Functions or your Server](https://medium.com/google-cloud/automatic-oidc-using-cloud-scheduler-tasks-and-pubsub-to-make-authenticated-calls-to-cloud-run-de9e7e9cec3f)\n\n  - [Authorizing access to Cloud Run for Anthos deployed on GKE services using Istio](https://cloud.google.com/solutions/authorizing-access-to-cloud-run-on-gke-services-using-istio)\n  - [Authenticating end users of Cloud Run for Anthos deployed on GKE services using Istio and Identity Platform](https://cloud.google.com/solutions/authenticating-cloud-run-on-gke-end-users-using-istio-and-identity-platform)\n\n### Appendix\n\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsalrashid123%2Fcloud_run_grpc_auth","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsalrashid123%2Fcloud_run_grpc_auth","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsalrashid123%2Fcloud_run_grpc_auth/lists"}