Etcdに格納されたRestでのKubernetesシークレットの暗号化

Container Engine for Kubernetes (OKE)の使用時にetcdにKubernetesシークレットとして格納された構成データを暗号化する方法を確認します。

Kubernetesクラスタ・コントロール・プレーンには、機密構成データ(認証トークン、証明書、資格証明など)がKubernetesシークレット・オブジェクトとしてetcdに格納されます。etcdは、Kubernetesがクラスタの調整および状態管理に使用する、オープン・ソースの分散キー-値ストアです。Container Engine for Kubernetesによって作成されたKubernetesクラスタでは、etcdは、Oracle Cloud Infrastructure Block Volumeサービスのブロック・ストレージ・ボリュームとの間でデータの書込みと読取りを行います。デフォルトでは、OracleはetcdやKubernetesシークレットなどのブロック・ボリューム内のデータを暗号化します。Oracleでは、マスター暗号化キーを使用してこのデフォルトの暗号化を管理するため、ユーザーの操作は必要ありません。マスター暗号化キーのライフサイクルとその使用方法をさらに制御するには、Oracleで管理するのではなく、マスター暗号化キーを自分で管理することを選択できます。

マスター暗号化キーを自分で管理することを選択した場合は、使用するキーを指定し、キーがローテーションされるタイミングを制御できます。マスター暗号化キーは、Oracle Cloud Infrastructure Vaultサービスに格納されます(キー管理を参照)。etcdに保存されているKubernetesシークレットは、PKCS#7パディングを使用したAES-CBC暗号化アルゴリズムを使用して、データ暗号化キー(DEK)を使用して暗号化されます。暗号化ごとに新しいDEKが生成されます。データ暗号化キーは、エンベロープ暗号化と呼ばれる概念であるマスター暗号化キー(MEK)を使用して暗号化されます。

マスター暗号化キーを管理するクラスタを自分で作成する前に、次のことを行う必要があります。

  • ボールトに適切なマスター暗号化キーを作成します(または、そのようなキーの名前およびOCIDを取得します)
  • 新しいクラスタを作成するコンパートメント内のすべてのクラスタを含む動的グループを作成する
  • マスター暗号化キーを使用する動的グループを認可するポリシーを作成する

クラスタを作成し、マスター暗号化キーを自分で管理することを指定したら、必要に応じて、そのクラスタのみを含めるように動的グループを変更することによって、マスター暗号化キーの使用を制限できます。

次の点に注意してください:

  • カスタム作成ワークフローで新規クラスタを作成する場合、マスター暗号化鍵を管理するオプションのみを選択できます。「クイック作成」ワークフローで新規クラスタを作成する場合、マスター暗号化キーの管理を選択することはできません。また、「カスタム作成」ワークフローで以前に作成したクラスタのマスター暗号化鍵の管理は選択できません。
注意

マスター暗号化キーを自分で管理するオプションを選択した場合は、Vaultサービスのマスター暗号化キーを削除しないでください。ボールトでキーを削除するようにスケジュールするとすぐに、etcdのクラスタ用に格納されているKubernetesシークレットにアクセスできなくなります。キーの削除がすでにスケジュールされている場合、「削除の保留中」状態のままになっている可能性があります。その場合、スケジュールされているキーの削除を取り消して(マスター暗号化キーの削除の取消しを参照)、Kubernetesシークレットへのアクセスをリストアします。スケジュールされたキーの削除操作を完了し、マスター暗号化キーを削除できるようにすると、etcdのクラスタ用に格納されているKubernetesシークレットに永久にアクセスできなくなります。その結果、クラスタのアップグレードは失敗します。この状況では、クラスタを削除して再作成する以外に選択肢はありません。

マスター暗号化キー・アクセスの設定

「カスタム作成」ワークフローで新規クラスタを作成する際に、クラスタのetcdキー/値ストアにあるKubernetesシークレットを暗号化するマスター暗号化鍵を管理する場合は、マスター暗号化鍵へのアクセスを設定します。

  1. コンソールにログインします。
  2. Kubernetesシークレットの暗号化に使用するマスター暗号化キーのOCIDがわかっている場合は、次のステップに進みます。それ以外の場合:

    • 適切なマスター暗号化キーがVaultにすでに存在するが、そのOCIDが不明な場合は、マスター暗号化キーのリストの手順に従い、マスター暗号化キーのOCIDをノートにとります。
    • 適切なマスター暗号化キーがVaultに存在しない場合は、マスター暗号化キーの作成の手順に従って、次のように設定します:
      • ソフトウェアまたはHSMへの保護モード
      • キー・シェイプ:アルゴリズムからAES、RSAまたはECDSA。
      • キーのシェイプ:長さ: AESキー(128、256)およびRSAキー(2048、3072、4096)またはキー・シェイプ:曲線ID(ECDSAキー(NIST_P256、NIST_P384、NIST_P521)用です。
      新しいマスター暗号化キーを作成したら、そのOCIDを書き留めます。
  3. ボールトのマスター暗号化キーへのアクセス権を付与します。

    マスター暗号化キーへのアクセスは、次の2つの方法で付与できます。

    新規IAMポリシーの作成(推奨)
    1. ナビゲーション・メニューを開き、「アイデンティティとセキュリティ」をクリックします。「アイデンティティ」で、「ポリシー」をクリックします。
    2. ポリシーを作成するにはの説明に従って、ポリシーに名前を付けます(たとえば、acme-oke-kms-policy)。
    3. 次の形式で、マスター暗号化キーへのアクセス権を付与するポリシー・ステートメントを入力します:

      Allow any-user to use keys in compartment <compartment-name> where ALL {request.principal.type = 'cluster', target.key.id = '<key-ocid>'}
      

      ここでは:

      • <compartment-name>は、マスター暗号化キーを含むコンパートメントの名前です。
      • <key-OCID>は、ボールトにおけるマスター暗号化キーのOCIDです。

      例:

      Allow any-user to use keys in compartment acme-kms-key-compartment where ALL {request.principal.type = 'cluster', target.key.id = 'ocid1.key.oc1.iad.annrl______trfg'}
      
    4. 「作成」をクリックして、新しいポリシーを作成します。
    新しい動的グループを作成し、新しいIAMポリシーを作成します。
    1. ナビゲーション・メニューを開き、「アイデンティティとセキュリティ」をクリックします。「アイデンティティ」で、「ドメイン」をクリックします。「アイデンティティ・ドメイン」で、「動的グループ」をクリックします。
    2. 動的グループを作成するにはの手順に従って、動的グループに名前を付けます(たとえば、acme-oke-kms-dyn-grp)。
    3. コンパートメント内のすべてのクラスタを含むルールを次の形式で入力します:

      ALL {resource.type = 'cluster', resource.compartment.id = '<compartment-ocid>'}

      <compartment-ocid>は、新しいクラスタを作成する予定のコンパートメントのOCIDです。

      例:

      ALL {resource.type = 'cluster', resource.compartment.id = 'ocid1.compartment.oc1..aaaaaaaa23______smwa'}
    4. 「動的グループの作成」をクリックします。

      コンパートメント内のすべてのクラスタを含む動的グループを作成したら、ボールトでマスター暗号化キーへの動的グループ・アクセス権を付与するポリシーを作成できるようになります。

    5. ナビゲーション・メニューを開き、「アイデンティティとセキュリティ」をクリックします。「アイデンティティ」で、「ポリシー」をクリックします。
    6. ポリシーを作成するにはの手順に従って、ポリシーに名前を付けます(たとえば、acme-oke-kms-dyn-grp-policy)。
    7. 次の形式で、マスター暗号化キーへの動的グループ・アクセス権を付与するポリシー・ステートメントを入力します:

      Allow dynamic-group <dynamic-group-name> to use keys in compartment <compartment-name> where target.key.id = '<key-OCID>'

      ここでは:

      • <dynamic-group-name>は、以前に作成した動的グループの名前です。
      • <compartment-name>は、マスター暗号化キーを含むコンパートメントの名前です。
      • <key-OCID>は、ボールトにおけるマスター暗号化キーのOCIDです。

      例:

      Allow dynamic-group <acme-oke-kms-dyn-grp> to use keys in compartment acme-kms-key-compartment where target.key.id = 'ocid1.key.oc1.iad.annrl______trfg'
    8. 「作成」をクリックして、新しいポリシーを作成します。
  4. 新しいクラスタを作成する場合は、「管理するキーを使用した暗号化」オプションを選択し、マスター暗号化キーを指定します(コンソールを使用したカスタム作成ワークフローでの明示的に定義した設定によるクラスタの作成を参照)。

  5. (オプション)クラスタを作成した後、セキュリティを強化するには:

    1. 作成した新しいクラスタのOCIDをノートにとります。
    2. マスター暗号化キーの使用を制限します。

      • 単にIAMポリシーを作成した場合は、コンパートメント内のすべてのクラスタではなく、新しいクラスタのOCIDを明示的に含めるようにポリシー・ステートメントを変更します。例:

        Allow any-user to use keys in compartment acme-kms-key-compartment where ALL {request.principal.type = 'cluster', target.key.id = 'ocid1.key.oc1.iad.annrl______trfg', request.principal.id = 'ocid1.cluster.oc1.iad.aaaaaaaaaf______yg5q'}
        
      • 動的グループを作成した場合は、以前に作成した動的グループ・ルールを変更して、コンパートメント内のすべてのクラスタではなく、新しいクラスタのOCIDを明示的に指定します。例:

        resource.id = 'ocid1.cluster.oc1.iad.aaaaaaaaaf______yg5q'

マスター暗号化キーの回転

マスター暗号化キーを自分で管理するオプションを選択した場合は、Vaultサービスでマスター暗号化キーをローテーションし、マスター暗号化キーの新しいバージョンを作成できます(Vaultキーのローテーションを参照)。

この場合、マスター暗号化鍵自体は削除されません(マスター暗号化鍵リソースは引き続き存在し、同じOCID)。ただし、マスター暗号化鍵には新しい値があります。クラスタに格納されている新しいKubernetesシークレットは、マスター暗号化鍵の新しい値を使用して暗号化されます。マスター暗号化キーの元のバージョンがボールト・サービスで使用可能なため、既存の暗号化されたKubernetesシークレットには引き続きアクセスできます。既存のKubernetesシークレットを新しいバージョンのマスター暗号化キーを使用して暗号化する場合は、再度暗号化されるようにKubernetesシークレットをローテーションする必要があります。たとえば、次のコマンドを実行します。
kubectl get secrets --all-namespaces -o json | kubectl annotate --overwrite -f - encryption-key-rotation-time="<time>"

ここで、<time>は、ローテーションを実行するタイミングを示す文字列です。例:

kubectl get secrets --all-namespaces -o json | kubectl annotate --overwrite -f - encryption-key-rotation-time="20210909_2135"

他のテナンシのマスター暗号化キー

別のテナンシのマスター暗号化キーを使用するクラスタをテナンシに作成できます。この場合、クロステナンシ・ポリシーを記述し、テナンシ内のクラスタがボールト・サービスのテナンシ内のマスター暗号化キーにアクセスできるようにする必要があります。クラスタを作成し、別のテナンシにあるマスター暗号化キーを指定する場合、コンソールを使用してクラスタを作成することはできません。

たとえば、クラスタがClusterTenancyにあり、マスター暗号化キーがKeyTenancyにあるとします。ClusterTenancyのグループ(OKEAdminGroup)に属するユーザーには、クラスタを作成する権限があります。ルールALL {resource.type = 'cluster', resource.compartment.id = 'ocid1.compartment.oc1..<unique_ID>'}を使用してクラスタに動的グループ(OKEAdminDynGroup)が作成されたため、ClusterTenancyに作成されたすべてのクラスタは動的グループに属します。

KeyTenancyのルート・コンパートメントには、次のポリシーがあります:

  • ClusterTenancyのOCIDを使用して、ClusterTenancyを別名OKE_Tenancyにマップします
  • OKEAdminGroupおよびOKEAdminDynGroupのOCIDを使用して、それぞれ別名RemoteOKEAdminGroupおよびRemoteOKEClusterDynGroupにマップします
  • RemoteOKEAdminGroupおよびRemoteOKEClusterDynGroupに、KeyTenancyの特定のマスター・キーを使用して暗号化操作をリスト、表示および実行する機能を付与します
Define tenancy OKE_Tenancy as ocid1.tenancy.oc1..<unique_ID>
Define dynamic-group RemoteOKEClusterDynGroup as ocid1.dynamicgroup.oc1..<unique_ID>
Define group RemoteOKEAdminGroup as ocid1.group.oc1..<unique_ID>
Admit dynamic-group RemoteOKEClusterDynGroup of tenancy ClusterTenancy to use keys in tenancy where target.key.id = 'ocid1.key.oc1..<unique_ID>'
Admit group RemoteOKEAdminGroup of tenancy ClusterTenancy to use keys in tenancy where target.key.id = 'ocid1.key.oc1..<unique_ID>'

ClusterTenancyのルート・コンパートメントには、次のポリシーがあります:

  • KeyTenancyのOCIDを使用してKeyTenancyを別名KMS_Tenancyにマップします
  • KeyTenancyのマスター・キーを使用する機能をOKEAdminGroupおよびOKEAdminDynGroupに付与します
  • OKEAdminDynGroupがKeyTenancyから取得した特定のマスター・キーをClusterTenancyで使用できるようにします
Define tenancy KMS_Tenancy as ocid1.tenancy.oc1..<unique_ID>
Endorse group OKEAdminGroup to use keys in tenancy KMS_Tenancy
Endorse dynamic-group OKEAdminDynGroup to use keys in tenancy KMS_Tenancy
Allow dynamic-group OKEAdminDynGroup to use keys in tenancy where target.key.id = 'ocid1.key.oc1..<unique_ID>'

クロステナンシ・ポリシーの記述例は、テナンシ間でのオブジェクト・ストレージ・リソースへのアクセスを参照してください。

ポリシーを入力したら、次のようなコマンドを実行して、KeyTenancyから取得したマスター・キーを使用するクラスタをClusterTenancyに作成できます:
oci ce cluster create --name oke-with-cross-kms --kubernetes-version v1.16.8 --vcn-id ocid1.vcn.oc1.iad.<unique_ID> --service-lb-subnet-ids '["ocid1.subnet.oc1.iad.<unique_ID>"]' --compartment-id ocid1.compartment.oc1..<unique_ID> --kms-key-id ocid1.key.oc1.iad.<unique_ID>