如何验证Python客户端应用程序是否可以访问受限的谷歌云功能



我已经创建了一个Google Cloud函数,我想从我正在开发的Python应用程序中访问它。我可以在不需要身份验证的情况下访问该功能,但在启用身份验证时无法访问该功能。

这是我正在使用的服务帐户密钥,其中包含已删除的信息。它配置的唯一角色是调用云函数。

{
"type": "service_account",
"project_id": "XYZ",
"private_key_id": "XYZ",
"private_key": "XYZ",
"client_email": "XYZ",
"client_id": "XYZ",
"auth_uri": "https://accounts.google.com/o/oauth2/auth",
"token_uri": "https://oauth2.googleapis.com/token",
"auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
"client_x509_cert_url": "XYZ"
}

经过身份验证的请求似乎需要包含在请求Authorization标头中的令牌,但我不知道从哪里获取该令牌。

我尝试过使用这里概述的方法,包括环境变量和默认的auth方法,但这不起作用。我认为这是因为服务帐户密钥与OAuth令牌不同。(我已经创建了一个具有云功能调用程序权限的新服务帐户,并且正在使用该服务帐户密钥(。我收到以下错误:

google.auth.exceptions.RefreshError: ('invalid_scope: Invalid OAuth scope or ID token audience provided.', '{"error":"invalid_scope","error_description":"Invalid OAuth scope or ID token audience provided."}')

如何生成此令牌来验证来自Python脚本的请求?还是建议使用服务帐户的方法,但出现了其他问题?

我能够做到这一点,尽管在撰写本文时,文档中有一个错误让我很失望。

使用google-auth库中的IDTokenCredentials类可以访问受保护的云功能:

credentials = service_account.IDTokenCredentials.from_service_account_file( 
SERVICE_ACCOUNT_JSON_FILE, 
target_audience="https://function/url/here",
) 
authed_session = AuthorizedSession(credentials)
response = authed_session.post(url)

我的服务帐户配置有";云函数调用程序";角色

您的问题几乎可以肯定是您为该服务帐户提供的角色。根据我的经验,服务帐户很挑剔,角色/权限并不总是按照你认为的方式行事。首先创建一个具有完全权限的服务帐户(项目所有者(。在脚本中使用该服务帐户,然后从那里开始限制权限。听起来你至少需要一个云功能";管理员";。如果有效的话,试着降低另一个级别。云功能"显影剂";等

如果你正在使用应用程序引擎甚至其他云功能连接到你的云功能,你可以使用这个:功能到功能,步骤基本上是:

  1. 授予云函数调用程序。

  2. 在调用功能中,您需要:

  3. 创建一个谷歌签名的OAuth ID令牌,其中受众(aud(设置为接收函数的URL

  4. 在对函数的请求中的Authorization:Bearer ID_token标头中包含ID令牌。

    导入请求

    //# TODO<developer>: set these values
    REGION = 'us-central1'
    PROJECT_ID = 'my-project'
    RECEIVING_FUNCTION = 'my-function'
    //# 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 calling_function(request):
    //# Fetch the token
    token_response = requests.get(token_full_url, headers=token_headers)
    jwt = token_response.text
    //# Provide the token in the request to the receiving function
    function_headers = {'Authorization': f'bearer {jwt}'}
    function_response = requests.get(function_url, headers=function_headers)
    return function_response.text
    

我已经测试了这个解决方案,并按预期工作。

如果您从无法访问计算元数据的计算实例(例如您自己的服务器(调用函数,则必须手动生成正确的令牌:

  1. 在target_audience声明设置为接收功能的URL的情况下,对服务帐户JWT进行自签名。

  2. 将自签名JWT交换为谷歌签名的ID令牌,该令牌应将aud声明设置为上述URL。

  3. 在对函数的请求中的Authorization:Bearer ID_token标头中包含ID令牌。

CloudIAP文档中有演示此功能的示例代码。你可能感兴趣的部分应该是从服务帐户进行身份验证

相关内容

  • 没有找到相关文章

最新更新