GCP API Gateway with gRPC
Simple gRPC client/server for GCP API Gateway and Cloud Run…now with with authentication and authorization!
Basically you deploy a gRPC server on Cloud Run, then an API gateway which brokers requests. The gateway is protected by JWT authentication while the Cloud Run backend will only allow requests originating from the gateway’s service account identity
client
-> (gRPC+auth)
-> APIGateway
-> (gRPC+auth)
-> Cloud Run API Server
You can find the source here
other references:
- gRPC Authentication with Cloud Run
- gRPC Authentication with Google OpenID Connect tokens
- Endpoints v2: Configuring a gRPC service
- Google API Gateway
Setup
Set environment variables
export PROJECT_ID=`gcloud config get-value core/project`
export PROJECT_NUMBER=`gcloud projects describe $PROJECT_ID --format='value(projectNumber)'`gcloud config set run/region us-central1
gcloud config set run/platform managed
Optionally recompile proto file:
/usr/local/bin/protoc -I src/ \
--include_imports --include_source_info \
--descriptor_set_out=src/echo/echo.proto.pb \
--go_out=plugins=grpc:src/ src/echo/echo.proto
Build and deploy backend API server
Build & push backend server image
Test direct access to backend.
Now create a service account that will act as the ‘client’ to the gateway
Deploy Gateway
In the following step, we will create a service account that will eventually be used the “Gateways” Service Account
gcloud iam service-accounts create gateway-sa \
--display-name "Service Account for API-Gateway" gcloud run services add-iam-policy-binding apiserver-grpc \
--region us-central1 --platform=managed \
--member=serviceAccount:gateway-sa@$PROJECT_ID.iam.gserviceaccount.com \
--role=roles/run.invoker
Now create the API
gcloud beta api-gateway apis create grpc-api-1gcloud beta api-gateway apis list
export MANAGED_SERVICE=`gcloud beta api-gateway apis describe grpc-api-1 --format="value(managedService)"`echo $MANAGED_SERVICE
echo $AUDIENCE
echo $ADDRESSgcloud endpoints configs list --service $MANAGED_SERVICE
Create the API.
(This step is manual using curl until gcloud cli is updated)
export API_ID=grpc-api-1
export API_CONFIG_ID=grpc-config-1
export SOURCE_FILE=api_config.yaml
export PROTO_FILE=src/echo/echo.proto.pb
echo $MANAGED_SERVICE
echo $AUDIENCE
echo $ADDRESS
envsubst < "api_config.yaml.tmpl" > "api_config.yaml"
gcloud beta api-gateway api-configs create $API_CONFIG_ID --api=grpc-api-1 \
--grpc-files=api_config.yaml,src/echo/echo.proto.pb \
--backend-auth-service-account=gateway-sa@$PROJECT_ID.iam.gserviceaccount.com
wait about a 3 or 4 mins until its ACTIVE
Create the gateway
gcloud beta api-gateway gateways create grpc-gateway-1 \
--location us-central-1 \
--api grpc-api-1 --api-config=grpc-config-1export GATEWAY_HOST=`gcloud beta api-gateway gateways describe grpc-gateway-1 --location us-central1 --format='value(defaultHostname)'`echo $GATEWAY_HOST
if you updated a config, you need to update the gateway to use it
gcloud alpha api-gateway gateways update grpc-gateway-1 \
--api=grpc-api-1 --api-config=grpc-config-2 \
--location=us-central1
Finally invoke the API Gateway using the client
go run src/grpc_client.go --address $GATEWAY_HOST:443 \
--audience=grpcs://grpc-gateway-1 \
--servername $GATEWAY_HOST \
--serviceAccount=api-client-sa.json
NOTE: the api gateway allows any Google Issued OIDC token through
For other options, see Authentication Rules (google.api.AuthProvider)
authentication:
providers:
- id: google_id_token
authorization_url: ''
audiences: 'grpcs://grpc-gateway-1'
issuer: 'https://accounts.google.com'
jwks_uri: 'https://www.googleapis.com/oauth2/v1/certs'
rules:
- selector: "*"
requirements:
- provider_id: google_id_token
You should also notice the responses come back from different instances over one gRPC channel to the gateway. That means the LB distributes each RPC to different Run backends.