iT邦幫忙

2025 iThome 鐵人賽

DAY 27
0

Call一個Google Workspace API之前,到底還要做多少事?🤨
沒關係,告訴自己,把這一切設置好以後
未來就全部交給🦕Deno幫我自動跑腳本~

前言

接續昨天(Day26),已經開好了GCP專案,接著我需要先取得access token,才有權限使用Google Sheets API。

正文

實作目標

Deno執行TypeScript腳本,向GCP申請access token,並以JSON格式存放於專案目錄內。

實作步驟

①下載金鑰(Service account key file)

透過瀏覽器下載Service account key file (JSON format):

  1. 進入GCP控制台:https://console.cloud.google.com/welcome?project=<project-name>
  2. 左選單點「身分與存取權管理」(IAM & Admin)
  3. 點「服務帳戶」(Service accounts)
  4. 點進要使用的機器人帳戶
  5. 點「金鑰」(Keys)
  6. 新增鍵(Add key)→建立新的金鑰(Create new key)→ JSON →建立(Create)
  7. 將金鑰儲存在專案目錄內[^1]

這樣我就準備好一份JSON檔案,它就好比我的機器人的身分證明文件。

②撰寫腳本

決定存放處

接下來要做的是,我想透過一些行政手續,向Google OAuth伺服器申請臨時的Google Sheets API使用權限,也就是access token,並存放於.env/目錄:[^2]

const OUTPUT_PATH = "./.env/gcp-token.json";

使用官方套件

由於我希望這個流程可以透過腳本自動化,所以我這裡採用JWT(JSON Web Token)流程。[^3] 這裡我使用Google的Google Auth Library for Node.js套件,它提供了JWT這個class,它封裝了完整的行政流程,我不需要搞懂流程細節,就可以透過它取得token:

import { JWT } from "npm:google-auth-library@10.3.0";

這個腳本我使用Deno跑,可以不需要手動安裝套件,直接在路徑上標註版本即可,相比於Node.js省去了一個配置步驟。

填寫文件

接著,我使用JWT創造一個instance,填入兩個文件:

  1. 機器人的身分證明文件:keyFile
  2. 機器人這次任務的權限:scopes
    我只是想獲取Google Sheet的資料,所以僅申請readonly權限。
const client = new JWT({
  keyFile: "./keys/service-account.json",
  scopes: ["https://www.googleapis.com/auth/spreadsheets.readonly"],
});

取得Token

然後,透過getAccessToken方法,就會自動幫我們跑行政流程,並取得token:

const accessToken = await client.getAccessToken();

轉存Token

最後,把token轉成JSON:

const jsonString = JSON.stringify(accessToken, null, 2);
await Deno.writeTextFile(OUTPUT_PATH, jsonString);
console.log(`Saved GCP token to ${OUTPUT_PATH}`);

③執行腳本

這樣,就可以讓Deno跑這個腳本:

deno run --allow-net --allow-write --allow-read --allow-env ./denoScripts/get-gcp-token.ts
  • read權限:JWTinstance讀取service account key file
  • env權限:JWTinstance依序讀取:
    1. GOOGLE_SDK_NODE_LOGGING
    2. HTTPS_PROXY
    3. HTTP_PROXY
  • net權限:JWTinstance向Google OAuth伺服器發送HTTP POST請求
  • write權限:Deno.writeTextFile

比喻

我向Google公司承租了一間圖書室,我請代理人去圖書室查閱某本書並複印部分頁面。

代理人透過Google公司提供的自動製卡機(class JWT),在機器上掃描員工證(service account key file),填入權限需求後,機器就製造了一個能臨時進入圖書室的門禁卡(access token)。

由於自動製卡機只認員工證,不認員工本人,所以必須小心保管好員工證;同樣的,雖然門禁卡只有一小時期限,但弄丟的話,誰都可以在這段期間進去我的圖書室。

實際上,跑完整個流程的是🦕Deno,他借用代理人的員工證,而代理人還躺在Google雲端上。

後話

基於iThome鐵人賽活動的其中一個目標是推廣中文寫作,這兩天撰文時,我重新辦了一個新Google帳號跑一次中文介面,一時還找不到下載金鑰的地方哈哈哈😅

如果是在公司,我應該不會想用Deno跑腳本,畢竟那是速度與堪用更重要的商務場景。現在回顧覺得當時休假日真的挺chill的,由於Deno的安全性設計,讓JWT執行過程更透明,我可以慢吞吞地稍微了解Google的這個JWT封裝依序在背後做了哪些事、我再一步步同意。

OK,今天就先這樣,我要出門去感受西門町的週六夜晚啦~掰!

Annotations

[^1]: 和《實作回顧:doGet(下)》一樣,我當時是在prebuild階段使用,所以我直接把金鑰存在專案目錄內,並確定金鑰不會被push到GitHub。就資安上,GCP官方文件則有建議的更佳實作方式。

[^2]: 其實讀者不必將token存放於目錄內,call API時直接附加在fetcher上即可。由於當時我是第一次實作,所以想看一下具體會拿到什麼。

[^3]: JWT廣義來說一個開放標準:RFC7519,由HEADER.PAYLOAD.SIGNATURE三段的base64編碼構成。由於我沒有要實作API,而僅僅是使用API,所以我只了解到這裡。想進一步了解的讀者,可以閱讀Spongeさん於2019年鐵人賽的這幾篇文章


上一篇
Day26|Google Sheets API:GCP服務啟用與設置
系列文
我只是不想加班:一名客服人員的GAS自救之路27
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言