Google Cloud Platform

Google Cloud のサービス アカウント キーを安全に管理する

Google Cloud Platform(GCP)は、サービス アカウント キーの堅牢な管理機能を提供することで、権限を持ち、適切に認証されたエンティティだけが GCP リソースにアクセスできるようにしています。

アプリケーションが GCP 上だけで実行されるのであれば、サービス アカウント キーの管理は簡単です。GCP から離れることはないので、キーのローテーションなどは GCP が自動的に行ってくれます。

しかし、多くのアプリケーションは、デベロッパー所有のローカル PC、オンプレミス データベース、他のパブリック クラウドなどさまざまな環境で実行されます。そうなると、キーの安全な管理は簡単ではなくなります。

複数の環境を行き来する過程でサービス アカウント キーを無防備な状態に置かないようにすることは、アプリケーションのセキュリティを維持するうえで最も重要なポイントです。この投稿では、与えられたアプリケーション環境で適切にキーを管理するためのベスト プラクティスを紹介します。

サービス アカウントの基礎知識

アプリケーションを使って Cloud Platform API にアクセスする場合は、サービス アカウントの使用をお勧めします。サービス アカウントは、アプリケーションが他の GCP サービスへのアクセス時に使用できる認証情報を提供します。サービス アカウントに対しては、GCP、オンプレミス環境、他のクラウドで実行されているコードからアクセスできます。

GCP でコードを実行しているときには、サービス アカウントのセットアップは単純です。たとえば Google Compute Engine をターゲット環境とする場合は、次のような手順になります。

このようにサービス アカウントを準備すると、その管理下でインスタンスを起動できます(既存のインスタンスを一時的に停止して、別のサービス アカウントの管理下で改めて実行することも可能です)。

  • 次に、アプリケーションの記述に使用されている言語用のクライアント ライブラリをインストールします(SDK も使えますが、クライアント ライブラリのほうがわかりやすくお勧めできる方法です)。これで、アプリケーションは、そのインスタンスのサービス アカウントの認証情報を使って認証を受けられるようになります。Compute Engine インスタンスで実行しているので、キーをダウンロードする必要はありません。GCP が自動的にキーを作成し、ローテーションします。

GCP 以外の環境でのサービス アカウント キーの保護

GCP 以外の環境でアプリケーションを実行する場合も上記の手順に従いますが、クライアント ライブラリについては実行環境の仮想また物理マシンにインストールします。

サービス アカウントを作成するときは、権限を最小限に抑えるという原則に特に忠実に従うようにしてください。この原則はどこで実行する場合でも重要なことですが、認証情報をダウンロードするときには特に重要です。そうしないと、GCP によるキー管理を受けられず、サービス アカウントが誤って公開されるリスクが高くなります。

さらに、サービス アカウントのための新しいキーのペアを作り、秘密鍵をダウンロードする必要もあります(Google は秘密鍵を保持しません)。外部鍵の場合、秘密鍵のセキュリティ保持やキーのローテーションなどの管理オペレーションはお客様の責任になりますのでご注意ください。

アプリケーションから Google Cloud API を呼び出せるようにするには、外部鍵をアプリケーションが使用できることが必要です。これは、Google API クライアント ライブラリを使うことで容易になります。Google APIクライアント ライブラリは、アプリケーションから呼び出されると、単純な形で認証情報を得るために Application Default Credentials を使います。GCP 以外の環境でアプリケーションを実行するときに、キーをダウンロードした位置を GOOGLE_APPLICATION_CREDENTIALS 環境変数に格納しておけば、そのキーに紐付けられたサービス アカウントを使って認証を受けられます

サービス アカウント キーをダウンロードするときのベスト プラクティス

GCP リソースにアクセスするのに必要なサービス アカウント キーが手に入ったら、そのキーを適切に管理する必要があります。ここからは、本来の使用範囲外でキーが公になることを防ぐベスト プラクティスに焦点を当てます。

1. ローカル環境での開発用にキーをダウンロードする場合は、そのキーに本番リソースへのアクセスが許可されていないことを確認します。


2. 次に示す IAM Service Account API のメソッドに使ってキーをローテーションします。

  • serviceAccounts.keys.create()
  • 古いキーを新しいキーに入れ替える
  • serviceAccounts.keys.delete()
3. キーを毎日ローテーションするプロセスを実装することを考慮し、新しいキーを毎日ダウンロードできるストレージ バケットをデベロッパーに提供します。


4. serviceAccounts.keys.list() メソッドもしくは Cloud Console のログ ビューア ページを使用して、サービス アカウントとキーを監査します。


5. サービス アカウントの Service Account Actor と Service Account User の役割を持つ人はすべてのリソースにフルアクセスできるため、該当する人間をごく一部だけに絞り込みます。


6. ローカル環境での開発では常にクライアント ライブラリと GOOGLE_APPLICATION_CREDENTIALS 環境変数を使用するようにします。


7. デベロッパーが外部ソースコード リポジトリにキーを送ることを禁止します。


8. 外部リポジトリにキーが格納されていないか定期的にスキャンし、見つかった場合には是正措置を講じます。

次に、このベスト プラクティスを実践に移す方法を紹介しましょう。

キーのローテーション

Keyrotator は Python で書かれたシンプルな CLI ツールで、そのまま使用することも、あるいはサービス アカウントのローテーション プロセスのベースとして使用することもできます。このツールを管理インスタンス上で cron ジョブとして実行し、(たとえば深夜に)新しいキーを Cloud Storage に格納して、それをデベロッパーが毎朝ダウンロードできるようにします。

この場合、キーを格納する Cloud Storage バケットへのアクセス制御がきわめて重要になります。その方法は次のとおりです。

  1. 共有リソース用の専用のプロジェクトを作成します。
  2. 専用プロジェクト内にバケットを作成します。パブリック アクセス可能に設定してはなりません。
  3. キーを毎日ダウンロードする必要のあるデベロッパーのためのグループを作成します。
  4. このデベロッパー グループに対し、ストレージ バケットを持つプロジェクトの storage.objectViewer の役割を与え、Cloud IAM を使ったバケットの読み出しアクセスを許可します。

もっと管理を強化したい場合は、Cloud Storage での秘密管理のために Google Cloud Key Management Service を使います。

外部リポジトリへのキーのコミットを防止する

コードとともにキーを管理しなくても済むようにすべきですが、誤ってコードとともにキーが外部にプッシュされることはありえます。

これを避けるための 1 つの方法は、外部リポジトリを使わないことに決め、外部リポジトリが使用できないようなプロセスを設けることです。GCP はそのためにプライベートな git リポジトリを提供しています。

キーが外部リポジトリに送信されるのを防ぐ仕組みを組み込む方法もあります。git-secrets はこの目的のために使えるオープンソース ツールで、インストール時に git のフックになるように設定します。

git-secrets は、‘git commit’ コマンドを実行したときに自動的に実行されます。

git-secrets を使うには、サービス アカウント キーと一致するパターンをチェックする必要がありますが、設定はごく簡単です。

サービス アカウント キーを JSON ファイル形式でダウンロードすると、次のようになっています。

  {
 "type": "service_account",
 "project_id": "your-project-id",
 "private_key_id": "randomsetofalphanumericcharacters",
 "private_key": "-----BEGIN PRIVATE KEY-----\thisiswhereyourprivatekeyis\n-----END PRIVATE KEY-----\n",
 "client_email": "keyname@your-project-id.iam.gserviceaccount.com",
 "client_id": "numberhere",
 "auth_uri": "https://accounts.google.com/o/oauth2/auth",
 "token_uri": "https://accounts.google.com/o/oauth2/token",
 "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
 "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/keyname%40your-project-id.iam.gserviceaccount.com"
}

サービス アカウント キーを手に入れるには、‘private_key_id’ や ‘private_key’ などのキー名からローカル git フォルダのサービス アカウント ファイルを探すことになるので、次のパターンを登録します。

  git secrets --add 'private_key'
git secrets --add 'private_key_id'

‘git commit’ コマンドを実行したときにこのパターンが見つかるとエラー メッセージが表示され、修正しないかぎりコードを送ることはできなくなります。

nI1cNClBRfcknrj4fXo_htMxit5dbJApJCeUVGSS18UHAYsFejBGN1EAMAgjWHmS1OrpAXms2Pt6Klme-yA_8nWNRjadAFAVgAbLIYgCCEodcVyXimivdG1akpkvFv2QLb2ia4Zvt7dr.PNG
秘密鍵を含むファイルをデベロッパーが送信しようとしたときに表示される画面(この秘密鍵は削除済み)

外部リポジトリに格納されたキーのスキャン

git-secrets を補完する Truffle Hog というオープンソース ツールもあります。Truffle Hog は、エントロピー分析(Shannon エントロピー)を使って外部リポジトリの履歴情報を検索し、アップロードされた可能性のあるキーを見つけ出します。

まとめ

この投稿では、アプリケーションが GCP だけで実行されるか、ローカル環境や他のクラウドで実行されるかにかかわらず、アプリケーションの認証に使用されるサービス アカウント キーの安全性を強化する方法を説明しました。予期せぬキーの公開を防いだり、アプリケーション リソースにアクセスするユーザーを管理したりするため、ここで説明したベスト プラクティスを活用してください。GCP の認証、認可(権限授与)の詳細については Authentication Overview のページを参照してください。

* この投稿は米国時間 7 月 19 日、Cloud Solutions Architect である Grace Mollison によって投稿されたもの(投稿はこちら)の抄訳です。

- By Grace Mollison, Cloud Solutions Architect