Google Cloud Composer:如何从本地开发计算机触发 DAG 运行?

发布于 2025-01-09 00:18:25 字数 2844 浏览 2 评论 0原文

背景

我有一个在 GCP 上运行的 Google Cloud Composer 1 环境。

我编写了一个Google Cloud Function,当在云中运行时,它可以在我的 Composer 环境中成功触发 DAG 运行。我的代码基于 使用 Cloud Functions 触发 DAG 指南。

这是与我的问题最相关的代码部分(来源):

from google.auth.transport.requests import Request
from google.oauth2 import id_token
import requests


def make_iap_request(url, client_id, method='GET', **kwargs):
    """Makes a request to an application protected by Identity-Aware Proxy.
    Args:
      url: The Identity-Aware Proxy-protected URL to fetch.
      client_id: The client ID used by Identity-Aware Proxy.
      method: The request method to use
              ('GET', 'OPTIONS', 'HEAD', 'POST', 'PUT', 'PATCH', 'DELETE')
      **kwargs: Any of the parameters defined for the request function:
                https://github.com/requests/requests/blob/master/requests/api.py
                If no timeout is provided, it is set to 90 by default.
    Returns:
      The page body, or raises an exception if the page couldn't be retrieved.
    """
    # Set the default timeout, if missing
    if 'timeout' not in kwargs:
        kwargs['timeout'] = 90

    # Obtain an OpenID Connect (OIDC) token from metadata server or using service
    # account.
    open_id_connect_token = id_token.fetch_id_token(Request(), client_id)

    # Fetch the Identity-Aware Proxy-protected URL, including an
    # Authorization header containing "Bearer " followed by a
    # Google-issued OpenID Connect token for the service account.
    resp = requests.request(
        method, url,
        headers={'Authorization': 'Bearer {}'.format(
            open_id_connect_token)}, **kwargs)
    if resp.status_code == 403:
        raise Exception('Service account does not have permission to '
                        'access the IAP-protected application.')
    elif resp.status_code != 200:
        raise Exception(
            'Bad response from application: {!r} / {!r} / {!r}'.format(
                resp.status_code, resp.headers, resp.text))
    else:
        return resp.text

挑战

我希望能够在我的开发计算机上本地运行相同的云功能。当我尝试这样做时,该函数崩溃并显示以下错误消息:

google.auth.exceptions.DefaultCredentialsError:找不到元数据服务器或有效的服务帐户凭据。

这是有道理的,因为引发错误的行是:

    google_open_id_connect_token = id_token.fetch_id_token(Request(), client_id)

确实,在本地运行时,元数据服务器不可用,并且我不知道如何使有效的服务帐户凭据可用于调用 fetch_id_token()

问题

我的问题是 - 当我在本地运行函数时,我需要更改什么才能安全地获取 OpenID Connect 令牌?

Background

I have a Google Cloud Composer 1 environment running on GCP.

I have written a Google Cloud Function that, when run in the cloud, successfully triggers a DAG Run in my Composer environment. My code is based on and almost identical to the code in the Trigger DAGs with Cloud Functions guide from GCP documentation.

Here is the section of code most relevant to my question (source):

from google.auth.transport.requests import Request
from google.oauth2 import id_token
import requests


def make_iap_request(url, client_id, method='GET', **kwargs):
    """Makes a request to an application protected by Identity-Aware Proxy.
    Args:
      url: The Identity-Aware Proxy-protected URL to fetch.
      client_id: The client ID used by Identity-Aware Proxy.
      method: The request method to use
              ('GET', 'OPTIONS', 'HEAD', 'POST', 'PUT', 'PATCH', 'DELETE')
      **kwargs: Any of the parameters defined for the request function:
                https://github.com/requests/requests/blob/master/requests/api.py
                If no timeout is provided, it is set to 90 by default.
    Returns:
      The page body, or raises an exception if the page couldn't be retrieved.
    """
    # Set the default timeout, if missing
    if 'timeout' not in kwargs:
        kwargs['timeout'] = 90

    # Obtain an OpenID Connect (OIDC) token from metadata server or using service
    # account.
    open_id_connect_token = id_token.fetch_id_token(Request(), client_id)

    # Fetch the Identity-Aware Proxy-protected URL, including an
    # Authorization header containing "Bearer " followed by a
    # Google-issued OpenID Connect token for the service account.
    resp = requests.request(
        method, url,
        headers={'Authorization': 'Bearer {}'.format(
            open_id_connect_token)}, **kwargs)
    if resp.status_code == 403:
        raise Exception('Service account does not have permission to '
                        'access the IAP-protected application.')
    elif resp.status_code != 200:
        raise Exception(
            'Bad response from application: {!r} / {!r} / {!r}'.format(
                resp.status_code, resp.headers, resp.text))
    else:
        return resp.text

Challenge

I want to be able to run the same Cloud Function locally on my dev machine. When I try to do that, the function crashes with this error message:

google.auth.exceptions.DefaultCredentialsError: Neither metadata server or valid service account credentials are found.

This makes sense because the line that throws the error is:

    google_open_id_connect_token = id_token.fetch_id_token(Request(), client_id)

Indeed when running locally the Metadata Server is not available and I don't know how to make valid service account credentials available to the call to fetch_id_token().

Question

My question is - What do I need to change in order to be able to securely obtain the OpenID Connect token when I run my function locally?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

被你宠の有点坏 2025-01-16 00:18:25

我已经能够在本地运行我的代码而无需更改它。以下是详细信息,但我不确定这是完成此操作的最安全的选择。

  1. 在 Google Cloud Console 中,我浏览到服务帐号模块。
  2. 我单击“App Engine 默认服务帐户”以查看其详细信息。
  3. 我切换到“KEYS”选项卡。
  4. 我单击“添加密钥”按钮并生成了一个新的 JSON 密钥。
  5. 我下载了 JSON 文件并将其放在源代码文件夹之外。
  6. 最后,在我的开发机器*上,我将 GOOGLE_APPLICATION_CREDENTIALS 环境变量设置为放置 JSON 文件的路径。更多详细信息请参见:https://cloud.google.com/docs/authentication/product

完成此操作后,对 id_token.fetch_id_token() 的调用从密钥文件中获取服务帐户详细信息并成功返回令牌。

* - 就我而言,我在 PyCharm 调试配置中设置了环境变量。

I've been able to run my code locally without changing it. Below are the details though I'm not sure this is the most secure option to get it done.

  1. In the Google Cloud Console I browsed to the Service Accounts module.
  2. I clicked on the "App Engine default service account" to see its details.
  3. I switched to the "KEYS" tab.
  4. I clicked on the "Add Key" button and generated a new JSON key.
  5. I downloaded the JSON file and placed it outside of my source code folder.
  6. Finally, on my dev machine*, I set the GOOGLE_APPLICATION_CREDENTIALS environment variable to be the path to where I placed the JSON file. More details here: https://cloud.google.com/docs/authentication/production

Once I did this, the call to id_token.fetch_id_token() picked up the service account details from the key file and returned the token successfully.

* - In my case I set the environment variable inside my PyCharm Debug Configuration.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文