您可以使用 gRPC 服务中的服务账号在服务之间实现身份验证。本页面将通过一个完整示例演示服务到服务的身份验证,其中包括如何在 gRPC 服务中配置 Extensible Service Proxy (ESP) 以支持经过身份验证的请求,以及如何从 gRPC 客户端调用该服务。
要使任何服务能够对 Cloud Endpoints API 进行经过身份验证的调用,调用服务必须具有服务账号,并且必须在调用中发送身份验证令牌。调用者必须使用 Google ID 令牌或仅由调用者的服务账号签名的自定义 JSON 网络令牌 (JWT)。ESP 将验证 JWT 中的 iss
声明是否与服务配置中的 issuer
设置匹配。ESP 不会检查已授予服务账号的 Identity and Access Management 权限。
在我们的示例中,您将设置和使用最简单的服务到服务身份验证形式,其中客户端使用其 Google Cloud 服务账号生成执行身份验证的 JWT。对于其他身份验证方法而言,方案是类似的,但用于获取有效身份验证令牌的客户端进程取决于使用的身份验证方法。
准备工作
本指南使用的是教程中提供的 Bookstore 示例。
克隆用于托管 gRPC 示例代码的 Git 代码库:
git clone https://github.com/GoogleCloudPlatform/python-docs-samples.git
切换您的工作目录:
cd python-docs-samples/endpoints/bookstore-grpc/
如果您还没有项目,请按照教程中的说明设置一个。
在该示例中,请使用部署到 Google Kubernetes Engine,尽管对于 Compute Engine 而言,身份验证设置是相同的。
该示例中引用了两个 Google Cloud Platform 项目:
- 服务提供方项目,即拥有适用于 gRPC 的 Cloud Endpoints 服务的项目。
- 服务使用方项目,即拥有 gRPC 客户端的项目。
创建使用方服务账号和密钥
要为使用方项目创建服务账号和密钥,请执行以下操作:
- 在 Google Cloud 控制台中,转到“API 和服务”。确保您位于使用方项目中。
- 在凭据页面上的创建凭据下拉列表中,选择服务账号密钥。
如果要使用的服务账号已存在,请在创建服务账号密钥页面上选择该账号。如果该账号不存在,则在服务账号下拉列表中选择新建服务账号,然后输入账号名称。
系统将为您创建相应的服务账号 ID。请记下该 ID,因为您在后面部分中需要用到该信息。例如:
service-account-name@YOUR_PROJECT_ID.iam.gserviceaccount.com
点击角色下拉列表,然后选择以下角色:
- 服务账号 > 服务账号用户
- 服务账号 > 服务账号令牌创建者
务必选中 JSON 密钥类型。
点击创建。您的服务账号 JSON 密钥文件将下载到本地机器。请注意位置,并确保其安全存储,因为该文件稍后将用于生成令牌。
为服务配置身份验证
请在本部分的所有步骤中使用提供方项目。
在 gRPC API 配置中设置身份验证
ESP 的身份验证在 gRPC API 配置 YAML 文件的 authentication
部分中进行配置。对于该示例服务,包含身份验证的配置位于 api_config_auth.yaml
中。
providers
部分指定了要使用的身份验证提供方。在本例中,该部分指定您要将 Google 服务账号用作身份验证提供方。rules
部分指定您需要使用来自此提供方的令牌才能访问服务的所有方法。
在您自己通过克隆代码库而为此文件创建的副本中,执行以下操作:
- 将
MY_PROJECT_ID
更改为您的提供方项目 ID。 - 将
authentication
部分中的SERVICE-ACCOUNT-ID
(包含在issuer
和jwks_uri
值中)更改为您在上一部分中记录的使用方服务账号 ID。此操作会告知 ESP,您要向通过该特定服务账号提供有效令牌的用户授予对您服务的访问权限。 - (可选)在
providers
元素下添加jwt_locations
。您可以使用此值指定自定义 JWT 位置。默认 JWT 位置是Authorization
元数据(带有“Bearer”前缀)和X-Goog-Iap-Jwt-Assertion
元数据。
保存该文件以供在下一步中使用。
部署配置和服务
以下步骤与 GKE 上的 gRPC 使用入门中的步骤相同:
将服务配置部署到 Endpoints:即使您已在教程中执行过此操作,也需要这样做,因为这是不同的配置。请记下返回的服务名称:
gcloud endpoints services deploy api_descriptor.pb api_config_auth.yaml --project PRODUCER_PROJECT
创建容器集群并向该集群进行
kubectl
身份验证(如果您还没有执行此操作)。将示例 API 和 ESP 部署到集群。如果您使用的提供方项目和使用方项目不同,请首先确保您已在
gcloud
命令行工具中设置适当的项目:gcloud config set project PRODUCER_PROJECT
通过 gRPC 客户端调用经过身份验证的方法
最后,在客户端上,您可以使用服务账号密钥生成 JWT 令牌,然后使用该令牌调用经过身份验证的 Bookstore 方法。首先根据生成令牌和运行示例客户端所需的相应 Python 内容进行安装。确保您位于克隆客户端的 python-docs-samples/endpoints/bookstore-grpc
文件夹中,然后运行以下命令:
virtualenv bookstore-env
source bookstore-env/bin/activate
pip install -r requirements.txt
生成 JWT 令牌
在该示例中,Bookstore 使用服务到服务的身份验证,其中调用服务只需通过其服务账号进行身份验证,因此您可以轻松地创建适当令牌,以随我们的请求一起发送。请注意,您还可以设定更严格的服务到服务身份验证要求,即生成的令牌必须通过 Google(使用 Google ID 令牌)进行进一步身份验证。
在本例中,提供的 Python 脚本可以根据先前下载的 JSON 密钥文件,使用虚拟用户 ID 和电子邮件生成令牌。
要使用脚本生成令牌,请执行以下操作:
生成 JWT 令牌并将其分配给变量
$JWT_TOKEN
:JWT_TOKEN=$(python jwt_token_gen.py \ --file=[SERVICE_ACCOUNT_FILE] \ --audiences=[SERVICE_NAME] \ --issuer=[SERVICE-ACCOUNT-ID])
其中:
[SERVICE_ACCOUNT_FILE]
是已下载的使用方服务账号 JSON 密钥文件。[SERVICE_NAME]
是您将更新后的服务配置部署到 Endpoints 时系统返回的 Bookstore 服务的名称。[SERVICE-ACCOUNT-ID]
是您在生成服务账号时获得的完整使用方服务账号 ID。
发起经过身份验证的 gRPC 调用
最后一步使用 bookstore_client.py
,它与教程中使用的客户端相同。为了发起经过身份验证的调用,客户端将 JWT 作为元数据与其方法调用一起传递。
要运行示例,请执行以下操作:
使用
kubectl get services
获取已部署 Bookstore 的外部 IP 地址:#kubectl get services NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE echo 10.11.246.240 104.196.186.92 80/TCP 10d endpoints 10.11.243.168 104.196.210.50 80/TCP,8090/TCP 10d esp-grpc-bookstore 10.11.254.34 104.196.60.37 80/TCP 1d kubernetes 10.11.240.1 <none> 443/TCP 10d
在本例中,服务为
esp-grpc-bookstore
,其外部 IP 为104.196.60.37
。将此 IP 地址分配给变量
EXTERNAL_IP
EXTERNAL_IP=104.196.60.37
列出 Bookstore 服务中的所有书架:
python bookstore_client.py --port=80 --host=$EXTERNAL_IP --auth_token=$JWT_TOKEN
该服务会返回当前 Bookstore 中的所有书架。要确认这一点,您可以不提供令牌或在生成 JWT 时指定错误的服务账号 ID。此时命令应失败。