30歳からのプログラミング

30歳無職から独学でプログラミングを開始した人間の記録。

gcloud auth application-default login は何をしているのか

dbt でデータウェアハウスとして BigQuery を使う際、ローカル開発においては OAuth 方式を使うことが推奨されている。
そしてその場合はgcloud auth application-default loginコマンドを実行する必要がある。

確かにこのコマンドを実行すると BigQuery との接続が上手くいきローカルで開発できるようになる。

しかしこのコマンドは、具体的には何をしているのか。gcloud auth loginとは何が違うのか。何も分かっていなかったので調べてみた。

この記事の内容は、以下の環境で動作確認している。

  • npm パッケージ
    • @google-cloud/storage@7.14.0
  • dbt
    • dbt-core@1.9.1
    • dbt-bigquery@1.9.0

Application Default Credentials

gcloud auth application-default loginについて理解するためにはまず Application Default Credentials (以下 ADC)という概念について理解したほうがよい。

ADC とは、 Google Cloud のクライアントライブラリが認証情報を取得するための仕組み。

クライアントライブラリは Google Cloud の API を叩くためのツールだが、当然ながら認証情報がなければ API を叩くことはできない。
例えば以下はproject-x-123456プロジェクトにある Cloud Storage のバケット一覧を表示するコードだが、クライアントライブラリである@google-cloud/storageに認証情報を渡さなければ動作しない。

// bucket.js
const { Storage } = require("@google-cloud/storage");

const storage = new Storage({ projectId: "project-x-123456" });

async function listBuckets() {
  try {
    const [buckets] = await storage.getBuckets();
    buckets.forEach((bucket) => console.log(bucket.name));
  } catch (err) {
    console.error("Error:", err);
  }
}

listBuckets();

例えば以下のようにStorageインスタンスを作る際に認証情報を渡すと動作する(この例ではkeyFilenameにサービスアカウントキーのパスを渡している)。

const storage = new Storage({
  projectId: "project-x-123456",
  keyFilename: "project-x-sa-key.json",
});

だが ADC の仕組みを利用すれば、コードのなかに認証情報に関する情報を書くことなく、クライアントライブラリに認証情報を渡すことができる。

ADC は特定の順序で認証情報を検索し、最初に見つかった認証情報をクライアントライブラリに提供する。
最後まで認証情報が見つからなかった場合は、以下のようにエラーになる。

$ node bucket.js
Error: Error: Could not load the default credentials. Browse to https://cloud.google.com/docs/authentication/getting-started for more information.

GOOGLE_APPLICATION_CREDENTIALS

ADC はまず最初に、環境変数GOOGLE_APPLICATION_CREDENTIALSに入っている値を使おうとする。

この環境変数に認証情報の JSON ファイルの場所を設定しておくことで、そのファイルの内容がクライアントライブラリに渡される。
「認証情報の JSON ファイル」として使えるものはいくつかあるが、今回はサービスアカウントキーを使う。

$ export GOOGLE_APPLICATION_CREDENTIALS=project-x-sa-key.json

この状態でbucket.jsを実行するとproject-x-123456にあるバケットbucket-aが表示される。

$ node bucket.js
bucket-a

GOOGLE_APPLICATION_CREDENTIALSを unset すると、bucket.jsは再び失敗するようになる。

$ unset GOOGLE_APPLICATION_CREDENTIALS

$ echo ${GOOGLE_APPLICATION_CREDENTIALS-none}
none

$ node bucket.js
Error: Error: Could not load the default credentials. Browse to https://cloud.google.com/docs/authentication/getting-started for more information.

~/.config/gcloud/application_default_credentials.json

GOOGLE_APPLICATION_CREDENTIALSに値が入っていなかった場合 ADC は~/.config/gcloud/application_default_credentials.jsonを使おうとする。
そして~/.config/gcloud/application_default_credentials.jsonを用意するためのコマンドが、gcloud auth application-default loginなのである。

gcloud auth application-default loginを実行するとウェブブラウザでページが開くので、その内容に沿って操作を行うと、選択したアカウントに基づき以下の形式の~/.config/gcloud/application_default_credentials.jsonが作られる。

{
  "account": "",
  "client_id": "***.apps.googleusercontent.com",
  "client_secret": "***",
  "refresh_token": "***",
  "type": "authorized_user",
  "universe_domain": "googleapis.com"
}

そうするとbucket.jsが再び成功するようになる。

$ node bucket.js
bucket-a

gcloud auth application-default revokeを実行すると~/.config/gcloud/application_default_credentials.jsonは消える。

このように、gcloud auth application-default loginはあくまでも ADC 用の認証情報を用意するためのコマンドであり、gcloudコマンドやbqコマンドを実行するための認証を行うgcloud auth loginとは別のものである。
gcloud auth loginについては以下の記事で詳しく書いた。

numb86-tech.hatenablog.com

dbt での挙動

dbt と BigQuery を接続させるために必要な認証情報も ADC を使って渡すことができる。
冒頭に貼ったドキュメントに書かれているようにgcloud auth application-default loginを使ってもよいが、ここまで書いてきたようにGOOGLE_APPLICATION_CREDENTIALSが設定されている場合はそちらが優先されるので注意する。

参考資料