GASアドオンでスクリプトプロパティ読み取り時にPERMISSION_DENIEDエラーが発生する場合の対処法

記事タイトルとURLをコピーする

G-gen の min です。Google Apps Script(以下、GAS)で開発したアドオンをユーザーが実行した際、スクリプトプロパティの読み取り時に PERMISSION_DENIED エラーが発生しました。本記事では、この事象の原因と対処法を解説します。

事象

GAS で作成した機能を Google Workspace アドオンとして配布し、利用者がそのアドオンのメニューを実行した際、以下のようなエラーログが Google Cloud の Cloud Logging に記録され、処理が失敗しました。

{
  "insertId": "-w58fk8fbk0qfb",
  "jsonPayload": {
    "message": "ストレージからの読み取り中にサーバーエラーが発生しました。エラーコード: PERMISSION_DENIED。",
    "serviceContext": {
      "service": "AKfycbw...(省略)..."
    }
  },
  "resource": {
    "type": "app_script_function",
    "labels": {
      "project_id": "000000000000",
      "invocation_type": "menu",
      "function_name": "callUpdateMasterData"
    }
  },
  "severity": "ERROR",
  "labels": {
    "script.googleapis.com/deployment_id": "AKfycbw...(省略)..."
  }
}

メインのエラーメッセージは、以下のとおりです。

ストレージからの読み取り中にサーバーエラーが発生しました。エラーコード: PERMISSION_DENIED。

該当のスクリプトでは、PropertiesService.getScriptProperties().getProperty('KEY_NAME') メソッドを使用し、GAS エディタ上で手動設定したスクリプトプロパティを読み取ろうとしていました。

該当のソースコード

const TARGET_URL = PropertiesService.getScriptProperties().getProperty('TARGET_URL');
  
function callUpdateMasterData() {
  // ...処理...
  // URLにアクセスしてデータを取得する
  const response = UrlFetchApp.fetch(TARGET_URL);
  
  // 結果をログに出力する
  Logger.log('Response Code: ' + response.getResponseCode());
}

スクリプトプロパティ

原因

このエラーは、Google Workspace Marketplace で配布されるアドオンのセキュリティ仕様と、スクリプト実行環境の関係に起因しています。

Google Workspace アドオンでは、スクリプト実行ユーザーの環境で処理が実行されます。しかし、スクリプトプロパティは「スクリプトプロジェクト(ファイル)に紐づく共有ストレージ」であり、そのファイルにアクセス権を持つユーザー間で共有されるものです。

Marketplace 経由で配布されたアドオンを使用する場合、実行ユーザー(アドオン利用者)はスクリプトプロジェクト自体の所有者や編集者ではありません。

ユーザーには、開発者の Google ドライブ内にある GAS プロジェクトファイル自体へのアクセス権限がないため、結果としてそのファイルに付随するプロパティストアへのアクセスも拒否されます。

PropertiesService.getScriptProperties() を用いた読み取り処理が、実行時に PERMISSION_DENIED エラーとなります。

対処法

定数としてコード内に記述する

外部サービスの URL や固定の ID など、公開されても問題ない設定値であれば、スクリプト プロパティではなくコード内の定数(const)として記述することでエラーを回避できます。

// 修正前:スクリプトプロパティから読み取る(アドオン配布時にエラーになる)
// const TARGET_URL = PropertiesService.getScriptProperties().getProperty('TARGET_URL');
  
// 修正後:コード内に定数として定義する
const TARGET_URL = 'https://blog.g-gen.co.jp/';
  
function callUpdateMasterData() {
  // ...処理...
  // URLにアクセスしてデータを取得する
  const response = UrlFetchApp.fetch(TARGET_URL);
  
  // 結果をログに出力する
  Logger.log('Response Code: ' + response.getResponseCode());
}

ただし、API キーなどの機密情報はソースコード内に直接記述してはいけないことに十分留意してください。

ユーザーにスクリプトファイルへの閲覧権限を付与する

アドオンの実行ユーザーに対して、実体となる GAS プロジェクトファイルの閲覧者権限を付与します。

スクリプト プロパティはファイルに紐づくメタデータであるため、ユーザーがファイル自体へのアクセス権を持っていれば、プロパティの読み取りが可能になります。

ただし、この方法はユーザーがソースコードを閲覧可能になるというセキュリティ上の懸念があります。社内用ツールなど、ソースコードの内容が利用者に公開されても問題ない場合にのみ採用してください。

佐々木 愛美 (min) (記事一覧)

クラウドソリューション部 データアナリティクス課。2024年7月 G-gen にジョイン。G-gen 最南端、沖縄県在住。最近覚えた島言葉は、「マヤー(猫)」。