「サービスアカウントを作ってJSONを持ってきましょう!」ばかりでよくわからなかった。実際に動かす場所ではWorkload Identityを使う予定なので、手元の開発や動作確認でもJSONなしに動かせるようにしたい。
Application default credentialsを使うのがいいんじゃないか?と思っていたが、Goからスプレッドシートを見ようとするとこんなエラーが出てくる。
package main
import (
"context"
"fmt"
"log"
"google.golang.org/api/sheets/v4"
)
const spreadsheetId = "....."
func main() {
ctx := context.Background()
sheetService, err := sheets.NewService(ctx)
if err != nil {
log.Fatalf("%v", err)
}
sheet, err := sheetService.Spreadsheets.Get(spreadsheetId).Do()
if err != nil {
log.Fatalf("%v", err)
}
fmt.Printf("Sheet title: %s\n", sheet.Properties.Title)
}
$ gcloud auth application-default login
$ go run main.go
Unable to get Spreadsheets. googleapi: Error 403: Request had insufficient authentication scopes.
Details:
[
{
"@type": "type.googleapis.com/google.rpc.ErrorInfo",
"domain": "googleapis.com",
"metadata": {
"method": "google.apps.sheets.v4.SpreadsheetsService.GetSpreadsheet",
"service": "sheets.googleapis.com"
},
"reason": "ACCESS_TOKEN_SCOPE_INSUFFICIENT"
}
]
More details:
Reason: insufficientPermissions, Message: Insufficient Permission
スコープが違うっぽいのでスコープをつけてみる。
これを真似しようと思ったが sheets.NewService
の中でスコープが書いてあったのでこれを使ったほうがいいんじゃないだろうか?
https://github.com/googleapis/google-api-go-client/blob/main/sheets/v4/sheets-gen.go#L122
こうなった。
$ gcloud auth application-default login --scopes "https://www.googleapis.com/auth/drive,https://www.googleapis.com/auth/drive.file,https://www.googleapis.com/auth/drive.readonly,https://www.googleapis.com/auth/spreadsheets,https://www.googleapis.com/auth/spreadsheets.readonly,https://www.googleapis.com/auth/userinfo.email,https://www.googleapis.com/auth/cloud-platform,openid"
Quota projectが云々というのが出てきてしまったので、デフォルトのプロジェクトをやめてコードで書くことにしてみる。これ良さげだなあ。
gcloud にカレントプロジェクトを設定しない派 - ぽ靴な缶
sheetService, err := sheets.NewService(ctx, option.WithQuotaProject(gcpProjectID))
$ go run main.go
Sheet title: ワイワイ
これでOK。
ライブラリがデフォルトのクレデンシャルを読みにいって読めているので、Workload Identityになっても同じようにできるはず。認証情報を持たなくてよくなって便利。