首页 > 解决方案 > 如何通过 Apps 脚本验证服务帐户以调用 GCP 云功能

问题描述

我正在努力从 Apps 脚本运行 GCP 云功能。云功能需要身份验证。但是我一直被抛出“401错误”

在我的谷歌项目上;

  1. 我创建了一个需要身份验证的云功能
  2. 我已经创建了一个具有调用(和编辑)该功能访问权限的服务帐户
  3. 我已下载该服务帐户的 JSON 密钥并将其保存为我的 Apps 脚本中名为CREDS的对象

到目前为止,这是我的脚本:

const CREDS = {....JSON Key I downloaded from Cloud Console}

function base64Encode(str){
  let encoded = Utilities.base64EncodeWebSafe(str)

  return encoded.replace(/=+$/,'')
}

function encodeJWT(){
  const privateKey = `Copied the PK from the CREDs file and replaced all the escaped whitespace as a string literal`;

  let header = JSON.stringify({
    alg: "RS256",
    typ: "JWT",
  });

  let encodedHeader = base64Encode(header);

  const now = Math.floor(Date.now() / 1000);
  let payload = JSON.stringify({
    "iss": "https://accounts.google.com",
    "azp": "OAUTH CLIENT ID I CREATED ON GCP",
    "aud": "OAUTH CLIENT ID I CREATED ON GCP",
    "sub": CREDS.client_id,
    "email": CREDS.client_email,
    "email_verified": true,
    //    "at_hash": "TMTv8_OtKA539BBRxLoTBw", //Saw this in a reverse engineered Token but didnt know what to put
    "iat": now.toString(),
    "exp": (now + 3600).toString()  
  })

  let encodedPayload = base64Encode(payload);

  let toSign = [encodedHeader, encodedPayload].join('.')
  let signature = Utilities.computeRsaSha256Signature(toSign, privateKey)
  let encodedSignature = base64Encode(signature);

  let jwt = [toSign, encodedSignature].join('.')

  return jwt;

}

function testFireStore() {
  let funcUrl = "https://[MY PROJECT].cloudfunctions.net/MyFunc"

  const token = encodeJWT()
  let options = {
    headers:{
      "Authorization": "Bearer " + token
    }
  }


  let func = UrlFetchApp.fetch(funcUrl,options)
  Logger.log(func.getContentText())
}

实际的 Cloud func 现在只给出一个“Hello World”,它在控制台中测试良好

仅供参考,我已经完成了一些步骤

标签: google-app-enginegoogle-apps-scriptgoogle-cloud-platformhttp-status-code-401

解决方案


@TheMaster 在我的解决方案的评论中发布的这个解决方案解决了这个问题。

在 GCP 方面,我进入并启用了计算引擎和 App Engine,然后使用了这个解决方案并且它起作用了。

唯一奇怪的是target_audience在那里请求,我必须做一些逆向工程才能得到它。我必须从命令行工具获取身份令牌,然后使用 jwt.io 对其进行解码,获取 AUD 密钥...

但除此之外,一切都像一个魅力


推荐阅读