Azure API Management(APIM)のポリシーで、Key Vault 参照のクライアント証明書を使って JWT を署名したいのに、取得キーがサムプリントしかなくてローテーション運用がつらい――この悩みはよく起きます。仕組み上の制約と、現実的に「手間を減らす」設計パターンをまとめます。
よくある構成:APIM ポリシーで証明書の秘密鍵を使い JWT を生成する
APIM を単なるルーティングではなく「認証付きのゲートウェイ」として使う場合、バックエンドへアクセスするために 証明書ベースのクライアント認証(例:OAuth 2.0 Client Credentials の client_assertion)を組み込みたくなることがあります。
典型的な流れは次のようになります。
- 呼び出し元 → APIM
- APIM(ポリシー)で JWT(クライアントアサーション)を生成し署名
- APIM がトークンエンドポイントへアクセスしてアクセストークン取得
- APIM がバックエンド API を呼び出し、結果を返す
このとき、署名に使う秘密鍵を持つ証明書を Key Vault 管理にしておくと、セキュリティ面・運用面でメリットがあります。一方で「ローテーション後の追随」で詰まりやすいのが本題です。
結論:ポリシー内の context.Deployment.Certificates はサムプリントでしか取得できない
APIM のポリシー式(C#)で context.Deployment.Certificates から証明書を取り出す場合、辞書のキーとして使えるのは サムプリント(thumbprint)のみです。Key Vault のシークレット URI や、ポータルの「クライアント証明書」画面で表示される内部的な証明書 ID を指定して context.Deployment.Certificates["CertificateId"] のように取得することはサポートされていません。
まずは「できる/できない」を表にすると、整理が早いです。
| 指定したい識別子 | ポリシー(context.Deployment.Certificates)でキーにできる? | 補足 |
|---|---|---|
| 証明書サムプリント | できる | 辞書キーとして唯一サポート |
| Key Vault のシークレット URI / ID | できない | ポリシー式から直接のキー指定は不可 |
| APIM ポータルの「クライアント証明書」ブレードに出る内部 ID | できない | 見えている ID とポリシー式は連動しない |
| (誤解されがち)certificate-id | 用途が違う | 後述:特定のポリシーでのみ有効 |
混同しやすい「証明書 ID」を整理する
「IDで取れないの?」が起きる最大の理由は、Azure の画面やドキュメントで “ID” と呼ばれるものが複数あるためです。実務上は、次の4つを区別すると迷いません。
| 呼び名 | 見える場所 | ローテーションで変わる? | 主な用途 |
|---|---|---|---|
| サムプリント(Thumbprint) | 証明書詳細、APIM 証明書一覧など | 変わる(証明書が変われば変わる) | 証明書そのものの識別(ただし運用は重くなりがち) |
| Key Vault 証明書の識別子(シークレット URI) | Key Vault(Secrets/Certificates) | バージョン付きは変わる/バージョンなしは固定 | Key Vault 側の参照(サービス連携の入口) |
| APIM の証明書リソース名(Id / resource name) | APIM の「Certificates」登録時の Id(名前) | 通常は変えない | 一部のポリシーで certificate-id として指定可能 |
| APIM ポータルの内部的な GUID 風 ID | 「クライアント証明書」ブレードなど | 証明書入れ替え等で変わり得る | UI 上の内部参照(ポリシー式のキーにはならない) |
今回ハマっているのは、「ポリシー式の辞書キー=サムプリント固定」という仕様に対して、運用では「Key Vault ローテーション=サムプリント変化」が起きることです。つまり、仕組み上 “追随が必要” になります。
まず押さえる:Key Vault 参照の証明書は「バージョンなし識別子」が基本
Key Vault 連携をしているなら、ローテーションの設計を一段ラクにできる重要ポイントがあります。Key Vault の識別子(証明書の identifier)を手入力する場合、バージョン情報を含めないことです。バージョン付き URI を指定すると、Key Vault で更新しても APIM 側が自動追随しません。
また Microsoft Learn の手順では、Key Vault の証明書が更新されると APIM 側は最大で数時間(目安:4時間以内)で更新されること、必要ならポータルや管理 API で手動リフレッシュできることが説明されています。
ただしここで注意が必要です。APIM 側が自動更新して “証明書本体” は最新になっても、あなたのポリシーがサムプリントを固定参照している限り、ローテーション後の新サムプリントを参照できずに失敗する、という問題は残ります。
「certificate-id で解決できるのでは?」に対する正しい理解
APIM には、バックエンド呼び出し時にクライアント証明書を付与するための <authentication-certificate> ポリシーがあります。このポリシーは thumbprint だけでなく certificate-id(証明書リソース名) でも指定できます。さらに、Key Vault 参照の証明書を使う場合は thumbprint ではなく certificate-id を使うよう注意書きもあります(ローテーションで thumbprint が変わり、thumbprint 指定だと新しい証明書を解決できないため)。
つまり、「APIM の標準ポリシーで mTLS を張る/バックエンドへ証明書を提示する」用途なら、certificate-id に寄せるだけでローテーション耐性を上げられる可能性があります。
ただし本題の JWT 署名のために証明書オブジェクト(秘密鍵)を取り出す用途では、context.Deployment.Certificates を使う以上、取得キーがサムプリントに固定されるため、context.Deployment.Certificates["証明書リソース名"] のような書き方はできません。
王道パターン:Named Value でサムプリントを管理する
「仕様でサムプリントしか取れない」なら、運用としては サムプリントの置き場所をポリシーから分離するのが基本戦略です。もっともシンプルで効果が高いのが Named Value です。
設計の狙い
- ポリシー本体(ロジック)は固定
- 変動するのは “サムプリント文字列” だけ
- 変動要素を Named Value に逃がし、更新点を一か所に集約
実装手順
- APIM に Named Value を作成(例:
OracleCertThumbprint) - 値として現在の証明書サムプリントを保存
- ポリシーで Named Value を参照し、変数に格納
context.Deployment.Certificatesからサムプリントで取得
ポリシー(XML)例
<set-variable name="certificateThumbprint" value="{{OracleCertThumbprint}}" />
C#(ポリシー式)例:取得とエラーの見える化
失敗したときに原因調査ができるよう、「存在しない場合に何が登録されているか」をログ相当で出せる形にしておくと運用がラクです(本番ではメッセージに機密を含めないよう注意してください)。
string certificateThumbprint = context.Variables.GetValueOrDefault<string>("certificateThumbprint");
if (string.IsNullOrEmpty(certificateThumbprint))
{
throw new Exception("Certificate thumbprint is empty. Check Named Value OracleCertThumbprint.");
}
if (!context.Deployment.Certificates.TryGetValue(certificateThumbprint, out var certificate))
{
// Keys には thumbprint が並ぶため、切り分けに役立つ
throw new Exception(
$"Certificate not found for thumbprint: {certificateThumbprint}. " +
$"Available: {string.Join(", ", context.Deployment.Certificates.Keys)}");
}
// certificate を使って JWT 署名などを実施
メリット/デメリット
| 観点 | Named Value 管理 |
|---|---|
| ポリシー修正 | 原則不要(ロジック固定) |
| 変更点 | Named Value の値(サムプリント)だけ |
| 運用負荷 | ローテーションごとに更新が必要(手動だと漏れやすい) |
| 監査・管理 | 更新履歴を運用プロセスに乗せやすい |
ここまでで「回る」状態にはなりますが、手動更新が残ると結局つらいので、次は自動化が本命です。
運用を壊さない本命:サムプリント更新の自動化
Named Value を採用したら、次に考えるべきは「いつ・誰が・どうやって」更新するかです。おすすめは 更新の検知と反映を自動化し、担当者が “やることがない” 状態に寄せることです。
自動化の代表パターン
| パターン | 検知方法 | メリット | 注意点 |
|---|---|---|---|
| イベント駆動 | Key Vault 更新イベント(例:Event Grid) | 反映が速い/ムダな定期実行がない | イベント配線・例外時の再試行設計が必要 |
| 定期実行 | Timer(数分〜数十分おき) | 実装が単純/再実行で収束しやすい | 不要な実行が増える/検知が遅れる可能性 |
実装イメージ(設計の肝)
自動化の肝は「最新の証明書サムプリントを取得して、APIM の Named Value を更新する」だけです。手段は何でもよく、Azure Functions / Logic Apps / Azure Automation など、運用チームが扱いやすいものを選べます。
- Key Vault 側:ローテーション後の最新証明書(または対応するシークレット)からサムプリントを取得
- APIM 側:Named Value(例:OracleCertThumbprint)を更新
- 安全策:現在値と比較し、差分があるときだけ更新(不要な更新を抑える)
- 障害対策:更新失敗時のアラートとリトライ(運用で一番効く)
自動化を組むときのチェックポイント
- Key Vault の識別子はバージョンなしにしておく(APIM 連携側のローテーションも成立させる)
- APIM 側の更新タイミング(反映に時間差がある)を見越して、リトライや待ちを設計する
- アクセス許可は最小限にする(Key Vault は Get/List、APIM は Named Value 更新に必要な権限)
- 監視:更新が止まったときに気付ける仕組み(ログ、メトリクス、アラート)
上級パターン:ポリシーから Key Vault に直接アクセスする
どうしても「APIM に登録した証明書ストア」ではなく、実行時に Key Vault から取りたい事情がある場合は、<send-request> ポリシーで Key Vault の REST API を呼び出す設計も考えられます。
ただしこの方式は、設計・運用の難易度が一段上がります。
| 論点 | 影響 |
|---|---|
| レイテンシ | リクエストごとに Key Vault 呼び出しが増え、応答が遅くなりやすい |
| スループット制限 | Key Vault の制限・混雑の影響を直接受ける |
| 障害点 | APIM と Key Vault の両方が依存先になり、切り分けが難しくなる |
| セキュリティ | 取得データの扱い(秘密鍵相当をポリシーで扱う設計)に慎重さが必要 |
さらに、Key Vault のネットワーク要件は将来的に変わることがあります。たとえば Microsoft Learn では、Key Vault のファイアウォールで「Trusted Microsoft Services を許可」する前提が将来変わる旨の注意書きがあり、ゲートウェイからの到達性設計は固定化しない方が安全です。
そのため、実務では次の優先順位が無難です。
- まずは「APIM に Key Vault 参照の証明書を登録」+「ポリシーでは Named Value でサムプリント参照」
- 次に「Named Value 更新の自動化」で運用負荷をゼロに近づける
- 最後の手段として「ポリシーから Key Vault 直接アクセス」
「ローテーションに強い」実践的な落とし穴と対策
落とし穴:APIM 側の証明書更新と、ポリシー参照の更新は別問題
Key Vault → APIM の証明書更新が自動化されていても、ポリシーがサムプリントを固定参照している限り、参照側の更新が必要です。ここを同一視すると「証明書は更新されているのに、JWT 署名だけ失敗する」状態になります。
落とし穴:サムプリント更新だけでは足りないケースがある
JWT の世界では、ヘッダーの kid や x5t(証明書サムプリント由来の識別子)を相手が検証に使う場合があります。証明書ローテーション後は、相手側(認可サーバーやバックエンド)の公開鍵更新とタイミングがずれると、一時的に失敗することがあります。
対策としては、ローテーション手順に以下を含めると安定します。
- 相手側が新証明書(公開鍵)を受け入れるまでの “併存期間” を設ける
- APIM 側の自動更新(数時間の遅延があり得る)を見込む
- 失敗時のフォールバック(旧証明書での再署名など)が許されるなら検討する
落とし穴:障害時に調査できない
運用で一番困るのは「更新が止まっているのか」「証明書が見つからないのか」「署名が失敗しているのか」が分からない状態です。次のように “観測点” を作ると、復旧が早くなります。
- Named Value 更新処理のログ(更新前・更新後、対象の証明書名、実行結果)
- APIM 側のポリシーで、証明書未検出時に原因を特定できるエラー(過剰な情報は出さない)
- 401/403/500 の増加を監視し、ローテーションのタイミングと相関を取れるようにする
選択肢まとめ:どの方法を選ぶべきか
| 方法 | ローテーション耐性 | 実装難易度 | レイテンシ影響 | おすすめ度 |
|---|---|---|---|---|
| サムプリントをポリシーにハードコード | 弱い | 低い | なし | 短期検証のみ |
| Named Value にサムプリントを置く(手動更新) | 中 | 低い | なし | 小規模なら可 |
| Named Value + 自動更新(Functions/Logic Apps 等) | 強い | 中 | なし | 本命 |
| authentication-certificate の certificate-id を使う(用途限定) | 強い | 低い | なし | mTLS 用なら最優先 |
| ポリシーから Key Vault 直接アクセス | 設計次第 | 高い | 増える | 特殊ケースのみ |
まとめ:APIM ポリシーで “ID指定” はできないが、運用は設計で軽くできる
APIM ポリシーの context.Deployment.Certificates はサムプリントでしか取得できないため、Key Vault ローテーションでサムプリントが変わる運用は避けられません。
一方で、次の構成にすることで、実務上の手間はほぼゼロにできます。
- Key Vault 参照証明書は バージョンなし識別子で APIM に登録し、自動更新を成立させる
- ポリシーは Named Value からサムプリントを参照し、コードは固定化する
- ローテーション検知 → Named Value 更新を 自動化して運用を消す
もし “証明書を使う用途” がバックエンドへの mTLS だけなら、<authentication-certificate> の certificate-id を使うだけでローテーション耐性を上げられるケースもあります。用途を切り分けて、最小コストで安定する設計を選びましょう。

コメント