google-apps-script - UrlFetchApp.fetch 由 Sheets 事件触发,因缺少权限而失败,但在直接运行时有效
问题描述
我有一个谷歌应用程序脚本托管在谷歌表格表中,它运行 UrlFetchApp.fetch,用于几件事(使用 GCP 服务帐户进行身份验证、调用 GCP api 等)。
问题是,如果我直接从脚本编辑器运行或调试它(菜单运行 -> 运行函数/调试函数),它工作正常,但是当我将它附加到像“onEdit”这样的事件处理程序时,它会失败,在“ Apps 脚本仪表板”我可以看到这个错误
您无权调用 UrlFetchApp.fetch。所需权限:https://www.googleapis.com/auth/script.external_request 在 getBearerToken(Code:24) at writeToBigquery(Code:40) at onEdit(Code:15) 的未知函数
但是,我有给定的范围https://www.googleapis.com/auth/script.external_request作为清单和脚本属性,以及脚本本身(即使直接启动时带有硬编码值的 onedit 也可以正常运行)。
遵循清单:
{
"timeZone": "Europe/Paris",
"dependencies": {
...
},
"oauthScopes": [
"https://www.googleapis.com/auth/script.external_request"
],
"exceptionLogging": "STACKDRIVER"
}
脚本文件提取如下:
function onEdit(e) {
// var range = e.range;
var range = SpreadsheetApp.getActiveSheet().getRange("A1");
// var row = range.rowStart;
var row = 2;
var cols = ['C', 'K', 'L', 'M', 'O', 'P', 'Q', 'R'];
var data = new Object();
for (var ii = 0; ii < cols.length; ii++)
{
data[cols[ii]] = SpreadsheetApp.getActiveSheet().getRange(cols[ii] + row.toString()).getValue();
}
Logger.log('calling writeToBigquery');
writeToBigquery(data);
}
// uses the wonderful library https://github.com/Spencer-Easton/Apps-Script-GSApp-Library to oauth against a GCP service account
function getBearerToken() {
var jsonKey = JSON.parse(PropertiesService.getScriptProperties().getProperty("json_key"));
var key = jsonKey.private_key;
var clientEmail = jsonKey.client_email;
var serverToken = new GSApp.init(key, ['https://www.googleapis.com/auth/bigquery.insertdata'], clientEmail);
// requestToken invokes UrlFetchApp according to https://github.com/Spencer-Easton/Apps-Script-GSApp-Library/blob/master/GSApp.gs, line 120
serverToken.addUser(clientEmail).requestToken();
var token = serverToken.getToken(clientEmail);
Logger.log(token);
return token.token;
}
function uuidv4() {
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8);
return v.toString(16);
});
}
function writeToBigquery(obj)
{
Logger.log('requesting bearer token');
// fails in this line
var token = getBearerToken();
// lots of other irrelevant stuff
// ...
}
如前所述,当直接从脚本编辑器运行时工作正常,它只是在通过谷歌表格中的用户交互触发它运行时失败。
此外,编辑 Google 表格的用户不一定是在 GCP 项目中拥有权限的用户(这就是使用服务帐户的原因)。