Pubsub 签署 JWT 令牌以使用错误的密钥进行推送

Raz*_*ung 0 jwt google-cloud-platform google-cloud-pubsub google-cloud-endpoints-v2 google-cloud-run

我正在为我的后端使用以下堆栈:

  1. 云端点
  2. 带有 ESPv2 的 Cloud Run Gateway => 检查 API 密钥并验证 JWT
  3. Cloud Run gRPC 服务器实现
  4. 当兴趣发生变化时,我会在 pubsub 上发布一条消息

现在,附加到该 pubsub 主题,我有一个推送订阅,它使用服务帐户和指定的受众触发 Cloud Run 方法。

设置: 在此处输入图片说明

现在,我需要配置 Cloud Run Gateway 以验证 pubsub 为指定服务帐户生成的 JWT。这是api_config.yaml按照此处的文档完成的:https : //cloud.google.com/pubsub/docs/push#jwt_format

发行者https://accounts.google.com和我在 pubsub 订阅中指定的受众。

authentication:
  providers:
    - id: gcloud
      jwks_uri: https://www.googleapis.com/robot/v1/metadata/x509/875517523825-compute@developer.gserviceaccount.com
      issuer: https://accounts.google.com
      audiences: project.clounrun.admin
  rules:
    - selector: project.v2.Events.*
      requirements:
        - provider_id: gcloud
Run Code Online (Sandbox Code Playgroud)

可以在此处找到此服务帐户的 jwks: https://www.googleapis.com/robot/v1/metadata/x509/SERVICE-ACCOUNT-ID

就我而言: https://www.googleapis.com/robot/v1/metadata/x509/875517523825-compute@developer.gserviceaccount.com

https://cloud.google.com/endpoints/docs/grpc/service-account-authentication#set_up_authentication_in_the_grpc_api_configuration

我已经激活了 ESPv2 的调试日志,这是我在尝试验证 JWT 时得到的信息:

13:07:37.027 request headers complete (end_stream=false):\n\':authority\', \'project-gateway-v2-dev-cuvfttrlpq-de.a.run.app\'\n\':path\', \'/v2/sessions:event\'\n\':method\', \'POST\'\n\'content-type\', \'application/json\'\n\'authorization\', \'Bearer eyJhbGciOiJSUzI1NiIsImtpZCI6ImQwNWVmMjBjNDUxOTFlZmY2NGIyNWQzODBkNDZmZGU1NWFjMjI5ZDEiLCJ0eXAiOiJKV1QifQ.eyJhdWQiOiJ5aXRub3cuY2xvdW5ydW4uYWRtaW4iLCJhenAiOiIxMDk0NDIwMDAxNjU1ODQ3Nzc4MDciLCJlbWFpbCI6Ijg3NTUxNzUyMzgyNS1jb21wdXRlQGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwiZW1haWxfdmVyaWZpZWQiOnRydWUsImV4cCI6MTYwMzgwNzAwMSwiaWF0IjoxNjAzODAzNDAxLCJpc3MiOiJodHRwczovL2FjY291bnRzLmdvb2dsZS5jb20iLCJzdWIiOiIxMDk0NDIwMDAxNjU1ODQ3Nzc4MDcifQ.PwLvaBz-_dM3_5VjgzVlaueoRhacUE39FdFuVSfQI2w4V3OD79tIA6t_0cuvE1-kIpNrfDda5RSavVcs4SV4Y5P8AvW5jDtHdCELP3yb8HzVT9nCJlLac-v5ZKuv06syBN9F2Ve7VtZHHZOE2VS4B7uw0Q__1rIVzIllYWBYHkYGUBP2mZ3VhRw9VXARMr-EICanXfETe_MMfoKsX4202L_O4LffPdv16pA5hYtwzKi67gFYuubKI1XNkVQVatQieYQrhkz5jMyNyhVKy8ZY5a2UXagQL7erdsm-uPJo6ujoq0Yxtl8iKMdRv4XfrQSLyFZHCYdO6n2LHJle_FQzCQ\'\n\'content-length\', \'335\'\n\'accept\', \'application/json\'\n\'from\', \'noreply@google.com\'\n\'user-agent\', \'APIs-Google; (+https://developers.google.com/webmasters/APIs-Google.html)\'\n\'x-cloud-trace-context\', \'c3027b54c6aad09d85ce75f6dcaf07d5/8778433264575104852\'\n\'x-forwarded-for\', \'66.249.82.169\'\n\'x-forwarded-proto\', \'https\'\n\'forwarded\', \'for=\"66.249.82.169\";proto=https\'\n\'accept-encoding\', \'gzip,deflate,br\'
13:07:37.027 Called Filter : setDecoderFilterCallbacks
13:07:37.027 matched operation: project.v2.Events.OnSessionEvent
13:07:37.027 Called Filter : decodeHeaders
13:07:37.027 use filter state value project.v2.Events.OnSessionEvent to find verifier.
13:07:37.028 extract authorizationBearer
13:07:37.028 extract x-goog-iap-jwt-assertion
13:07:37.028 gcloud: JWT authentication starts (allow_failed=false), tokens size=1
13:07:37.028 gcloud: startVerify: tokens size 1
13:07:37.028 gcloud: Verifying JWT token of issuer https://accounts.google.com
13:07:37.028 gcloud: JWT token verification completed with: Jwks doesn\'t have key to match kid or alg from Jwt
13:07:37.028 Called Filter : check complete Jwks doesn\'t have key to match kid or alg from Jwt
13:07:37.028 Sending local reply with details jwt_authn_access_denied
Run Code Online (Sandbox Code Playgroud)

如您所见,jwks 不包含 JWT 孩子。这是真的。

这个 JWT 的标题是这样的:

13:07:37.027 request headers complete (end_stream=false):\n\':authority\', \'project-gateway-v2-dev-cuvfttrlpq-de.a.run.app\'\n\':path\', \'/v2/sessions:event\'\n\':method\', \'POST\'\n\'content-type\', \'application/json\'\n\'authorization\', \'Bearer eyJhbGciOiJSUzI1NiIsImtpZCI6ImQwNWVmMjBjNDUxOTFlZmY2NGIyNWQzODBkNDZmZGU1NWFjMjI5ZDEiLCJ0eXAiOiJKV1QifQ.eyJhdWQiOiJ5aXRub3cuY2xvdW5ydW4uYWRtaW4iLCJhenAiOiIxMDk0NDIwMDAxNjU1ODQ3Nzc4MDciLCJlbWFpbCI6Ijg3NTUxNzUyMzgyNS1jb21wdXRlQGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwiZW1haWxfdmVyaWZpZWQiOnRydWUsImV4cCI6MTYwMzgwNzAwMSwiaWF0IjoxNjAzODAzNDAxLCJpc3MiOiJodHRwczovL2FjY291bnRzLmdvb2dsZS5jb20iLCJzdWIiOiIxMDk0NDIwMDAxNjU1ODQ3Nzc4MDcifQ.PwLvaBz-_dM3_5VjgzVlaueoRhacUE39FdFuVSfQI2w4V3OD79tIA6t_0cuvE1-kIpNrfDda5RSavVcs4SV4Y5P8AvW5jDtHdCELP3yb8HzVT9nCJlLac-v5ZKuv06syBN9F2Ve7VtZHHZOE2VS4B7uw0Q__1rIVzIllYWBYHkYGUBP2mZ3VhRw9VXARMr-EICanXfETe_MMfoKsX4202L_O4LffPdv16pA5hYtwzKi67gFYuubKI1XNkVQVatQieYQrhkz5jMyNyhVKy8ZY5a2UXagQL7erdsm-uPJo6ujoq0Yxtl8iKMdRv4XfrQSLyFZHCYdO6n2LHJle_FQzCQ\'\n\'content-length\', \'335\'\n\'accept\', \'application/json\'\n\'from\', \'noreply@google.com\'\n\'user-agent\', \'APIs-Google; (+https://developers.google.com/webmasters/APIs-Google.html)\'\n\'x-cloud-trace-context\', \'c3027b54c6aad09d85ce75f6dcaf07d5/8778433264575104852\'\n\'x-forwarded-for\', \'66.249.82.169\'\n\'x-forwarded-proto\', \'https\'\n\'forwarded\', \'for=\"66.249.82.169\";proto=https\'\n\'accept-encoding\', \'gzip,deflate,br\'
13:07:37.027 Called Filter : setDecoderFilterCallbacks
13:07:37.027 matched operation: project.v2.Events.OnSessionEvent
13:07:37.027 Called Filter : decodeHeaders
13:07:37.027 use filter state value project.v2.Events.OnSessionEvent to find verifier.
13:07:37.028 extract authorizationBearer
13:07:37.028 extract x-goog-iap-jwt-assertion
13:07:37.028 gcloud: JWT authentication starts (allow_failed=false), tokens size=1
13:07:37.028 gcloud: startVerify: tokens size 1
13:07:37.028 gcloud: Verifying JWT token of issuer https://accounts.google.com
13:07:37.028 gcloud: JWT token verification completed with: Jwks doesn\'t have key to match kid or alg from Jwt
13:07:37.028 Called Filter : check complete Jwks doesn\'t have key to match kid or alg from Jwt
13:07:37.028 Sending local reply with details jwt_authn_access_denied
Run Code Online (Sandbox Code Playgroud)

有效载荷是这样的:

{
  "alg": "RS256",
  "kid": "d05ef20c45191eff64b25d380d46fde55ac229d1",
  "typ": "JWT"
}
Run Code Online (Sandbox Code Playgroud)

这表明 pubsub 确实使用了该服务帐户,但 jwks 响应中似乎缺少该特定孩子。

{
  "aud": "project.clounrun.admin",
  "azp": "109442000165584777807",
  "email": "875517523825-compute@developer.gserviceaccount.com",
  "email_verified": true,
  "exp": 1603807001,
  "iat": 1603803401,
  "iss": "https://accounts.google.com",
  "sub": "109442000165584777807"
}
Run Code Online (Sandbox Code Playgroud)

我们有:

  • 4366ae10d4a79728de14f6f89a628b4fe640140f
  • e0b3368c1646eb88d93b9d0b2d65e2d6fbae27b7
  • c0191d2d00f89eb1905886a04335a79a124885e1

但不是

  • d05ef20c45191eff64b25d380d46fde55ac229d1

如果 pubsub 使用不同的密钥,我在哪里可以找到 jwks?

更新:我验证了我所有的服务帐户 JWKS 链接,但没有一个包含那个孩子。所以这很奇怪。

Joh*_*ley 5

您正在使用 Google 签名密钥(Google 正在为您签名)。

这意味着您需要从 Google 发布的公钥中查找 KID。

你会在这里找到公共证书孩子:https : //www.googleapis.com/oauth2/v1/certs

对于一些附加的上下文,每个服务帐户都有一种“隐藏的”密钥。Google 管理和控制此密钥。当您从 Google 请求身份令牌时,JWT 使用此特殊密钥进行签名。这就是您需要查看此内容的原因在 Google 的公共证书列表中而不是您的服务帐户的证书列表中。