安全存储在 Google Apps 脚本中使用的 API 个秘密 - 已发布的库

Securely Storing API Secrets used in Google Apps Script - Published Library

在 Google 表格中,有一个脚本使用“UrlFetchApp”从外部 API 获取信息,需要在每个调用中包含一个 API 密钥。

sheet 有许多编辑器,但只有所有者才能看到 API 密钥,因此将密钥存储在脚本本身或使用 PropertiesService 是不是一个选项。

以下解决方案是否会阻止 sheet 编辑者看到密钥?

  1. 创建一个新的独立 Apps Script 项目。

  2. 在独立脚本中,创建以下函数:

     function fetchData(idFromSheetScript) {
       var secret = '/abc123';
       var id = idFromSheetScript;
       var uri = 'https://.../'; 
       var url = uri+id+secret;
       var data = UrlFetchApp.fetch(url);
       return data;
     }
    
  3. 将独立脚本部署为库。不要与任何人共享该项目。

  4. 在 Google 表格绑定脚本中,导入库并使用库中的 fetchData() 函数。

     var response = fetchData('10');
    

导入库的 sheet 的编辑者是否能够看到或获取(通过日志记录或其他方式)库中的“秘密”变量,或者他们只能看到函数的返回变量?

  • 你的方法有问题:

    • 库需要shared with atleast "view level" access to the end user,否则无法运行。所以,第3点不可行。

    • 标识符为MyLibrary的库源代码也可以用

      检索
      console.log(MyLibrary.fetchData.toString());
      //where fetchData is one of the function names in MyLibrary
      
  • 可安装的编辑触发器:

    • 这些触发器 run under the authority of the user who created the trigger。因此,库可以与一个 user/dummy Google 帐户共享,并让该用户安装触发器,同时限制所有其他编辑者访问库源代码。

    • 但是,如果有恶意的编辑器,他们只需将 onEdit() 函数编辑为:

      function onEditInstalled(){
        SpreadsheetApp.getActiveRange().setValue(MyLibrary.fetchData.toString())
      }
      

      并编辑一些内容以获得 source+api 键。但是他们可以对创建触发器的用户做更多邪恶的事情,如果可安装的触发器有更多的权限(比如访问 Gmail 或 Drive)并且如果 在最近的部署中总是 运行.

    • 以上也许可以通过将触发器设置为总是run at a predetermined version and not at HEAD/latest version. This can be changed when setting up triggers in apps script dashboard user interface. To create a version, you can create a dummy library/webapp deployment or use the api. This protects the code against any modifications, because a version is like a 'snapshot' of current code. Once a trigger is set to execute at a certain version, it cannot be changed by other editors. There is also currently no way to modify a existing version by the owner or a editor. Versions are immutable.

      来避免
  • script properties are not shared between the library and the including script 起,您可以使用它来隐藏 api 键。

  • 另一种选择是将独立脚本部署为具有访问权限的 web app:任何人,包括匿名用户,但使用使用身份令牌的身份验证机制(ScriptApp.getIdentityToken())。但是您需要在 web 应用程序端为 id 令牌构建适当的验证机制。

    请注意,所有这些变通办法都没有经过安全渗透测试,而是作为基于经验的概念提供的。安全是相对的。欢迎批评指正

正如@TheMaster 所提到的,基于图书馆的共享性质,图书馆的机制并不打算超出用户的视线。

一旦库包含在项目中并被使用,运行库函数的用户基本上可以访问它的代码。

例如,他们可以重载库方法,如下所示:

Librarytestremove.UrlFetchApp = {
  fetch: function(url){
    console.log('check this out', url);
  }
};

var response = Librarytestremove.fetchData('10');

结果:

所以,如果您真的有什么需要保密的,请不要使用 Apps 脚本库。

如果您使用它们 - 保持最小和合理。