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

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

アプリケーション レイヤでのシークレットの暗号化は、GKE バージョン 1.11.2 以降で使用できます。

概要

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 サーバーからシークレットをリクエストすると、上記のプロセスが逆順で実行されます。

鍵を破棄した場合

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

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

始める前に

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

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

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

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

    Cloud KMS API の有効化

  • クラスタ プロジェクトで、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 リージョンの使用はサポートされていません。

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

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] は、クラスタ プロジェクト番号です。

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 です。

アプリケーション レイヤでのシークレットの暗号化を使用したクラスタの作成

アプリケーション レイヤでのシークレットの暗号化をサポートするクラスタを作成するには、作成コマンドの --database-encryption-key パラメータに値を指定します。クラスタ バージョン 1.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 です。

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

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

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 リージョン内の鍵のみを使用できます。リージョン クラスタの場合、鍵は同じリージョン内に存在する必要があります。

鍵のローテーション

Cloud KMS で鍵をローテーションすると、GKE のデータは再暗号化されません。以前に暗号化された既存のデータは再暗号化されませんが、新しいデータは新しい鍵で暗号化されます。

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

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 の鍵を持つ KMS プロバイダのみが GKE で利用できます。それ以外の Kubernetes KMS プロバイダ暗号化プロバイダを使用することはできません。

次のステップ

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

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

Kubernetes Engine のドキュメント