Cloud KMS + Cloud Storageの利用には大きく分けて3種類の方法があった

エンベロープ暗号化や秘密情報の扱いはそもそもそんなに得意じゃないので大間違いしている可能性があります。間違ってたら指摘お願いします。

※ Cloud KMSについては Key Management Serviceについて勘違いしていたこと - あーありがち(2018-10-21) に一部メモがあります。

まとめ

Cloud KMS + Cloud Storage の組み合わせには大きく分けて以下の3つの方法がある。

  1. Bucket のデフォルト暗号化キーを KMS Key にする
  2. Object 保存時に KMS Key Name をオプションで渡す
  3. 独自に KMS Key で暗号化して通常通り保存する

基本的に Cloud KMS のドキュメント上で説明されているのは 3 の方法。

1 と 2 の方法については Cloud KMS の API を enable にして KMS と Storage に同じアカウントでアクセスできるようにする必要がある。暗号化、複合は透過的に行われ、意図的に暗号化済みのデータを取得する方法はない。KMS Key が無効化されたら Object そのものにアクセスできなくなる。

Storageの自動機能の利用には注意が必要

上の 1, 2 は Storage + KMS という Google の提供する技で、これは簡単に言うと KMS Key Name の指定さえできていれば暗号化/複合処理は完全に Google におまかせになる、つまり自動で透過的に適用されるということ1

この場合、Object のメタデータの一つに KMS Key Name が入るので、鍵とデータの組み合わせは気にする必要がない。

ただし、利用の際には以下のような制限が生まれる。

  • Bucket の Region と Key の Location の組み合わせには制限がある(例えば asia な Bucket に global な Key を組み合わせることはできない)
  • KMS と Storage の両方に同一のアカウントで認証を要求することになるので厳密なことを言うと権限がややルーズ
  • Key が無効化されたら Object にはメタデータ含めてアクセスできない(読み取りはできるが中身が分からない、ではなく、読み取りもできない。ただし Key Name は取得できる。)

特に Bucket レベルの制限はバツンと一律アクセスできなくなってしまうので、いろいろな利用方法の混ざった暗号化キーやシークレットに対しておおもとの KMS KEK Key で有効/無効を切り替えるといった使い方は難しそう。

となると、あくまで

  • KMS へのアクセスを外部に許可するわけではなく、管理が容易
  • シークレットの利用方法は同一
  • キーのローテーションはするが無効化は原則しない

以上のような運用に向いている気がする。

例えばマルチテナントのデータをテナントごとに暗号化するキーを分けたうえでその暗号化キーの暗号化に使う KEK がローテートされる、みたいな使い方をすると開発環境の準備も楽そうだし、よさそうに思える。2

自前で暗号化する場合は自前で対応表に基づく自動化を行うべし

Storage の自動暗号化の恩恵に与らない場合、

  • KMS Key Name
  • 暗号化されたシークレット / DEK

の間を紐づける情報は Google Cloud のどこにも残らない。あくまで KMS Key とデータを呼び出したプログラムだったり紐づけて作業を行う作業者の頭の中だったり terminal の履歴の中だけに残るものとなる。

そこでおそらく基本的にはこのデータの暗号化/複合の処理はコードで閉じ込めてしまうわないと維持が難しくなってしまうので、まずは対応表とそれを利用した暗号化/複合処理のコードの準備が必要になる。

上に挙げた例の反対、

  • KMS へアクセスするユーザー(プログラム)の場所は様々
  • シークレットの利用方法が同一でない
  • キー単位で無効化するなどシークレットの利用を制御したい

といった要件が入る場合はこのような準備が必要と考えるのがよさそうだ。

  1. Bucket レベルの場合は指定はリソース ID になるが、同じこと。その場合はバージョンまで含めたリソース ID にならないように注意 

  2. データの暗号化キーが KMS と自動連携する Storage で管理されるイメージ。キーは DB に入っていない方が安心な感じもする。 

More