アプリケーション レイヤでのシークレットの暗号化

このページでは、Cloud Key Management Service(Cloud KMS)で管理する鍵を使用して、アプリケーション レイヤで Kubernetes のシークレットを暗号化する方法について説明します。

GKE v1.11.2 以降は、アプリケーション レイヤでシークレットの暗号化を使用する新しいクラスタを作成できます。アプリケーション レイヤでのシークレットの暗号化を既存のクラスタで使用するための更新は、次の GKE バージョンでサポートされています。

  • GKE 1.11: v1.11.9 以降
  • GKE 1.12: v1.12.7 以降
  • GKE 1.13 以降

概要

GKE はデフォルトで、シークレットなどの保存されている顧客コンテンツを暗号化します。GKE では、こうした暗号化の処理と管理が自動的に行われるため、ユーザー側での操作は不要です。

アプリケーション レイヤでシークレットを暗号化すると、機密データ(etcd に格納されているシークレットなど)に対するセキュリティをさらに強化できます。この機能により、Cloud KMS で管理している鍵を使用して、アプリケーション レイヤでデータを暗号化できます。そうすることで、攻撃者が etcd のオフライン コピーにアクセスした場合でもデータの内容を保護できます。

アプリケーション レイヤでのシークレットの暗号化を使用するには、まず Cloud KMS 鍵を作成し、GKE サービス アカウントにその鍵へのアクセス権を付与する必要があります。レイテンシを減らすため、またリソースが複数の障害発生ドメイン間のサービスに依存することを防ぐために、鍵はクラスタと同じロケーションに存在する必要があります。このようにしてから、使用する鍵を指定して新しいクラスタまたは既存のクラスタでこの機能を有効にできます。

エンベロープ暗号化

Kubernetes の KMS プロバイダは、シークレットのエンベロープ暗号化機能を提供します。具体的には、一般的にデータ暗号鍵(DEK)と呼ばれるローカル鍵がシークレットの暗号化に使用されます。DEK 自体は、鍵暗号鍵と呼ばれる別の鍵で暗号化されています。鍵暗号鍵は Kubernetes に保存されません。

エンベロープ暗号化には、主に 2 つの利点があります。

  • 鍵暗号鍵は、すべてのシークレットを再暗号化しなくてもローテーションできます。つまり、パフォーマンスに大きな影響を与えることなく、通常の鍵ローテーションのベスト プラクティスに簡単に従うことができます。

  • Kubernetes に保存されているシークレットは、外部の信頼のルートを利用できます。つまり、ハードウェア セキュリティ モジュールなどの一元的な信頼のルートによってシークレットを保護できるため、攻撃者がオフラインでコンテナにアクセスした場合でもシークレットが取得されることはありません。

GKE のアプリケーション レイヤでのシークレットの暗号化により、シークレットは AES-CBC プロバイダを使用して DEK でローカルに暗号化され、DEK は Cloud KMS で管理する鍵暗号鍵で暗号化されます。

エンベロープ暗号化の詳細については、エンベロープ暗号化をご覧ください。

シークレットを作成した場合

新しいシークレットを作成すると、次のようになります。

  • Kubernetes API サーバーは乱数生成ツールを使用して、シークレットのための一意の DEK を生成します。

  • Kubernetes API サーバーはシークレットを暗号化するために、DEK をローカルで使用します。

  • KMS プラグインは暗号化のために DEK を Cloud KMS に送信します。KMS プラグインはプロジェクトの GKE サービス アカウントを使用して、Cloud KMS への認証を行います。

  • Cloud KMS は DEK を暗号化し、それを KMS プラグインに返送します。

  • Kubernetes API サーバーは暗号化されたシークレットと暗号化された DEK を保存します。平文の DEK はディスクに保存されません。

クライアントが Kubernetes API サーバーからシークレットをリクエストすると、前述のプロセスが逆順で実行されます。

鍵のローテーション

シークレットを暗号化する KEK はローテーションされず、最後までシークレットに使われます。別の KEK がシークレットをラップできるようにするには、KEK をローテーションしてから新しいシークレットを作成します。

たとえば、Secret1 シークレットを作成して保存します。このシークレットが DEK1 で暗号化されて、さらに KEKv1 でラップされます。KEKv1 がローテーションする前に、別のシークレット Secret2 を作成します。Secret2 は独自のキー DEK2 を取得します。KEKv1 を再び使用して DEK を暗号化します。

KEK がローテーションした後で、別のシークレット Secret3 を作成すると、これが DEK3 で暗号化されます。DEK3 が今度は KEKv2 (ローテーションされた KEK)で暗号化されます。

シークレットを暗号化する KEK を手動でローテーションする方法については、シークレットを再暗号化するをご覧ください。

鍵を破棄した場合の対応

GKE でシークレットの暗号化に使用された鍵が Cloud KMS で破棄されると、そのシークレットは利用できなくなります。サービス アカウント トークン ボリューム プロジェクションを使用しない場合、GKE で使用するサービス アカウントもシークレットを使用するため、鍵が破壊されるとこれらは使用できなくなります。これらのアカウントにアクセスできないため、クラスタの起動は失敗します。

鍵を破棄する前にクラスタで現在使用されているか確認することをおすすめします。Cloud KMS での鍵の破棄に関するアラート ポリシーを作成することもできます。

始める前に

  • このトピックの演習を行うには、2 つの Google Cloud Platform プロジェクトが必要です。

    • 鍵プロジェクト: 鍵暗号鍵の作成先。

    • クラスタ プロジェクト: アプリケーション レイヤでのシークレットの暗号化を有効にするクラスタの作成先。

  • 鍵プロジェクトで、Cloud KMS API が有効になっていることを確認します。

    Cloud KMS API の有効化

  • 鍵プロジェクトで、キーリングと鍵を作成するユーザーには次の Cloud IAM 権限が必要になります。

    • cloudkms.keyRings.getIamPolicy
    • cloudkms.keyRings.setIamPolicy

    これらの権限(および他の権限)は、事前定義された roles/cloudkms.admin Cloud Identity and Access Management 役割に付与されています。鍵を管理するための権限の付与に関する詳細については、Cloud KMS のドキュメントをご覧ください。

  • クラスタ プロジェクトで、Google Kubernetes Engine API が有効になっていることを確認します。

    Google Kubernetes Engine API の有効化

  • Cloud SDK がインストール済みであることを確認します。

  • gcloud を最新バージョンに更新します。

    gcloud components update

Cloud KMS 鍵を作成する

キーリングを作成するときは、GKE クラスタのロケーションと一致するロケーションを指定します。

  • ゾーンクラスタは、スーパーセット ロケーションからのキーリングを使用する必要があります。たとえば、ゾーン us-central1-a のクラスタは、リージョン us-central1 の鍵のみを使用できます。

  • リージョン クラスタは、同じロケーションからのキーリングを使用する必要があります。たとえば、リージョン asia-northeast1 のクラスタは、リージョン asia-northeast1 のキーリングで保護する必要があります。

  • GKE では、Cloud KMS global リージョンの使用はサポートされていません。

Google Cloud Platform Console または gcloud コマンドを使用できます。

Console

鍵プロジェクトでキーリングを作成します。

  1. GCP Console で [暗号鍵] ページに移動します。

    [暗号鍵] ページに移動

  2. [キーリングを作成] をクリックします。

  3. [キーリング名] フィールドに、キーリングの名前を入力します。

  4. [ロケーション] プルダウンで、Kubernetes クラスタのロケーションを選択します。[キーリングの作成] ページは次のようになります。

    Google Cloud Platform ウェブ UI のキーリング作成画面

  5. [作成] をクリックします。

次に、鍵を作成します。

  1. GCP Console で [暗号鍵] ページに移動します。

    [暗号鍵] ページに移動

  2. 鍵を作成するキーリングの名前をクリックします。

  3. [鍵を作成] をクリックします。

  4. [キー名] フィールドに、鍵の名前を入力します。

  5. [ローテーション期間] と [開始日] に鍵のローテーション期間と開始時間を設定します。デフォルト値をそのまま使用することもできます。

  6. (省略可)鍵にラベルを追加する場合は、[ラベル] フィールドで [ラベルを追加] をクリックします。

    [鍵の作成] ページは次のようになります。

    Google Cloud Platform ウェブ UI のキー作成画面

  7. [作成] をクリックします。

gcloud

鍵プロジェクトでキーリングを作成します。

gcloud kms keyrings create [RING_NAME] \
    --location [LOCATION] \
    --project [KEY_PROJECT_ID]

ここで

  • [RING_NAME] は、キーリングに付ける名前です。
  • [LOCATION] は、キーリングを作成するリージョンです。
  • [KEY_PROJECT_ID] は、鍵プロジェクト ID です。

鍵を作成します。

gcloud kms keys create [KEY_NAME] \
    --location [LOCATION] \
    --keyring [RING_NAME] \
    --purpose encryption \
    --project [KEY_PROJECT_ID]

ここで

  • [KEY_NAME] は、鍵に付ける名前です。
  • [LOCATION] は、キーリングを作成したリージョンです。
  • [RING_NAME] は、キーリングの名前です。
  • [KEY_PROJECT_ID] は、鍵プロジェクト ID です。

鍵を使用する権限を付与する

クラスタ プロジェクトの GKE サービス アカウントの名前は次のとおりです。

service-[CLUSTER_PROJECT_NUMBER]@container-engine-robot.iam.gserviceaccount.com

ここで、[CLUSTER_PROJECT_NUMBER] は、クラスタ プロジェクト番号です。

サービス アカウントへのアクセスを許可するには、Google Cloud Platform Console または gcloud コマンドを使用します。

Console

GKE サービス アカウントに Cloud KMS 暗号鍵の暗号化 / 復号の役割を付与します。

  1. Google Cloud Platform Console で Cloud Key Management Service 鍵のブラウザを開きます。
    Cloud KMS 鍵のブラウザを開く
  2. 目的の鍵を含むキーリングの名前をクリックします。

  3. 使用する鍵のチェックボックスをオンにします。

    右側のウィンドウの [権限] タブが有効になります。

  4. [メンバーの追加] ダイアログで、アクセス権を付与する GKE サービス アカウントのメールアドレスを指定します。

  5. [役割を選択] プルダウンで、[クラウド KMS 暗号鍵の暗号化 / 復号] を選択します。

  6. [保存] をクリックします。

gcloud

GKE サービス アカウントに Cloud KMS 暗号鍵の暗号化 / 復号の役割を付与します。

gcloud kms keys add-iam-policy-binding [KEY_NAME] \
  --location [LOCATION] \
  --keyring [RING_NAME] \
  --member serviceAccount:[SERVICE_ACCOUNT_NAME] \
  --role roles/cloudkms.cryptoKeyEncrypterDecrypter \
  --project [KEY_PROJECT_ID]

ここで

  • [KEY_NAME] は、鍵の名前です。
  • [LOCATION] は、キーリングを作成したリージョンです。
  • [RING_NAME] は、キーリングの名前です。
  • [SERVICE_ACCOUNT_NAME] は、GKE サービス アカウントの名前です。
  • [KEY_PROJECT_ID] は、鍵プロジェクト ID です。

アプリケーション レイヤでのシークレットの暗号化を有効にする

新しいクラスタの場合

新しいクラスタは、Google Cloud Platform Console または gcloud コマンドを使用して作成できます。

Console

  1. GCP Console で Google Kubernetes Engine のメニューに移動します。

    Google Kubernetes Engine のメニューに移動

  2. [クラスタを作成] をクリックします。

  3. クラスタとノードプールを、必要に応じて構成します。保存する前に、[可用性、ネットワーキング、セキュリティ、その他の機能] を選択します。

  4. [アプリケーション レイヤでのシークレットの暗号化を有効にする] を選択して、Cloud KMS 鍵を作成するで作成したデータベース暗号鍵を選択します。

  5. クラスタの構成を続行して、変更を保存します。

gcloud

アプリケーション レイヤでのシークレットの暗号化をサポートするクラスタを作成するには、作成コマンドの --database-encryption-key パラメータに値を指定します。クラスタ バージョン v1.11.2 以降を使用してください。

gcloud beta container clusters create [CLUSTER_NAME] \
  --cluster-version=latest \
  --zone [ZONE] \
  --database-encryption-key projects/[KEY_PROJECT_ID]/locations/[LOCATION]/keyRings/[RING_NAME]/cryptoKeys/[KEY_NAME] \
  --project [CLUSTER_PROJECT_ID]

ここで

  • [CLUSTER_NAME] は、クラスタに付ける名前です。
  • [ZONE] は、クラスタを作成するゾーンです。
  • [KEY_PROJECT_ID] は、鍵プロジェクト ID です。
  • [LOCATION] は、キーリングのロケーションです。
  • [RING_NAME] は、キーリングの名前です。
  • [KEY_NAME] は、鍵の名前です。
  • [CLUSTER_PROJECT_ID] は、クラスタ プロジェクト ID です。

既存クラスタの場合

既存のクラスタを更新すると、次のいずれかの条件が満たされていれば、アプリケーション レイヤでのシークレットの暗号化を使用できます。

  • クラスタ バージョンが v1.11.9 以降で v1.12.0 未満である。
  • クラスタ バージョンが v1.12.7 以降である。

Google Cloud Platform Console または gcloud コマンドを使用できます。

Console

アプリケーション レイヤでのシークレットの暗号化をサポートするようクラスタを更新するには:

  1. GCP Console で Google Kubernetes Engine のメニューに移動します。

    Google Kubernetes Engine のメニューに移動

  2. 変更するクラスタの [編集] アイコンをクリックします。アイコンは鉛筆の形をしています。

  3. [アプリケーション レイヤでのシークレットの暗号化] を有効にして、Cloud KMS 鍵を作成するで作成したデータベース暗号鍵を選択します。

  4. [保存] をクリックします。

gcloud

アプリケーション レイヤでのシークレットの暗号化を既存のクラスタで有効にするには、次のコマンドを実行します。

gcloud beta container clusters update [CLUSTER_NAME] \
  --zone [ZONE] \
  --database-encryption-key projects/[KEY_PROJECT_ID]/locations/[LOCATION]/keyRings/[RING_NAME]/cryptoKeys/[KEY_NAME] \
  --project [CLUSTER_PROJECT_ID]

ここで

  • [CLUSTER_NAME] は、クラスタに付ける名前です。
  • [ZONE] は、クラスタを作成するゾーンです。
  • [KEY_PROJECT_ID] は、鍵プロジェクト ID です。
  • [LOCATION] は、キーリングのロケーションです。
  • [RING_NAME] は、キーリングの名前です。
  • [KEY_NAME] は、鍵の名前です。
  • [CLUSTER_PROJECT_ID] は、クラスタ プロジェクト ID です。

アプリケーション レイヤでのシークレットの暗号化を無効にする

既存のクラスタを更新すると、次のいずれかの条件が満たされていれば、アプリケーション レイヤでのシークレットの暗号化の使用を停止できます。

  • クラスタ バージョンが v1.11.9 以降で v1.12.0 未満である。
  • クラスタ バージョンが v1.12.7 以降である。

Google Cloud Platform Console または gcloud コマンドを使用できます。

Console

  1. GCP Console で Google Kubernetes Engine のメニューに移動します。

    Google Kubernetes Engine のメニューに移動

  2. 変更するクラスタの [編集] アイコンをクリックします。アイコンは鉛筆の形をしています。

  3. [アプリケーション レイヤでのシークレットの暗号化] を無効にします。

  4. [保存] をクリックします。

gcloud

アプリケーション レイヤでのシークレットの暗号化を無効にするには、次のコマンドを実行します。

gcloud beta container clusters update [CLUSTER_NAME] \
  --zone [ZONE] \
  --disable-database-encryption \
  --project [CLUSTER_PROJECT_ID]

ここで

  • [CLUSTER_NAME] は、クラスタに付ける名前です。
  • [ZONE] は、クラスタを作成するゾーンです。
  • [CLUSTER_PROJECT_ID] は、クラスタ プロジェクト ID です。

アプリケーション レイヤでのシークレットの暗号化が有効になっていることを確認する

クラスタがアプリケーション レイヤでのシークレットの暗号化を使用しているか調べるには、Google Cloud Platform Console または gcloud コマンドを使用します。

Console

  1. GCP Console で Google Kubernetes Engine のメニューに移動します。

    Google Kubernetes Engine のメニューに移動

  2. 変更するクラスタの名前をクリックします。クラスタの [詳細] ページが開きます。

  3. [アプリケーション レイヤでのシークレットの暗号化] が有効であること、正しいキーが表示されていることを確認します。

gcloud

クラスタがアプリケーション レイヤでのシークレットの暗号化を使用しているかどうかを確認します。

gcloud beta container clusters describe [CLUSTER_NAME] \
  --zone [COMPUTE_ZONE] \
  --format 'value(databaseEncryption)' \
  --project [CLUSTER_PROJECT_ID]

ここで

  • [CLUSTER_NAME] は、既存のクラスタの名前です。
  • [COMPUTE_ZONE] は、クラスタのゾーンの名前です。
  • [CLUSTER_PROJECT_ID] は、クラスタ プロジェクト ID です。

クラスタがアプリケーション レイヤでのシークレットの暗号化を使用している場合、レスポンスには次の EncryptionConfig が含まれます。

keyName=projects/[PROJECT]/locations/[LOCATION]/keyRings/[RING_NAME]/cryptoKeys/[KEY_NAME];state=ENCRYPTED

制限事項

鍵のロケーション

使用されているクラスタと同じリージョン内の鍵を選択する必要があります。たとえば us-central1-a 内のゾーンクラスタは、us-central1 リージョン内の鍵のみを使用できます。リージョン クラスタでは、レイテンシを減らすため、またリソースが複数の障害発生ドメイン間のサービスに依存することを防ぐため、鍵がクラスタと同じロケーションに存在する必要があります。

シークレットを再暗号化する

現時点では、シークレットの自動的な再暗号化を強制する手段はありません。必要な場合は、新しい鍵バージョンを作成して KEK を手動でローテーションできます。

gcloud kms keys versions create --location [LOCATION] \
   --keyring [RING_NAME] \
   --key [KEY_NAME] \
   --primary \
   --project [KEY_PROJECT_ID]

すべてのシークレットをタップして GKE を強制的に再暗号化します。

kubectl get secrets --all-namespaces -o json | kubectl replace -f -

EncryptionConfig

現時点では、Cloud KMS の鍵だけが GKE でサポートされています。それ以外の Kubernetes KMS プロバイダ暗号化プロバイダを使用することはできません。

次のステップ

このページは役立ちましたか?評価をお願いいたします。

フィードバックを送信...

Kubernetes Engine のドキュメント