6
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Google Cloud APIの認証設定

Last updated at Posted at 2021-04-21

はじめに

Rails初学者です。GCのStorageとAPIを使用したアプリケーションをHerokuにデプロイする際、認証設定に苦労したのでメモを書き留めておきます。

【使用環境】
・MacOS BigSur
・Ruby 2.6.5, Ruby on Rails 6

GCPのサービスアカウントについて

サービスアカウントを作成するとjson形式の鍵ファイルをダウンロードでき、そのファイルパスを環境変数GOOGLE_APPLICATION_CREDENTIALSに設定することで認証ができます。

export GOOGLE_APPLICATION_CREDENTIALS="/home/user/Downloads/my-key.json"

しかし、この鍵ファイルをGitやHerokuに渡すわけには行きません。

また、公式ドキュメントにありますが、開発環境と本番環境ではサービスアカウントを使い分ける必要があるようです。そのため、Rails 6からサポートされたMulti environment credentialsでそれぞれの秘密鍵情報を記載しました。

Multi environment credentialsの設定

credentialsファイルから読み込む設定

config/storage.yml
google:
  service: GCS
  credentials:
    type: "service_account"
    project_id: <%= Rails.application.credentials.dig(:gcs, :project_id) %>
    private_key_id: <%= Rails.application.credentials.dig(:gcs, :private_key_id) %>
    private_key: <%= Rails.application.credentials.dig(:gcs, :private_key).dump %>
    client_email: <%= Rails.application.credentials.dig(:gcs, :client_email) %>
    client_id: <%= Rails.application.credentials.dig(:gcs, :client_id) %>
    auth_uri: "https://accounts.google.com/o/oauth2/auth"
    token_uri: "https://oauth2.googleapis.com/token"
    auth_provider_x509_cert_url: "https://www.googleapis.com/oauth2/v1/certs"
    client_x509_cert_url: <%= Rails.application.credentials.dig(:gcs, :client_x509_cert_url) %>
  project: <%= Rails.application.credentials.dig(:gcs, :project) %>
  bucket: <%= Rails.application.credentials.dig(:gcs, :bucket) %>

次のコマンドで本番環境用のcredentialsファイルを作成

% bundle exec rails credentials:edit --environment production

configディレクトリ内にcredentialsというディレクトリが作成され、設定ファイルとキーファイルが対で生成されます。
config
 ∟credentials
  ∟ production.key
  ∟ production.yml.enc
 ∟ master.key
 ∟ credentials.yml.enc

設定ファイルは暗号化されているため、次のコマンドでviを使用して編集します。

% EDITOR="vi" bin/rails credentials:edit --environment production
config/credentials/production.yml.enc
secret_key_base: ******
gcs:
  project_id: ******
  private_key_id: ******
  private_key_id: ******
  private_key: "-----BEGIN PRIVATE KEY-----\n******************
***************************************************************
*********************************\n-----END PRIVATE KEY-----\n"
  client_email: ******@******.iam.gserviceaccount.com
  client_id: ******
  client_x509_cert_url: https://www.googleapis.com/robot/v1/metadata/x509/******.iam.gserviceaccount.com
  project: ******
  bucket: ******

secret_key_baseは元々のcredentials.yml.encと同じ。
サービスアカウントを作成して、ダウンロードしたjson形式の鍵ファイルの中に記載されている各項目を書いていきます。private_keyはとても長く改行文字を含んでいるためダブルクォーテーション(”)で囲みます。

そして、production.keyの中身をHerokuに環境変数 RAILS_MASTER_KEYとして保存します。

% heroku config:set RAILS_MASTER_KEY=`cat config/credentials/production.key`

これでいけるかと思いきや

GCSへのデータアップロードは出来るのですが、APIにリクエスト送信すると「認証できないよ」というエラーが。結局、環境変数GOOGLE_APPLICATION_CREDENTIALSを読み込めないと駄目なのか。

いろいろ調べた中で、次の方法を試しました。

まず、Herokuに任意の名前で環境変数を作成、鍵ファイルの中身を保存する。

% heroku config:set GOOGLE_CREDENTIALS="$(< /PATH/TO/my-key.json)"

次に、appディレクトリ内に空のjsonファイルを作成し、そのjsonファイル内に先程の環境変数を出力するという記述を.profileファイル内に書き込む。
aplicationディレクトリ
 ∟app
  ∟gcp_key.json
 ∟**.profile**

gcp_key.json
.profile
echo ${GOOGLE_CREDENTIALS} > /app/gcp_key.json

最後に、Herokuに環境変数GOOGLE_APPLICATION_CREDENTIALSにjsonファイルパスを設定。

% heroku config:set GOOGLE_APPLICATION_CREDENTIALS=/app/gcp_key.json

.profileに記述したコマンドは、Herokuのアプリケーションを格納するコンテナ(Dyno)が起動すると同時に実行されるとのこと。

ここまでの設定で漸く本番環境でも期待の動作をしてくれました。

補足 サービスアカウントのロール(権限)について

オーナー、編集者、閲覧者といった基本ロールの他に、膨大な数のロールが用意されています。基本ロールは設定権限が多いため、本番環境には使用するなとドキュメントにはあったものの、どれを選んで良いものか。
今回、色々と試行した中では「サービスアカウントユーザー」(オペレーションをサービスアカウントとして実行)と「ストレージ管理者」(GCSリソースの全てを管理)の2つを選んで上手く行きましたが、今後不具合などあれば加筆します。

6
3
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?