本页面介绍了如何使用签名的 IAP 标头保护应用的安全。配置 Identity-Aware Proxy (IAP) 后,该服务会使用 JSON Web 令牌 (JWT) 来确保向应用发出的请求已获得授权。这样可以保护您的应用远离以下风险:
- IAP 被意外停用
- 防火墙配置有误
- 来自项目内部的未经授权的访问
为帮助保护应用的安全,您必须对所有应用类型使用签名标头。
或者,如果您有 App Engine 标准环境应用,则可以使用 Users API。
Compute Engine 和 GKE 健康检查不包含 JWT 标头,而 IAP 不会处理健康检查。如果健康检查返回访问权限错误,请确保已在 Google Cloud 控制台中正确配置健康检查,并且确保 JWT 标头验证服务该健康检查路径。如需了解详情,请参阅创建健康检查例外。
准备工作
要使用签名标头保护应用的安全,您需要做好以下准备:
- 希望用户连接的应用。
- 支持
ES256算法的与您所用语言对应的第三方 JWT 库。
使用 IAP 标头保护应用的安全
为了使用 IAP JWT 保护您的应用,请验证 JWT 的标头、载荷和签名。JWT 在 HTTP 请求标头 x-goog-iap-jwt-assertion 中。如果攻击者绕过 IAP,他们便能够伪造没有签名的 IAP 身份标头 x-goog-authenticated-user-{email,id}。JWT 可提供一种更加安全的替代解决方案。
当有人绕过 IAP 时,签名标头可提供额外的安全保护。启用 IAP 后,IAP 会在请求通过 IAP 服务基础架构时删除客户端提供的 x-goog-* 标头。
验证 JWT 标头
验证 JWT 的标头是否符合以下规定:
| JWT 标头声明 | ||
|---|---|---|
alg |
算法 | ES256 |
kid |
密钥 ID | 必须与 IAP 密钥文件中列出的公钥之一相对应,并以两种不同的格式提供:https://www.gstatic.com/iap/verify/public_key 和 https://www.gstatic.com/iap/verify/public_key-jwk |
请确保 JWT 已由与令牌的 kid 声明相对应的私钥签名。首先,从以下任一位置检索公钥:
https://www.gstatic.com/iap/verify/public_key。该网址包含一个 JSON 字典,该字典将kid声明映射到公钥值。https://www.gstatic.com/iap/verify/public_key-jwk。该网址包含 JWK 格式的 IAP 公钥。
获取公钥后,请使用 JWT 库来验证签名。
IAP 会定期轮换其公钥。如需确保您始终可以验证 JWT,请参阅自动执行公钥缓存。
验证 JWT 载荷
验证 JWT 的载荷是否符合以下规定:
| JWT 负载声明 | ||
|---|---|---|
exp |
到期时间 | 必须是将来的时间。时间从 UNIX 计时原点开始计算,以秒为单位。允许 30 秒偏差。 令牌的最长生命周期为 10 分钟 + 2 * 偏差。 |
iat |
颁发时间 | 必须是过去的时间。时间从 UNIX 计时原点开始计算,以秒为单位。允许 30 秒偏差。 |
aud |
受众 |
必须是一个含有以下值的字符串:
|
iss |
颁发者 | 必须为 https://cloud.google.com/iap。
|
hd |
账号网域 | 如果账号属于一个托管网域,则会提供 hd 声明来区分与该账号关联的网域。 |
google |
Google 声明 |
如果一个或多个访问权限级别适用于请求,则这些级别的名称将以字符串数组形式存储在 google 声明 JSON 对象的 access_levels 键下。
指定设备政策且组织有权访问设备数据时, |
要获取上述 aud 字符串的值,您可以访问Google Cloud 控制台,也可以使用 gcloud 命令行工具。
如需通过 Google Cloud 控制台获取 aud 字符串值,请转到项目的 Identity-Aware Proxy 代理设置,点击负载平衡器资源旁边的更多,然后选择签名标头 JWT 目标设备。随即会出现签名标头 JWT 对话框,其中显示所选资源的 aud 声明。
如果您想使用 gcloud CLI gcloud 命令行工具来获取 aud 字符串值,则需要知道项目 ID。您可以在 Google Cloud 控制台的项目信息卡片上找到项目 ID,然后为每个值运行指定的命令。
项目编号
要使用 gcloud 命令行工具获取项目编号,请运行以下命令:
gcloud projects describe PROJECT_ID
该命令返回如下输出:
createTime: '2016-10-13T16:44:28.170Z' lifecycleState: ACTIVE