環境変数 GOOGLE_APPLICATION_CREDENTIALS に設定する JSON ファイルをアプリケーション実行時に動的生成する

Firebase Authentication のサーバーサイドでサービスアカウントキーが含まれる JSON ファイルのパスを環境変数 GOOGLE_APPLICATION_CREDENTIALS に設定しなければならないが、そもそも JSON ファイル自体の置き場に困ったので JSON ファイルの中身を環境変数で渡して JSON ファイルを動的生成する。

環境

  • go version go1.19.3 linux/amd64

本文

Firebase Authentication のサーバーサイドを Docker コンテナでつくろうとしているのだが、「サービスアカウントキーが含まれる JSON ファイルのパスを環境変数 GOOGLE_APPLICATION_CREDENTIALS に設定しなければならない」という点で困った。

JSON ファイルをコンテナに含めるのが一番楽だが、個人的にあまりやりたくない。

そのため JSON ファイルを base64 エンコードした文字列を環境変数で渡し、アプリケーション実行時に JSON ファイルを生成して配置後、JSON ファイルのパスを環境変数 GOOGLE_APPLICATION_CREDENTIALS に設定することにした。

1. JSON ファイルを base64 エンコードする

Linux 環境で base64 コマンドが入っている場合、

base64 firebase.json

みたいな感じでファイルを丸ごと base64 エンコードできる。

出力された文字列を環境変数 GOOGLE_SERVICE_ACCOUNT_JSON に設定する。

なお私の環境では base64 エンコードした文字列には改行が含まれていたが、改行は削除して問題なかった。

base64 エンコードの結果はそれほど長くないので AWS Systems Manager Parameter Store にも設定可能である。

2. JSON ファイルを生成してパスを環境変数にセット

下記のような感じで base64 エンコードされた文字列から JSON ファイルを生成して GOOGLE_APPLICATION_CREDENTIALS に設定できる。

import (
    "os"
    "bytes"
    "encoding/base64"
    "log"
)

func setGoogleApplicationCredentials() error {
    credentialFile := "credentials.json"

	// 環境変数から base64 エンコードされた JSON を読み取ってファイルとして保存する
	serviceAccount := os.Getenv("GOOGLE_SERVICE_ACCOUNT_JSON")
	buf := bytes.NewBufferString(serviceAccount)
	dst := make([]byte, base64.StdEncoding.DecodedLen(buf.Len()))
	_, err := base64.StdEncoding.Decode(dst, buf.Bytes())
	if err != nil {
		return err
	}
	f, err := os.Create(credentialFile)
	if err != nil {
		return err
	}
	defer func() {
		err := f.Close()
		if err != nil {
			log.Fatal(err)
		}
	}()
	_, err = f.Write(dst)
	if err != nil {
		return err
	}
	// Firebase SDK セットアップのために環境変数に JSON へのパスをセット
	return os.Setenv("GOOGLE_APPLICATION_CREDENTIALS", credentialFile)
}

以上