GCPにおけるサーバサイド暗号化

#はじめに
GCPにおける暗号化の全体像は以下になります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/78184/1e3c6aad-86ae-e9a3-48f0-7d7c0c076b7e.png)

一般的に暗号化は、データの転送中(in transit)の暗号化とデータ保存時(at rest)の暗号化に分類されます。データ保存時(at rest)の暗号化は、データを暗号化する場所によりクライアントサイド暗号化、サーバサイド暗号化に分類できます。

ここからは、サーバサイド暗号化について記載します。

#本記事における用語の定義
ユーザ：クラウドの利用者
顧客：ユーザと同義、GCPのマニュアルでは、Customer Managed keyを顧客管理鍵と訳しているため、鍵の名称にはユーザではなく顧客を使用する

#GCPにおけるサーバサイド暗号化の種類

GCPにおけるサーバサイド暗号化の種類は、Google のデフォルトの暗号化、顧客管理鍵による暗号化、顧客管供鍵による暗号化の3種類あります。

Google のデフォルトの暗号化は、Googleが暗号鍵を管理します。
顧客管理鍵(CMEK)による暗号化は、ユーザがCloud KMSを使用して鍵を管理します。
顧客提供鍵(CSEK)による暗号化は、ユーザ自身が鍵を作成し管理します。

#GCPにおけるサーバサイド暗号化の方法
GCPでは、AWSなど他のクラウドベンダーと同じようにEnvelop encryptionという仕組みをつかい鍵を管理しています。
Envelop encryptionとは、ユーザがデータを暗号化する鍵を管理(有効化、無効化、ローテションなど)するのではなく、データを暗号化する鍵を別の鍵で暗号化し、その鍵を管理する仕組みになります。
https://cloud.google.com/kms/docs/envelope-encryption

データを暗号化する鍵をDEK(Data Encryption Keys)、DEKを暗号化する鍵をKEK(Key Encryption Keys)と呼びます。
なぜ、直接DKEを管理せずEnvelop encryptionという仕組みを使うのかというと、GCPではデータは全てデフォルトで暗号化されて保存されることもあり、暗号鍵が膨大な数になり、直接DEKを管理することは運用が煩雑になるため、鍵の用途ごとにレイヤーを分けて、一元的に鍵(KEK)を管理できる仕組みとしてEnvelop encryptionを使用していいます。
また、DEKはデータの近くに保存され、ネットワーク経由でデータ複合化処理を行う必要がないため、パフォーマンス的なメリットもあります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/78184/7bcbfed9-db2e-527f-be6a-1b2f976ffdd9.png)

https://cloud.google.com/kms/docs/envelope-encryption

さらに、KEKはさらにKMS Master Key/Root KMS Master keyで暗号化され保存されます。詳しくは以下のホワイトペーパーをご覧ください。
https://cloud.google.com/security/encryption-at-rest/default-encryption?hl=ja

Google のデフォルトの暗号化、顧客管理鍵による暗号化、顧客提供鍵による暗号化で直接管理する鍵は、KEKになります。DEKに関しては、Googleが自動で生成し、ローテーション、無効化といった管理をユーザに対して透過的に行います。

KEKで暗号化できるサイズは、64 KiBとなっており、64KiBより地位なサイズのデータであれば暗号化することも可能です。ただ、Envelop encriptionの仕組みとしてKEKはDEKを暗号化する鍵であるため、サイズの小さなデータを暗号化する場合は、Secret managerの利用も検討ください。
https://cloud.google.com/secret-manager/docs

Secret managerの上限サイズも64KiBになります。
https://cloud.google.com/secret-manager/quotas?hl=ja

#Google のデフォルトの暗号化
Google のデフォルトの暗号化は、Googleがサービスごとに準備しているKEKを使って暗号化する手法です。KEKの管理は、GoogleのInternal KMSを利用します。
https://cloud.google.com/security/encryption-at-rest/default-encryption?hl=ja

デフォルトの暗号化の場合、Cloud Datastore、App Engine、Cloud Pub/Sub に保存されるデータの場合、複数のユーザで同じ DEK でが使われる可能性があります。
https://cloud.google.com/security/encryption-at-rest/default-encryption

#顧客管理鍵(CMEK)による暗号化
顧客管理鍵(CMEK)による暗号化は、Cloud KMSを使用して、ユーザがKEKを管理する手法です。
Cloud KMSでは、KEKを利用者側で管理することが可能です。

Cloud KMSは、Keyring/Location/Key(KEK)/Versionといった概念を理解する必要があります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/78184/2dc0b4ef-3b97-6622-4a29-94b563ac8f83.png)
https://cloud.google.com/kms/docs/envelope-encryption

Keyringは、複数のKEKをまとめて管理するための入れ物です。Keyringレベルで認可設定を与えることが可能です。リソースレベルの認可設定は、IAM Conditionsを使用します。KMSは、Keyring/KEK/KEK versionの3つのレベルで設定できます。

```
projects/project-number/locations/location-id/keyRings/keyring-id
projects/project-number/locations/location-id/keyRings/keyring-id/cryptoKeys/cryptokey-id
projects/project-number/locations/location-id/keyRings/keyring-id/cryptoKeys/cryptokey-id/cryptoKeyVersions/cryptokeyversion-id
```

https://cloud.google.com/iam/docs/conditions-resource-attributes

Locationは、KEKを使用する場所の指定になります。Keyringを作成する際に指定します。暗号化する場合、KEKを使用して暗号化する対象のリージョンがLocationで指定する場所と一致してる必要があります。例えばGSCをCMEKで暗号化する場合、GCSのリージョンがus-central1の場合、KeyringのLocationもus-central1である必要があります。またlocationはGlobalが設定できますが、GKEなどはglobalのKEKが指定できないといった制限もあります。

>
GKE では、Cloud KMS の global リージョンの使用はサポートされていません。
https://cloud.google.com/kubernetes-engine/docs/how-to/encrypting-secrets

Key(KEK)は、前述の通りDEKを暗号化するための鍵になります。

Versionは、KEKのバージョンになります。Cloud KMSでKEKを作成管理する場合は、自動ローテーション設定が可能です。

Cloud KMSの注意点としては、一度作成したKeyring,Key(KEK)は削除できません。削除可能なものは、Versionのみです。Vesionを削除した場合、24時間後に削除されます。24時間以内であればリストアできます。
>
鍵と鍵リングを削除できないのはなぜですか？
リソース名の競合を防ぐため、キーリングと鍵のリソースは削除できません。鍵バージョンも削除できませんが、鍵バージョンのマテリアルを破棄することによって、リソースを使用できないようにすることができます。詳細については、オブジェクトの存続期間をご覧ください。
https://cloud.google.com/kms/docs/faq?hl=ja

Versionは、無効化と削除が可能です。該当バージョンを無効化、削除すると該当バージョンのKEKで暗号化したDEKで暗号化したデータにアクセスできなくなります。KEKを無効化して暗号化したGCSバケットからファイルをダウンロードを試みた場合、以下の様なエラーになります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/78184/d2a1d3f9-95ea-7469-bc3c-3185ce749518.png)

###Cloud KMSのKEKの種類、目的、アルゴリズム、保護レベル
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/78184/b81c98a3-4ca4-8a92-f451-b194d70cf856.png)

KEKの種類は、「生成した鍵」「インポートした鍵」「外部で管理する鍵」の3つあります。
「生成した鍵」はGoogle側でKEKを作成しCloud KMSをつかってユーザが管理する方式です。
「インポートした鍵」は、KEKをユーザが作成し、インポートJobを作りCloud KMSにインポートし管理します。ユーザがKEKを作成するためCSEKと混同しがちですが、Cloud KMSで管理するため、Cloud KMSのマニュアルとしては、CMEKの一種になります。
「外部で管理する鍵」は、Cloud EKMを使って外部の鍵管理パートナーシステム上のKEKを使う仕組みです。
2020/6現在サポートされているパートナーは、FortanixとIonicになります。
https://cloud.google.com/kms/docs/ekm#supported

Cloud KMSでKEKを管理する場合、KEKの目的、アルゴリズム、保護レベルが設定可能です。
https://cloud.google.com/kms/docs/algorithms?hl=ja

KEKの目的(=暗号鍵の種類)としては、3つ選択いただくことが可能です。対象鍵暗号化、非対称鍵暗号化、非対称鍵署名です。
アルゴリズムは、KEKの目的ごとにそれぞれアルゴリズムが選択可能です。例えば、非対称鍵署名の場合は、ECDSA on the P-256 Curve with a SHA-256 digestやECDSA on the P-384 Curve with a SHA-384 digestが選択可能です。

KEKの保護レベルとしては、ソフトウェアとハードウェアが選択可能です。
保護レベルは暗号オペレーションをどのように実施するかを指定します。一度作成したKEKは保護レベルを変更することはできません。
https://cloud.google.com/kms/docs/algorithms

#顧客提供鍵(CSEK)による暗号化
顧客提供鍵(CSEK)による暗号化は、KEKをユーザが作成し管理する方式です。
GCEで顧客提供鍵(CSEK)でDEKを暗号化し、DEKでディスクに保存されるデータを暗号化できます。インスタンスを一度停止し再度起動した場合、再度顧客提供鍵(CSEK)の入力が必要になります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/78184/d4b9f9de-3747-3887-b222-2110277ce85f.png)

https://cloud.google.com/security/encryption-at-rest/customer-supplied-encryption-keys?hl=ja

#それぞれの方式のGoogle cloud consoleのマッピング
GCEの場合は、以下のような形になります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/78184/8d54990d-e52e-e7b5-4f30-d7308deb56ee.png)

#デフォルト暗号化と顧客管理鍵(CMEK)と顧客提供鍵(CSEK)の違い
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/78184/cd1f18e0-196b-2211-435c-f5ef1a181122.png)

当然ながらKEKの管理方法がことなります。
また、それぞれの暗号鍵の管理方法式をサポートしているGCPサービスが異なります。
DEKの取り扱いについては同じになります。
KEKのバージョンについては、バージョンの上限について差があります。

*1 https://cloud.google.com/security/encryption-at-rest/default-encryption?hl=ja
*2 https://cloud.google.com/kms/quotas?hl=ja