GCP - 从 API Gateway 访问 Google Cloud Run 后端

dvr*_*ype 7 google-cloud-platform google-cloud-run google-cloud-api-gateway

在我的 GCP 项目中,我有一个在 docker 容器中运行的 python API(使用 connexion)。我想使用 API Gateway 公开 API(带有 API 密钥)。

\n

当我使用 部署 docker 容器时--ingress internal,我Access is forbidden.通过网关进行 API 调用。因此 API 网关无法访问 Google Run 容器。\n当我使用 时--ingress all,一切都按预期工作,但随后可以从网络访问我的内部 API,这不是我想要的。

\n

我为此创建了一个服务帐户:

\n
gcloud iam service-accounts create $SERVICE_ACCOUNT_ID \\\n#  --description="the api gateway user" \\\n#  --display-name="api gateway user"\n
Run Code Online (Sandbox Code Playgroud)\n

...授予帐户run.invoker权限:

\n
gcloud projects add-iam-policy-binding $PROJECT_ID \\\n  --role=roles/run.invoker --member \\\n  serviceAccount:$SERVICE_ACCOUNT_EMAIL\n
Run Code Online (Sandbox Code Playgroud)\n

...并使用服务帐户创建 API 配置:

\n
gcloud api-gateway api-configs create $CONFIG_ID \\\n  --api=$API_ID --openapi-spec=$API_DEFINITION \\\n  --project=$PROJECT_ID --backend-auth-service-account=$SERVICE_ACCOUNT_EMAIL\n
Run Code Online (Sandbox Code Playgroud)\n

但我无法从 API Gateway 访问 docker API。我在这里缺少什么?如何保护我的 API,以便 API Gateway 可以在内部进行连接。

\n

Update1:\n还将角色应用于我的运行服务:

\n
gcloud run services add-iam-policy-binding $SERVICE_ID \\\n  --region $REGION --member="serviceAccount:$SERVICE_ACCOUNT_EMAIL" \\\n  --role="roles/run.invoker"\n
Run Code Online (Sandbox Code Playgroud)\n

更新 2:\n约翰·汉利 (John Hanley) 要求的一些额外信息:

\n

我的网关 yml 如下所示:

\n
swagger: '2.0'\n\ninfo:\n  title: "title"\n  description: "description"\n  version: "0.1"\n\nschemes:\n- https\n\nx-google-backend:\n  address: <CLOUD_RUN_SERVICE_URL>\n\npaths:\n  /api:\n    post:\n      operationId: api\n      consumes:\n        - application/json\n      produces:\n        - application/json\n      security:\n        - api_key: []\n      parameters:\n        - in: body\n          name: request\n          description: request\n          required: true\n          schema:\n            $ref: '#/definitions/Request'\n      responses:\n        200:\n          description: "success"\n        400:\n          description: "bad data"\n        503:\n          description: "internal error"\n\ndefinitions:\n  Request:\n    properties:\n      parameter1:\n        type: string\n      parameter1:\n        type: string\n    required:  \n      - parameter1\n\nsecurityDefinitions:\n  api_key:\n    type: "apiKey"\n    name: "key"\n    in: "query"\n
Run Code Online (Sandbox Code Playgroud)\n
gcloud api-gateway api-configs describe api-config --api api-api\ncreateTime: '2021-06-12T15:02:27.382098034Z'\ndisplayName: api-config\ngatewayServiceAccount: projects/-/serviceAccounts/apigatewayuser@projectid.iam.gserviceaccount.com\nname: projects/722514052893/locations/global/apis/api-api/configs/api-config\nserviceConfigId: api-config-3hytlxf4gfvzj\nstate: ACTIVE\nupdateTime: '2021-06-12T15:05:09.778404414Z'\n
Run Code Online (Sandbox Code Playgroud)\n
gcloud api-gateway gateways describe api-gateway --location europe-west1\napiConfig: projects/722514052893/locations/global/apis/api-api/configs/api-config\ncreateTime: '2021-06-12T15:06:03.383002459Z'\ndefaultHostname: api-gateway-97x27n6l.ew.gateway.dev\ndisplayName: api-gateway\nname: projects/projectid/locations/europe-west1/gateways/api-gateway\nstate: ACTIVE\nupdateTime: '2021-06-12T15:07:37.590520122Z'\n
Run Code Online (Sandbox Code Playgroud)\n
gcloud run services describe api --region europe-west1\n\xe2\x9c\x94 Service api in region europe-west1\n \nURL:     https://api-o3rf5h4boa-ew.a.run.app\nIngress: internal\nTraffic:\n  100% LATEST (currently api-00010-lig)\n \nLast updated on 2021-06-12T17:42:49.913232Z by myemail@gmail.com:\n  Revision api-00010-lig\n  Image:         gcr.io/projectid/api\n  Port:          8080\n  Memory:        512Mi\n  CPU:           1000m\n  Concurrency:   80\n  Max Instances: 100\n  Timeout:       300s\n
Run Code Online (Sandbox Code Playgroud)\n

尝试直接在 Cloud Run 上调试:

\n
gcloud iam service-accounts keys create $KEY_FILE --iam-account=$SERVICE_ACCOUNT_EMAIL\ngcloud auth activate-service-account $SERVICE_ACCOUNT_EMAIL --key-file $KEY_FILE\nBEARER=$(gcloud auth print-identity-token $SERVICE_ACCOUNT_EMAIL)\n\n\ncurl --header "Content-Type: application/json" \\\n  --header "Authorization: bearer $BEARER" \\\n  --request POST \\\n  --data '{"parameter1":"somedata"}' \\\n  $SERVICE_URL/api\n
Run Code Online (Sandbox Code Playgroud)\n

结果仍然是Forbidden:

\n
<!DOCTYPE html>\n<html lang=en>\n  <meta charset=utf-8>\n  <meta name=viewport content="initial-scale=1, minimum-scale=1, width=device-width">\n  <title>Error 403 (Forbidden)!!1</title>\n  <style>\n    *{margin:0;padding:0}html,code{font:15px/22px arial,sans-serif}html{background:#fff;color:#222;padding:15px}body{margin:7% auto 0;max-width:390px;min-height:180px;padding:30px 0 15px}* > body{background:url(//www.google.com/images/errors/robot.png) 100% 5px no-repeat;padding-right:205px}p{margin:11px 0 22px;overflow:hidden}ins{color:#777;text-decoration:none}a img{border:0}@media screen and (max-width:772px){body{background:none;margin-top:0;max-width:none;padding-right:0}}#logo{background:url(//www.google.com/images/branding/googlelogo/1x/googlelogo_color_150x54dp.png) no-repeat;margin-left:-5px}@media only screen and (min-resolution:192dpi){#logo{background:url(//www.google.com/images/branding/googlelogo/2x/googlelogo_color_150x54dp.png) no-repeat 0% 0%/100% 100%;-moz-border-image:url(//www.google.com/images/branding/googlelogo/2x/googlelogo_color_150x54dp.png) 0}}@media only screen and (-webkit-min-device-pixel-ratio:2){#logo{background:url(//www.google.com/images/branding/googlelogo/2x/googlelogo_color_150x54dp.png) no-repeat;-webkit-background-size:100% 100%}}#logo{display:inline-block;height:54px;width:150px}\n  </style>\n  <a href=//www.google.com/><span id=logo aria-label=Google></span></a>\n  <p><b>403.</b> <ins>That\xe2\x80\x99s an error.</ins>\n  <p>Access is forbidden.  <ins>That\xe2\x80\x99s all we know.</ins>\n
Run Code Online (Sandbox Code Playgroud)\n

因此,问题在于服务帐户无法访问 Cloud Run 应用程序。我不确定为什么这不起作用,因为该run.invoker角色已添加到运行服务中。

\n

gui*_*ere 14

Ingress 内部意味着“仅接受来自项目 VPC 或 VPC SC 外围的请求”。

当您使用 API Gateway 时,您不在 VPC 中,它是无服务器的,而是在 Google Cloud 托管的 VPC 中。因此,您的查询被禁止。

由于 API Gateway 无法插入 VPC 连接器(目前),因此无法将请求路由到您的 VPC,因此您无法使用此 ingress=internal 模式。


因此,解决方案是为所有人设置一个入口,这不是您只授权合法帐户访问它的问题。

为此,请检查 Cloud Run 服务中是否有所有用户在您的项目中被授予了 Roles/run.invoker。

  • 如果是,请将其删除

然后,创建一个服务帐户并为其授予 Cloud Run 服务上的 Roles/run.invoker。

遵循此文档

  • 步骤 4:更新 OpenAPI 规范文件中的 x-google-backend,以便在调用 Cloud Run 时添加正确的身份验证受众(这是基本服务 URL)
  • 第五步:创建带有后端服务帐号的网关;设置您之前创建的服务帐户

最后,只有经过身份验证和授权的帐户才能访问您的 Cloud Run 服务

所有未经授权的访问都会被 Google 前端过滤并在到达您的服务之前被丢弃。因此,您的服务不会被无偿调用,因此您无需支付任何费用!

只有 API Gateway(以及您在 Cloud Run 服务上允许的潜在其他账户)可以调用 Cloud Run 服务。

所以,好吧,您的 URL 是公开的,可以从野外互联网访问,但受到 Google 前端和 IAM 的保护。