Google Apps Scriptは、パスワード付きPDFが作成できない事から、生成するためには外部のAPI等を利用しなければなりません。これ、Google Cloud Functionsでどうにかできないかなぁという考えている過程で、Hummus RecipeというNode.jsのモジュールが単体でPDF暗号化に対応しているので、これ使えないかなと実験中(Bufferから直接は暗号化できない為)。

そのHummus Recipeは通常はローカルのPDFファイルを受け取って、パスワード設定するのですが、クラウド上で実現するには、一旦Google Cloud Storageにアップしなければならいのではという事で、今回は、GASからGCSにアップする手段を作ります

今回使用するスプレッドシートその他

※Cloud Storageサービスは有料のサービスです。その為、利用するには事前に課金設定(請求アカウントの設定)が必要になります。

事前準備

OAuth2.0認証ライブラリの追加

今回のサービスは、OAuth2.0認証が必要です。以下の手順でOAuth2 for Apps Scriptライブラリを追加しましょう。

  1. スクリプトエディタを開きます。
  2. メニューより「リソース」⇒「ライブラリ」を開きます。
  3. ライブラリを追加欄に「1B7FSrk5Zi6L1rSxxTDgDEUsPzlukDsi4KGuTMorsTQHhGBzBkMun4iDF」を追加します。
  4. 現時点ではバージョンは30が最新ですので、それを選択しておきます。
  5. 保存ボタンを押して完了

これで、OAuth2.0認証にまつわる様々な関数を手軽に利用できるようになります。

図:ライブラリを追加した様子

プロジェクトを移動

今回の発表直前の2019年4月8日より、Google Apps ScriptからCloud Platform Projectへ直接アクセスが出来なくなりました。これまでにデプロイしてるものについては、これまで通り「リソース」⇒「Google Cloud Platform API ダッシュボード」からアクセスが可能です。

今回の変更はスプレッドシート上で動かすスクリプトやGoogleの拡張サービスを利用しないタイプのスクリプトであれば特に問題はありませんが、「Apps Script API」や「Google Picker API」、「Cloud SQL接続」などGCP上のAPIを利用する場合には以下の手順を踏んで、Google Apps Scriptにプロジェクトを連結する必要があります。これまでは、自動的にGCP上にGoogle Apps Script用のプロジェクトが生成されていたのですが、今後は自分の組織(もしくはGCPプロジェクト)上で作成されたプロジェクトでなければならないということです。詳細はこちらのページを見てください。

連結する手順は以下の通り

  1. Google Cloud Consoleを開く
  2. 左上にある▼をクリックする
  3. ダイアログが出てくるので、新規プロジェクトを作るか?既存のプロジェクトを選択する。この時、G Suiteであれば選択元は「自分のドメイン」を選択する必要があります。
  4. プロジェクト情報パネルから「プロジェクト番号」をコピーする
  5. 対象のGoogle Apps Scriptのスクリプトエディタを開く
  6. 「リソース」⇒「Cloud Platform プロジェクト」を開く
  7. 4.で入手した番号をプロジェクトを変更のテキストボックスに入れて、プロジェクトを設定ボタンをクリックする
  8. 無事に移動が完了すればメッセージが表示されます。
  9. この時、元の自動作成されたプロジェクトはシャットダウンされて消えます。これで設定完了です。

今回のこの変更だと1つ作ったプロジェクトに集約する必要があるので、クォータについてプロジェクト毎のカウントだったので問題なかったものが、集約されることで、クォータに引っ掛かる可能性があります。

図:プロジェクト番号をコピーしておきます

図:プロジェクトを他のプロジェクトに紐付けしました。

図:GCPの拡張サービスを使うには手順が必要になった

サービスアカウントの作成

今回のスクリプトの準備で最も面倒なのはこのサービスアカウントの作成です。サービスアカウントの作成自体は以前Google Cloud Consoleを弄ってみるの回で紹介しています。今回はサービスアカウント方式を利用しています。請求アカウントは事前に作ってある事としてここでは、サービスアカウントの作成のみを紹介します。

  1. スクリプトエディタを開き、「リソース」⇒「Googleの拡張サービス」を開く
  2. ダイアログ下にある「Google Cloud Platform API ダッシュボード」を開く
  3. APIとサービスにて、APIとサービスの有効化にするをクリックする。
  4. Cloud Storage JSON APIを有効化する。続けて認証情報の追加画面に移動し、Cloud Storage JSON APIを選択しておく。
  5. App Engineで使う予定の問いには、「いいえ」で答える。
  6. 次のステップではサービスアカウントの名前を入力。わかりやすい名前をつけましょう。キーのタイプはJSONを選択
  7. サービスアカウントの役割では、Project⇒編集者を選択します。
  8. JSONファイルがダウンロードされるので、これを誰とも共有しない形で、Google Driveにアップロードします。流出すると後で課金で痛い目を見るので絶対に共有はしないでください。
  9. アップロードしたJSONファイルの直URLを取得する。https://drive.google.com/open?id=に続けてファイルのIDをつなげればOKです。
  10. 次の項目のJSONキーファイルを取得して認証するにて、冒頭のfilelinkの場所にこのURLを入れてあげる。

図:Cloud Storage JSON APIを有効化する

図:APIの認証情報を作っておく

図:サービスアカウントの権限はできる限り最小で

JSONキーファイルを取得して認証する

  • この認証方式はサービスアカウントが認証を行うので、いつものユーザが認証するものとは異なり、Access Token取得は自動で行われます。
  • 取得したアクセストークン等の塊は、OAuth2ライブラリ最新版より、スクリプトプロパティではなくユーザプロパティに格納されているので、より安全になっています。塊は、var service = checkOAuth();で呼び出せます。
  • スコープは半角スペースで切ると、複数付加することが可能です。今回はcloud-platformdevstorage.read_writeを繋げています。

Google Picker用の準備

今回のスクリプトでは、ユーザがDriveのファイルを指定し、Cloud StorageにアップできるようにPicker APIを利用しています。APIキーの取得に関しては、前回の記事が参考になります。

GAS側コード

  • 必ず1回、startoauthにて認証の実行が必要です。

HTML側コード

Cloud Storageにバケットを用意する

ここまで準備ができたら、あとはCloud Storage側にバケットを用意します。以下の手順でバケットを用意して、アップロード用コードの為のバケット名を取得しておきます。

  1. Cloud Consoleにて、Cloud Storageを開き、バケットの作成をクリック
  2. 名前に半角英数字で命名する。これがバケット名になる。
  3. 作成をクリックして完了
  4. 今回は更に、publicという名前のフォルダを用意しました。

図:名前は世界でユニークな名前をつけなければならない

ソースコード

  • バケットの名前は、drive2gcsにしてあります。
  • Pickerからは、ファイルのIDとファイル名を引数で取得しています。
  • publicフォルダ以下にファイル名を付けてアップロードするようにしています。
  • URL組み立てでバケット名と格納先+ファイル名を繋げています。
  • POST通信で取得したByteデータをGCS側へと渡しています。
  • DELETEメソッドを使って、https://www.googleapis.com/storage/v1/b/バケット名/o/ファイル名にて、ファイルを削除する事も可能です。

ちなみに、レスポンスで取得した内容は以下のような感じ。getContentTextで取得できます。これで、Cloud Function側からファイルにアクセスできるようになったはず!!多分。

図:無事にアップロードできました。

関連リンク

共有してみる: