Google Cloud Function 403 用于内部经过身份验证的请求
Google Cloud Function 403 for internal authenticated requests
我正在从我的 GCP 项目中调用云函数。
当功能配置为仅允许内部流量时,我收到 403(权限被拒绝),请参阅
https://cloud.google.com/functions/docs/networking/network-settings#ingress_settings
移除入口控制时没有问题,函数以状态 200 响应。
该函数 不允许 允许未经身份验证的访问,已配置 IAM 策略 。
效仿 https://cloud.google.com/functions/docs/securing/authenticating#function-to-function 中的示例:
# main.py
import requests
# TODO<developer>: set these values
# REGION = None
# PROJECT_ID = None
RECEIVING_FUNCTION = 'hello-get'
# Constants for setting up metadata server request
# See https://cloud.google.com/compute/docs/instances/verifying-instance-identity#request_signature
function_url = f'https://{REGION}-{PROJECT_ID}.cloudfunctions.net/{RECEIVING_FUNCTION}'
metadata_server_url = \
'http://metadata/computeMetadata/v1/instance/service-accounts/default/identity?audience='
token_full_url = metadata_server_url + function_url
token_headers = {'Metadata-Flavor': 'Google'}
def hello_trigger(request):
token_response = requests.get(token_full_url, headers=token_headers)
jwt = token_response.text
function_headers = {'Authorization': f'bearer {jwt}'}
function_response = requests.get(function_url, headers=function_headers)
function_response.raise_for_status()
return function_response.text
def hello_get(req):
return 'Hello there...'
使用所需的入口设置部署函数和触发函数:
gcloud functions deploy hello-get --trigger-http --entry-point hello_get --runtime python37 --ingress-settings internal-only
gcloud functions deploy hello-trigger --trigger-http --entry-point hello_trigger --runtime python37 --ingress-settings all --allow-unauthenticated
呼叫 hello-trigger
returns 403.
更改 hello-get
的入口解决了问题:
gcloud functions deploy hello-get --trigger-http --entry-point hello_get --runtime python37 --ingress-settings all
正在拨打 hello-trigger
returns 200.
用于 Cloud Functions 的服务帐户被赋予了此设置的 Functions Invoker 角色。
当您将入口流量设置为 internal-only 时,仅接受来自您的 VPC 或来自 VPC SC(服务控制)的流量。
在这里,在你的触发函数中,你不是来自你的 vpc,而是来自另一个(一个无服务器 VPC,由 Google 管理,部署云函数的地方)。因此,入口设置不受尊重,您会收到 403。
因此,为此您有 2 个解决方案:
- 仅使用 IAM 服务来过滤谁可以调用您的函数,并让“public”您的函数具有 ingress=all。 (约翰在他的第二条评论中提出的解决方案)。安全级别已经很高了。
但是,有时出于监管原因(或老式安全团队设计)网络控制是首选。
- 如果你想通过你的VPC,你需要
- 在与触发函数相同的区域创建一个serverless VPC connector
- Deploy your trigger function with this serverless VPC connector
- 设置egress traffic to all
--egress-settings=all
像这样,您的触发器函数的所有传出流量都将通过无服务器 VPC 连接器,因此,流量在尝试到达您的“ingress-internal”云函数之前先在您的 VPC 中路由。它将被接受。
如果您的函数使用 ingress=all 设置,任何人都可以通过互联网访问它。
但是,如果你不让功能 public 可以访问,我的意思是,授权给未经身份验证的用户,只有有效的请求(经过身份验证和授权角色 cloudfunctions.invoker) 将由您的 Cloud Functions
处理
事实上,任何 Google 服务名称 GFE: Google Front End 都有一个公共层。该层负责许多事情(在 HTTPS 中公开您的服务、管理您的证书、丢弃 DDoS 攻击 OSI 第 4 层,...),其中验证检查 header 和针对 IAM 服务的授权检查。
因此,如果在第 4 层发生 DDoS 攻击,GFE 默认会过滤这些攻击。在第 7 层攻击的情况下,只允许授权请求(有效),您只需为此付费。 GFE 执行的过滤器是免费的。
我正在从我的 GCP 项目中调用云函数。
当功能配置为仅允许内部流量时,我收到 403(权限被拒绝),请参阅 https://cloud.google.com/functions/docs/networking/network-settings#ingress_settings
移除入口控制时没有问题,函数以状态 200 响应。 该函数 不允许 允许未经身份验证的访问,已配置 IAM 策略 。
效仿 https://cloud.google.com/functions/docs/securing/authenticating#function-to-function 中的示例:
# main.py
import requests
# TODO<developer>: set these values
# REGION = None
# PROJECT_ID = None
RECEIVING_FUNCTION = 'hello-get'
# Constants for setting up metadata server request
# See https://cloud.google.com/compute/docs/instances/verifying-instance-identity#request_signature
function_url = f'https://{REGION}-{PROJECT_ID}.cloudfunctions.net/{RECEIVING_FUNCTION}'
metadata_server_url = \
'http://metadata/computeMetadata/v1/instance/service-accounts/default/identity?audience='
token_full_url = metadata_server_url + function_url
token_headers = {'Metadata-Flavor': 'Google'}
def hello_trigger(request):
token_response = requests.get(token_full_url, headers=token_headers)
jwt = token_response.text
function_headers = {'Authorization': f'bearer {jwt}'}
function_response = requests.get(function_url, headers=function_headers)
function_response.raise_for_status()
return function_response.text
def hello_get(req):
return 'Hello there...'
使用所需的入口设置部署函数和触发函数:
gcloud functions deploy hello-get --trigger-http --entry-point hello_get --runtime python37 --ingress-settings internal-only
gcloud functions deploy hello-trigger --trigger-http --entry-point hello_trigger --runtime python37 --ingress-settings all --allow-unauthenticated
呼叫 hello-trigger
returns 403.
更改 hello-get
的入口解决了问题:
gcloud functions deploy hello-get --trigger-http --entry-point hello_get --runtime python37 --ingress-settings all
正在拨打 hello-trigger
returns 200.
用于 Cloud Functions 的服务帐户被赋予了此设置的 Functions Invoker 角色。
当您将入口流量设置为 internal-only 时,仅接受来自您的 VPC 或来自 VPC SC(服务控制)的流量。
在这里,在你的触发函数中,你不是来自你的 vpc,而是来自另一个(一个无服务器 VPC,由 Google 管理,部署云函数的地方)。因此,入口设置不受尊重,您会收到 403。
因此,为此您有 2 个解决方案:
- 仅使用 IAM 服务来过滤谁可以调用您的函数,并让“public”您的函数具有 ingress=all。 (约翰在他的第二条评论中提出的解决方案)。安全级别已经很高了。
但是,有时出于监管原因(或老式安全团队设计)网络控制是首选。
- 如果你想通过你的VPC,你需要
- 在与触发函数相同的区域创建一个serverless VPC connector
- Deploy your trigger function with this serverless VPC connector
- 设置egress traffic to all
--egress-settings=all
像这样,您的触发器函数的所有传出流量都将通过无服务器 VPC 连接器,因此,流量在尝试到达您的“ingress-internal”云函数之前先在您的 VPC 中路由。它将被接受。
如果您的函数使用 ingress=all 设置,任何人都可以通过互联网访问它。
但是,如果你不让功能 public 可以访问,我的意思是,授权给未经身份验证的用户,只有有效的请求(经过身份验证和授权角色 cloudfunctions.invoker) 将由您的 Cloud Functions
处理事实上,任何 Google 服务名称 GFE: Google Front End 都有一个公共层。该层负责许多事情(在 HTTPS 中公开您的服务、管理您的证书、丢弃 DDoS 攻击 OSI 第 4 层,...),其中验证检查 header 和针对 IAM 服务的授权检查。
因此,如果在第 4 层发生 DDoS 攻击,GFE 默认会过滤这些攻击。在第 7 层攻击的情况下,只允许授权请求(有效),您只需为此付费。 GFE 执行的过滤器是免费的。