【问题标题】:Google Cloud Functions Credentials for Local Development用于本地开发的 Google Cloud Functions 凭据
【发布时间】:2022-09-23 05:02:13
【问题描述】:

我有谷歌云功能。在此函数中,我想将文件写入 GCS(谷歌云存储),然后获取写入 GCS 的文件的签名 URL,并将该 URL 发送给调用者。

对于本地开发,我使用 functions-framework 命令在本地运行函数: functions-framework --source=.build/ --target=http-function --port 8082

当我想写信给 GCS 或获取签名的 URL 时,云功能框架只是尝试从已登录的 gcloud CLI 用户那里获取凭据。但是,我想指出它从服务帐户中读取凭据。对于所有其他 gcloud 开发目的,我们已将服务帐户信息放在本地 creds.json 文件中,并将 gcloud 指向从该文件中读取。

有什么方法可以实现这个功能吗?这意味着当我在本地启动函数时(使用函数框架),我将它指向 creds.json 文件以从那里读取凭据?

  • 如果你在运行functions-framework 之前export APPLICATION_DEFAULT_CREDENTIALS=/path/to/your/key.json 会发生什么?
  • 我不熟悉functions-framework,但快速的谷歌建议functions-framework 作为 CLI 仅由 Python (link) 使用。所有 Google 的 SDK,例如对于 GCS,使用您应该使用的应用程序默认凭据,而不是显式路径到密钥。如果functions-framework 是这样(我怀疑),那么导出变量应该可以工作。
  • @DazWilkin,您不能推荐使用服务帐户密钥文件。这不是一个好习惯,而且 90% 的情况下,你都可以不用。在这种情况下,命令gcloud auth application-default login 是更好的建议。特别是对于测试签名 URL,因为使用该本地凭据以及 Cloud Functions 凭据(通过元数据服务器),私钥不存在,并且必须以特定方式调用签名 URL(提供令牌和服务帐户代表您签署 URL)
  • @guillaume_blaquiere 在脱离 GCP 运行时,您的选择更少。使用gcloud auth application-default login 也会创建应用程序默认凭据,这些凭据拥有用户帐户的所有权限。并且作为一个名为{HOME}/.config/gcloud/application-default_credentials 的密钥持久保存。您的建议是什么?
  • 如果您可以提供任何反馈来验证讨论中的答案是否有帮助,那对社区来说会很棒吗?

标签: google-cloud-platform google-cloud-functions google-cloud-storage gcloud service-accounts


【解决方案1】:

所有 Google 的 SDK,例如用于 GCS 的 SDK,都使用您应该使用的应用程序默认凭据,而不是显式路径到密钥。如果函数框架是这样,那么导出变量应该可以工作。

在这种情况下,命令 gcloud auth application-default login 是更好的建议,尤其是对于测试签名 URL,因为使用该本地凭据以及 Cloud Functions 凭据(通过元数据服务器),私钥不存在,并且签名 URL必须以特定方式调用(提供令牌和服务帐户才能对 URL 进行签名)。 使用gcloud auth application-default login 创建应用程序默认凭据,该凭据具有用户帐户的所有权限,并作为名为@9​​87654324@ 的密钥持久保存。

【讨论】:

    【解决方案2】:

    云功能本地开发认证

    这就是我为使用由 pub/sub 事件触发的 Nodejs 本地开发谷歌云功能所做的工作。这使用Functions Framework Nodejs

    TL;博士;

    # shell A
    gcloud auth application-default login
    
    npm start
    

    发布/订阅事件消息

    # shell B
    curl -d "@mockPubSub.json" \                                                                                
      -X POST \
      -H "Content-Type: application/json" \
      http://localhost:8080
    

    更多细节

    1. 带有函数框架的云函数

      文档:Functions Framework Nodejs

      package.json

      注意--target--signature-type

      {
      ...
        "scripts": {
          "start": "npx functions-framework --target=helloPubSub --signatur-type=event"
        },
        "dependencies": {
          "@google-cloud/debug-agent": "^7.0.0",
          "@google-cloud/storage": "^6.0.0"
        },
        "devDependencies": {
          "@google-cloud/functions-framework": "^3.1.2"
        }
      ...
      }
      
      1. downloads file 的示例 nodejs 云函数
      /* modified from the sample
      index.js
      */
      
      const {Storage} = require('@google-cloud/storage');
      
      function log(message, severity = 'DEBUG', payload) {
        // Structured logging
        // https://cloud.google.com/functions/docs/monitoring/logging#writing_structured_logs
      
        if (!!payload) {
          // If payload is an Error, get the stack trace.
          if (payload instanceof Error && !!payload.stack) {
            if (!!message ) {
               message = message + '\n' + payload.stack;
            } else {
               message = payload.stack;
            }
          }
        }
        const logEntry = {
          message: message,
          severity: severity,
          payload : payload
        };
        console.log(JSON.stringify(logEntry));
      }
      
      function getConfigFile(payload){
        console.log("Get Config File from GCS")
        const bucketName = 'some-bucket-in-a-project';
        const fileName = 'config.json';
      
        // Creates a client
        const storage = new Storage();
      
        async function downloadIntoMemory() {
          // Downloads the file into a buffer in memory.
          const contents = await storage.bucket(bucketName).file(fileName).download();
      
          console.log(
            `Contents of gs://${bucketName}/${fileName} are ${contents.toString()}.`
          );
        }
      
        downloadIntoMemory().catch(console.error);
      }
      
      
      exports.helloPubSub = async (pubSubEvent, context) => {
        /*
        Read payload from the event and log the exception in App project if the payload cannot be parsed
        */
       try {
          const payload = Buffer.from(pubSubEvent.body.message.data, 'base64').toString()
          const pubSubEventObj = JSON.parse(payload) ;
          console.log("name: ", pubSubEventObj.name);
      
          getConfigFile(pubSubEventObj)
      
        } catch (err) {
          log('failed to process payload: + payload \n' , 'ERROR', err);
        }
      
      };
      
      1. Pub/Sub 事件的模拟消息

      blog reference,但我没有使用模拟器

      myJson.json

      {"widget": {
          "debug": "on",
          "window": {
              "title": "Sample Konfabulator Widget",
              "name": "main_window",
              "width": 500,
              "height": 500
          },
          "image": { 
              "src": "Images/Sun.png",
              "name": "sun1",
              "hOffset": 250,
              "vOffset": 250,
              "alignment": "center"
          },
          "text": {
              "data": "Click Here",
              "size": 36,
              "style": "bold",
              "name": "text1",
              "hOffset": 250,
              "vOffset": 100,
              "alignment": "center",
              "onMouseUp": "sun1.opacity = (sun1.opacity / 100) * 90;"
          }
      }}  
      
      1. Pub/sub 消息的编码 (可能有更好的方法)
      cat myJson.json | grep -v % | base64
      
      1. 将该输出值转化为数据钥匙:

      mockPubSub.json

      {
        "message": {
          "attributes": {
            "greeting": "Hello from the Cloud Pub/Sub Emulator!"
          },
          "data": "< put out base64 from above >",
          "messageId": "136969346945"
        },
        "subscription": "projects/myproject/subscriptions/mysubscription"
      }
      
      1. 按照从TL;博士:以上。

      免责声明

      • 在擦洗(即重命名位)并复制它时,我可能搞砸了。对不起,如果这是真的。
      • 这都是人为的。如果您对我的设计感到好奇,可以从云调度程序中获取消息,其中包含有关从配置中读取内容的相关详细信息。

    【讨论】:

      猜你喜欢
      • 2021-11-23
      • 1970-01-01
      • 2019-05-10
      • 2017-11-26
      • 2020-03-11
      • 1970-01-01
      • 2021-02-04
      • 1970-01-01
      • 2017-08-24
      相关资源
      最近更新 更多