公式ドキュメントで迷子になる前に
안녕하신게라!パナソニック コネクト株式会社クラウドソリューション部の加賀です。
Azure Key Vault (AKV) の公式ドキュメントは多機能ゆえに情報量が多く、要件やユースケースごとの定石が読み取りづらいと感じたことはないでしょうか。(分厚いオブラート)
SKUの違い、VM・ストレージ適用時、インフラ・アプリ開発の双方で意識しておくべき注意点をまとめた情報が世の中に少なそうだったので、AWS KMSとの違いにも触れつつ暗号化設計の勘所としてまとめました。
なお、前提としてAzure Key Vaultには3つのオブジェクト種別が存在し、本記事は主にデータの暗号化に用いるKeys(暗号化用のキー/鍵)を主題とします。他の2つ、Secrets(パスワード等)、Certificates(証明書)は記事が多く見つかったので触れません。また、パスワードなどのシークレットを保存するだけであれば、特別な要件がない限り基本的にStandard SKUで十分であることを事前にお伝えしておきます。
※本記事内では、以下、リソースとしてのKeyを「キー」、暗号化システムにおける役割を「鍵」と表記します。
独自の鍵管理(CMK)って必要?
要件整理からSKU選択に至るまでの全体的な判断の流れをフローチャートにしておきます。
まず大前提として、コンプライアンス等で「どうしても鍵を管理しなければならない」という明確な要件がない限り、Key Vaultのカスタマーマネージドキー(以下、CMK)を使った独自の暗号化は不要です。公式ドキュメントにも記載されている通り、コンプライアンス要件がないならプラットフォームマネージドキー(以下、PMK)で十分であると書かれています。とは言っても、実運用では「暗号化キーを自分たちで持たなくて本当に大丈夫か?」と疑心暗鬼となり、不要だったCMKを採用し運用で迷うケースが目立ちます。
Azure上のストレージやデータベース、VMのディスクなどに保存されるデータは、何もしなくてもデフォルトで暗号化されています。これはPMKと呼ばれ、Microsoftが鍵の生成・保管・定期的なローテーションまでを裏で自動処理してくれます。PMKのままであれば追加コストもかからず、パフォーマンスへの影響や運用管理も不要であると、公式に明記されています。(大事二回)
で、CMKを使う大きな要件は、以下の場合となります。
- 顧客ごとに異なる鍵を使用してデータを完全に分離したい(BYOK要件)
- Microsoftの基盤鍵と併用して二重に暗号化したい(DKE要件)
- 鍵のライフサイクルやアクセスログをコントロールする必要がある(監査要件)
- 鍵を物理ハードウェア(HSM)の境界内で生成・保護する必要がある(セキュリティ要件)
- 万が一のインシデント時に、即座に鍵を破棄し、データを強制的に読み取れなくする仕組みを持たせる必要がある(キルスイッチ要件)
※アプリ側で暗号化を実装する場合、AWSに比べアプリ側の実装・管理コストが跳ね上がるため、後述するアプリ側からKey Vaultを利用する際の実装パターンも加味してCMK採用を判断してください。
Azure Key Vault SKUの選び方
フローチャートで「CMKを使う」となった場合、次に直面するのがAzure Key VaultのSKU選びと、別製品である「Azure Managed HSM」の採用検討です。
| 項目 | Standard SKU | Premium SKU | Azure Managed HSM |
|---|---|---|---|
| 保護の仕組み | ソフトウェア実装 | HSM(ハードウェア) による物理的隔離 |
専有HSMによる独立環境 |
| コンプライアンス | FIPS 140-2 Level 1 | FIPS 140-2 Level 2 ※1 | FIPS 140-2 Level 3 |
| モデル | サービス共有型 | マルチテナント共有型 | テナント専有型 |
| 主な用途 | 一般的なアプリ、コストを抑えたCMK | 厳格な要件を持つミッションクリティカルなシステム | 医療・金融など極めて高い独立性が求められるシステム |
|
費用感(USD) 東/西日本リージョン |
処理費のみ 0.03~0.15 / 1万件2 キー保持費: 無料 |
処理費 + キー保持費 0.03~0.15 / 1万件2 キー保持費: 1.00〜5.00/月 ※有効なキー世代ごと3 |
処理費 + HSM専有費 0.03~0.15 / 1万件2 キー保持費: 追加課金なし HSM専有費: 約 2,400〜/月 ※稼働時間に対する課金4 |
基本的な機能や連携できるAzureサービスに大差はありませんが、裏側でどう守っているか、費用感、ハードウェアの分離具合が異なります。利用するシステムのコンプライアンス要件に応じて選択します。
Premium SKU との付き合い方とコストの罠
よくある勘違いとして「Premium SKUにすればパスワードなどのシークレットも全部HSMで守られて安全になる」と思われがちですが、これは罠です。Premium SKUであっても、HSMによって保護されるのは「キー」のみです。「シークレット」や「証明書」についてはStandard SKUと同様にソフトウェアベースでの保護となります。
(シークレットや証明書などの保管についてはPremium SKUであってもソフトウェア保護となるため、Standard SKUと同等で一律無料です。1つのKey Vault内に混在させても問題ありません)
費用の落とし穴として「キー保持コストの雪だるま式増加」があります。
セキュリティを高める目的で自動ローテーション(USD 1.00/回)を毎日や毎週といった高頻度に設定すると、無数に蓄積された過去バージョンのキー1つひとつに対して月額費用(USD 1.00〜5.00/世代)が発生し続け、想定外のコスト爆発を引き起こします。価格表の「1キーあたり」とは「有効(Enabled)なキーのバージョン単位」を指すため、AWS KMSの世代数を意識しなくて良いという感覚のままでローテーション設計を組むと痛い目を見ます。
最上位の Azure Managed HSM を採用する場合
さらに上位要件で利用される Azure Managed HSM は、Key Vault(コンテナ)とは完全に異なる、キー専用の独立した別リソース(Microsoft.KeyVault/managedHSMs)であり、Premium SKUへアドオンするようなものでもありません。そもそもシークレットや証明書をサポートしていません。
そのため、実運用ではセキュリティ要件の極めて高い「キー」管理はManaged HSMで行い、「シークレットや証明書」の管理にはコストを抑えた通常のKey Vault(Standard SKU)を別途構築して組み合わせて併用するアーキテクチャが一般的かつベストプラクティスです。併用するためだけにKey VaultのPremium SKUを契約する必要はありません。
また、Managed HSMはPremium SKUと違って専有リソースであるため、構築プロセスが特殊です。プロビジョニングに20〜30分近くかかる上、作成後に独自の“初期化儀式”で最低3つの証明書によるクォーラムを設定を行わないとアクティブ化できません。単なる上位互換機能と勘違いして採用すると、構築・運用自動化のハードルが数段跳ね上がる点には十分留意してください。
コンプライアンス要件で「鍵は物理的に隔離された専用のハードウェア(HSM)に保管すること」と名指しで指定されている場合にKey Vaultの Premium SKU を選びます。さらに「ハードウェアの基盤まるごと専用の隔離環境にならないとダメ」という非常に特殊な要件が出てきて初めて、別リソースである Managed HSM の出番となります。
2つのHSMサービスとその違い
AKVの話題から逸れるためフローチャートから外しましたが、似たようなHSMサービスがあり、その違いに触れないわけにもいかず、枠外で紹介しておきます。
-
Azure Managed HSM
基本はコチラ。「FIPS 140-2 Level 3 準拠」です。
CMKはAzureサービスと連携でき、AKVのAPIが使えます。 -
Azure Cloud HSM(Azure Dedicated HSMの後継IaaSサービス)
「FIPS 140-3 Level 3 準拠」が必要な場合や、暗号化処理を専有ハードウェアにオフロードできるIaaSサービス。運用ハードルは跳ね上がります。
CMKはAzureサービスと連携できず、AKVのAPIも利用できず、専用のクライアント経由で通信するためアプリケーションの改修が必要になります。
インフラ設計・構築時の落とし穴
Key Vaultを組み込んだインフラを設計する上で、実運用を見据え押さえるポイントを挙げます。
蛇足ですが、エンタープライズの本番運用では、ストレージやVMを構築する際、必ずCMKを利用するようAzure Policyで制限・強制する構成も有効なプラクティスです。
「論理的な削除」と「パージ保護」は必須
万が一Key Vault上の鍵が完全に消えてしまうと、暗号化されたディスクやストレージ内のデータは二度と復元できなくなります。これを防ぐため、現在のAzure Key Vaultにおいて「論理的な削除(Soft Delete)」は強制的に有効化されています(無効化できません)。ここで注意すべきインフラの罠として、論理的な削除の保持期間(7〜90日)はKey Vault作成時に一度決定すると、後から一切変更できないという仕様があります。
さらに、IaC(TerraformやBicep)で検証用に一時環境を構築する場合、洗礼が待っています。同名での再作成はできないため、CLIコマンド等で明示的にPurge(完全削除)するか、デプロイごとにサフィックスに乱数を付けて回避する必要があります。
ただし、「パージ保護(消去保護/Purge Protection)」については注意が必要です。有効にすると保持期間を満了するまで誰も(Microsoftサポートも)強制削除できなくなることに加え、一度有効化するとそのKey Vaultに対してパージ保護を無効化(オプトアウト)することはできなくなるため、一時的な検証環境等では設定値に注意を払いましょう。
本番環境では Microsoft Defender for Cloud 等のコンプライアンス要件を満たすため Azure Policy でパージ保護を強制(DeployIfNotExists や Deny)するのがベストプラクティスですが、それを開発・検証環境のサブスクリプションまで適用してしまうと、IaCでのスクラップ&ビルドが一切できなくなり地獄を見ます。環境に応じたポリシーの適用範囲の設計が不可欠です。
ネットワーク閉域化時のバイパス設定
Key Vaultをプライベートエンドポイント等で閉域化する際、ストレージアカウント等からのアクセスを許可するために「リソースインスタンス(Resource instances)」を利用した特定リソースへのアクセス許可、もしくは「信頼されたMicrosoftサービスがこのファイアウォールをバイパスすることを許可する」という例外設定を入れ忘れると、裏側のストレージやディスク基盤(DESなど)から鍵にアクセスできなくなり「VMが起動しない」といった障害につながります。なお、これはすべてのAzureサービスがアクセスできるわけではなく例外の対象(Azure Storage、SQL Databaseなど)に限られるため、一部のWeb AppsやAKSなどからアクセスする場合は別途プライベートエンドポイントやVNet統合が必要です。
また、閉域化の際のよくあるトラブルとして、Private DNS Zone (privatelink.vaultcore.azure.net) の設定漏れ・VNetリンク忘れによる名前解決の失敗が挙げられます。(※Managed HSMを利用する場合はエンドポイントが異なり privatelink.managedhsm.azure.net となります)
よくある勘違いとして「アプリからの接続先も privatelink... のURLに変更しなければならない」と思われがちですが、アプリの接続先は閉域化前後に関わらず常にパブリックなエンドポイント(https://<vault-name>.vault.azure.net/、Managed HSMの場合は https://<hsm-name>.managedhsm.azure.net/)を指定し続けるのが正解です。Azure DNSがCNAMEレコードで勝手にプライベートIPへルーティングしてくれます。アプリ側で直接プライベートのURLに変えると、TLS/SSL証明書のドメイン不一致エラーが発生するため注意してください。アクセス制御(RBACなど)以前のネットワークの罠として、構築時に必ず確認してください。
アクセス制御はAzure RBACで
以前はKey Vault独自のアクセスポリシーを使う手順が主流でしたが、現在はAzure RBACを利用する形が推奨されています。管理者には Key Vault 暗号化責任者 (Key Vault Crypto Officer)、VMやストレージ、アプリのマネージドIDには Key Vault 暗号化ユーザー (Key Vault Crypto User) や Key Vault 暗号化サービスの暗号化ユーザー (Key Vault Crypto Service Encryption User) など、用途を分離して必要最小限のロールだけを付与するシンプルな構成を取りましょう。
また、RBACの罠として「上位の管理者(OwnerやContributorなどの権限)であっても、自分自身に Key Vault Crypto Officer や Key Vault Secrets Officer などのデータプレーンのロールを付与しないと中身のデータ(鍵)は直接見られない・操作できない」点には注意が必要です。
※Managed HSMの場合は、通常のAzure RBACとは異なり、独立した「Managed HSM ローカル RBAC」が適用される点にもご留意ください。
自動ローテーションで運用を楽に
手作業での定期的な鍵更新は負担になります。Key Vaultのローテーションポリシーを設定し、有効期限が近づいたタイミングで自動的に新しいバージョンのキーへ更新されるようにしておくのが定石です。
自動ローテーションを活用すれば運用負荷は格段に下がりますが、ローテーションの実行自体に「スケジュールされたローテーション費用(約USD 1.00/回)」が都度発生します。さらにPremium SKUの場合は、生成された新バージョンのキーに対する月額の保持費用も追加で累積していくため、コンプライアンス要件(年1回など)を満たす範囲で適切な頻度を設定してください。
フェールオーバー時の「読み取り専用」制約
「CMKにするとKey Vaultが単一障害点(SPOF)にならないか?」と心配になるかもしれませんが、Key Vaultは標準でペアリージョンにデータが複製され、リージョン障害時には自動でフェールオーバーします。
ただし、フェールオーバー中のセカンダリリージョンでは「読み取り専用」モードです。キーの参照(復号・Unwrap操作など)は継続できますが、新たなキーの生成や更新などの書き込み操作は一切できなくなります。障害時にシステム側でキーの更新やシークレットの書き込みが走ってクラッシュしないよう、設計段階でフェールオーバー時の仕様を考慮してください。
有事に備えたバックアップの考慮
Key Vault内のキーはセキュリティ上、外部へのエクスポート(素の鍵データの取り出し)ができません。誤操作による消去やリージョン障害に対する備えとして、Azureネイティブのバックアップ・リストア操作を利用して別Key Vaultへの復元ができるよう運用を整えておくことを推奨します。
ただし、バックアップからの復元は「同一のAzureテナント」および「同一の地理的境界(Geography内)」に限定されるという制約があります。別のサブスクリプションであっても同じテナントとGeography内であれば復元可能ですが、別テナントへの移行や、海外リージョンへの持ち出しは設計上ブロックされている点に注意してください。
Managed HSM 特有のバックアップ(DR)の罠
前述の通り、通常のKey Vaultは裏側でペアリージョンに自動フェールオーバーされる高可用性を持っていますが、Managed HSMはデフォルトではマルチリージョン構成にならず、そのままでは単一リージョンでの稼働となります(要件に応じて後からセカンダリリージョンを追加することで高可用性を持たせます)。マルチリージョン構成にはバックアップ・リストア機能でレプリケーション戦略を構築する必要があります。
追加の罠として、Managed HSMのプロビジョニング直後に行う「セキュリティドメイン」のダウンロード(3つの証明書片)があります。万が一リージョン障害が発生した場合や、誤って全体を削除してしまった場合、全データを復元するためにはこのセキュリティドメインとクォーラム証明書が必須となります。もしこれを紛失していると、万が一の事態で全暗号化キーが二度と復元できず、それらで暗号化されていた全ストレージやVMのデータへ永遠にアクセスできなくなります。(だからこそキルスイッチ要件を満たします)
各種Azureリソースへの適用方法
ストレージやVMなどをKey Vaultで暗号化する際、SKUによって設定手順が変わることはありません。ただし、対象リソースによってアーキテクチャや必要な権限構成が少し異なります。
ストレージアカウントに適用する場合
ストレージアカウント内のデータは常に基盤側で暗号化されています。ここにCMKを適用するということは「暗号化の大元となる親鍵だけをKey Vaultに退避させる」という形になります。
ここで重要なのは、ストレージに対してマネージドIDを割り当て、そのIDに Key Vault 暗号化サービスの暗号化ユーザー 等のロールを付与することです。このとき、システム割り当てではなく「ユーザー割り当てマネージドID(UAMI)」を利用すると、TerraformやBicepといったIaCでの構築時にリソース間の依存関係の循環(鶏と卵問題)を防ぎやすくなります。
また、運用の手間を減らすために、ストレージ側の暗号化設定でKey Vaultのキーのバージョンをあえて指定しない(バージョンレス指定)設計を考慮しておきます。指定しないことでKey Vault側で親鍵がローテーションされたときに、ストレージ側にも自動で新しい親鍵が適用されます。ただし、仕組み上変更をポーリングで検知しているため、実際に新しい親鍵に切り替わるまでには最大1時間のラグが発生する点には注意してください。(※以前の仕様や他リソースと異なり、現在は1時間以内に同期されます。もしこのラグすら許容できない要件の場合は、Azure Event Grid でキー更新イベントを検知し、即座に手動更新をキックするアーキテクチャが公式のベストプラクティスとして推奨されています)
VM(マネージドディスク)に適用する場合
現在のMicrosoft Azureでは、古くからのVMゲストOS内で暗号化処理を行う Azure Disk Encryption (ADE) よりも、パフォーマンスや運用性に優れる「ホストベースの暗号化 (Encryption at Host)」または「CMKを利用したサーバ側暗号化 (SSE with CMK)」が強く推奨されています。ADEのようにわざわざVMの中に入ってOSの設定をいじる必要はなく、すべてAzureのホスト側が透過的に処理してくれます。実運用において、複雑で古いADEは極力避けましょう。
ストレージアカウントと少し違うのは、VMやマネージドディスクが直接Key Vaultへアクセスするわけではないという点です。間に「Disk Encryption Set (DES)」と呼ばれるリソースをワンクッション挟む必要があります。
このDESに対してマネージドID(ここでもUAMI推奨)とアクセス権を付与し、VMのディスク設定でそのDESを指定します。DES側で自動ローテーションを有効にしておけば、VMを再起動することなく新しい鍵が適用されます(反映までのラグがあるのはストレージと同様です)。
アプリ側からKey Vaultを利用する際の実装パターン
インフラではなく、アプリケーションからKey Vaultを使って暗号化機能を実装したい場合、暗号化したいデータを直接Key VaultのAPIに投げて処理させるのはアンチパターンです。
Key Vaultは、高頻度かつ大容量のデータをゴリゴリ処理するようには作られていません。これをしてしまうとAPIのスロットル制限(暗号化操作等のトランザクションは、RSA 2048等の標準的なキーで「2,000 リクエスト/10秒」、より高度なキーでは「400 リクエスト/10秒」が上限)に引っかかり、小規模なシステムでも最悪の場合システムが停止してしまいます。
耳タコかもですが「エンベロープ暗号化」が定石です。以下、Key Vault内で管理する親鍵を KEK(Key Encryption Key/鍵暗号化鍵)、アプリ側で生成して実データの暗号化に使う鍵を DEK(Data Encryption Key/データ暗号鍵) とします。
Azure環境では、以下のようなシーケンスでエンベロープ暗号化を実装します。
データを復号する際は、データベースから「暗号化されたデータ」「暗号化されたDEK」「鍵のバージョン(KIDバージョン情報を含むURL)」の3点を取り出し、Key Vaultの UnwrapKey APIに「このバージョンの親鍵で、暗号化されたDEKを復号して」と依頼します。返ってきた平文のDEKを使って、アプリ内でデータを復号する流れになります。
パフォーマンスへの影響が気になる場合は、セキュリティ要件が許す範囲で、復号済みのDEKをアプリケーションのメモリ上に短時間だけキャッシュするなどの工夫も効果的です。
AWS KMSとの決定的な違い
エンベロープ暗号化を実装する際、AWSから移行したエンジニアが最もつまずきやすいのが Azure Key VaultはAWS KMSほどよしなにやってくれない点です。違いは2つ。
1. データ暗号化キー(DEK)は自動生成されない
AWS KMSには、APIを1回呼び出すだけで「平文のDEK」と「暗号化済みのDEK」の両方を生成して返してくれる便利な GenerateDataKey が存在します。
しかし、Azure Key Vaultにはこれに相当するAPIがありません。そのため、まずはアプリ側で自前でDEKとなる乱数のバイト配列を生成してから、WrapKey で暗号化を依頼するという2段階の手順を踏む必要があります。
2. 鍵バージョンの管理はアプリ側の責任
AWS KMSの場合、裏側の基盤(バッキングキー)がメタデータ付きで管理しているため、暗号化済みのデータの中に「どの鍵のどのバージョンで暗号化したか」の情報が含まれています。アプリ側は何も考えずに復号APIを叩けば、KMSが自動で古いバージョンの鍵を探して復号してくれるため、ローテーションを意識する必要はありません。
しかし、Azure Key Vaultの WrapKey や UnwrapKey は純粋な非対称暗号技術のプリミティブな操作を提供しており、Key Vault側が返す暗号文本体(バイト列)の中にはメタデータが含まれません。そのため、アプリ側で暗号文とKIDのペアを保存・管理する必要があります。もし親鍵がローテーションで更新された後に、アプリ側から「古いバージョンのKID」を明確に指定せずに UnwrapKey を呼ぶと、復号エラーになってしまいます。
Azureではバージョン管理の責任がアプリ側であり、暗号化データと一緒にKey VaultのKID(バージョン付きURL)をDBに保存・管理する設計が不可欠となります。AWSから移植する際は要注意です。
また、自動ローテーションにおいて陥りやすい罠として、親鍵(KEK)が更新されても既存の暗号化済みDEKは古いバージョンの親鍵で解読可能なままであり、自動で再暗号化はされません。自動で新しい親鍵が適用されるバージョンレス指定が効果を発揮するのはストレージ等のAzure基盤サービスのみであり、アプリでエンベロープ暗号化を行っている場合は、再暗号化処理をアプリ側で実装する必要がある点も理解しておくと混乱せずに済むでしょう。
まとめ
Azureの暗号化は「無理に自分たちで管理せず、PMKに任せる」のが良いと公式ドキュメントでも明確にPMKの利用が推奨されていました。(そりゃ情報が少ないワケだ)
どうしてもCMKが必要になった際、この記事が少しでも役立てば幸いです。
お断り
記事内容は個人の見解であり、所属組織の立場や戦略・意見を代表するものではありません。
あくまでエンジニアとしての経験や考えを発信していますので、ご了承ください。
-
公式では「Level 2 または Level 3」と表記されることがありますが、クラウド全体を通した保証レベルは「Level 2」として扱い、「Level 3」の保証としたい場合は、要件を詳細に確認してください。 ↩
-
基本的な処理(RSA 2048など)は USD 0.03 / 1万件 ですが、RSA 3072/4096 や ECC などの高度なキー操作の場合は単価が USD 0.15 / 1万件 に跳ね上がる点にも留意してください。 ↩ ↩2 ↩3
-
Azure Key Vault においては、ローテーション後も無効化(Disabled)していない過去バージョンのキー1つひとつに対して月額の保持費用が加算されるため、運用が長引くほど固定費が積み上がる点に注意が必要です。(ローテーション自体の実行にも都度 USD 1.00 かかります) ↩
-
専用ハードウェア環境を丸ごと借り切る形態のため、その箱の中に何種類の鍵を登録しても、何世代ローテーションして蓄積しても、鍵の数や世代に対する月額課金は一切発生しません(箱代とトランザクション料のみです)。1インスタンスにつき最大5,000キー、各100バージョンまでという上限が存在します。詳細は公式のAzure Key Vault の価格ページをご確認ください。 ↩