Azure App Service を Application Gateway 経由で公開しているのに、PCでは問題ないのに iPhone など iOS 端末だけ「証明書に問題があります」と警告が出る――。この手のトラブルは“端末依存”に見えて、実は「証明書失効(revoked)」が根本原因になっていることがあります。実例ベースで、原因の見抜き方と復旧手順をまとめます。
今回の構成と発生していた症状
対象は、Azure App Service(Windows Webアプリ)をバックエンドに置き、Application Gateway をフロントにして公開しているWebサイトです。TLS/SSL証明書は Azure 管理の有料証明書(発行元 GoDaddy)を利用していました。
- Windows / macOS(PC)からは HTTPS が正常に見える
- iPhone など iOS 端末からは、一部端末だけ「証明書に問題がある」旨の警告が出る(Safari/Chrome等ブラウザ種類に依存しない)
- SSL診断サイトの結果が割れる
- SSL Shopper:問題なし
- SSL Labs:発行者ステータスが revoked(失効) と表示
- Azure ポータル上では証明書が“正常”に見える
| 観測された現象 | ありがちな誤解 | 実際に疑うべきポイント |
|---|---|---|
| PCではOK、iOSだけ警告 | iPhoneの不具合/Safariの問題 | 失効チェック(OCSP/CRL)の差、または端末ごとのキャッシュ差 |
| SSL ShopperはOK | 証明書自体は正常 | チェーンや期限中心の検査で、失効まで厳密に追わないことがある |
| SSL Labsでrevoked | 診断サイト側の誤判定 | 実際に配信されている証明書が失効している可能性が高い |
| Azureポータルは正常表示 | Azureが正しいと言うなら正しい | ポータルは「リソースとしての証明書」を見ているだけで、最前段(App Gateway)が配信している証明書とは別の場合がある |
なぜ「一部のiOS端末だけ」警告になるのか
まず押さえておきたいのは、同じサイトでもクライアント(OS/ブラウザ/ネットワーク)によって「証明書の検証の厳しさ」や「失効情報の取り扱い」が異なる点です。
特に iOS は、証明書失効(revoked)に関する扱いが比較的シビアに見えるケースがあります。端末によって挙動が割れるのは、次のような要因が重なるためです。
- 失効情報の取得結果が端末ごとに変わる(OCSP/CRLの取得可否、ネットワーク条件、社内プロキシ、モバイル回線など)
- 中間証明書や失効情報のキャッシュ状況が端末で違う(以前に別の証明書にアクセスした履歴が影響することもある)
- 同じドメインでも経路や終端が複数存在(CDNや複数リスナー、複数Front Door/AGW、WAFの切替など)し、端末によって別系統に当たっている
そのため「特定のiPhoneだけ警告」でも、証明書側に原因がある可能性は十分にあります。ここで重要なのが、“実際に配信されている証明書が何か”を確定することです。
根本原因:証明書が CRL 上で「失効(revoked)」になっていた
今回のケースは、SSL Labs が示したとおり、対象サイトの証明書が 証明書失効リスト(CRL)上で「失効」として扱われていました。さらに失効理由(Reason Code)が Superseded(後継証明書に置き換え済み) だった、というのがポイントです。
Superseded は「新しい証明書を発行してそちらに切り替えた(あるいは切り替えるべき)」という文脈で登場します。つまり、運用としては次のような状態に陥りやすいです。
- 更新・再発行のプロセスで 新しい証明書は確かに作られた
- しかし、Application Gateway のリスナー(最前段)に反映されていない
- 結果として、外部へは 古い(失効済み)証明書 を配信し続けている
この状態だと、Azure ポータル上で「証明書リソースは正常」に見えても矛盾しません。なぜなら、ポータルが見ているのは “証明書の管理情報” であって、クライアントに提示されている証明書そのものではないからです(特に Application Gateway が証明書終端の場合)。
ドメイン検証(DV)の問題なのか?
結論から言うと、今回のパターンでは ドメイン検証(DV)が原因でiOSだけ警告 という線は薄いです。DVが失敗していると、そもそも証明書が発行できない/発行後にチェーンが不整合になるなど、もっと広範囲に影響が出やすいからです。
一方で「失効(revoked)」は、発行自体は成立しているのに、後から“使ってはいけない証明書”としてマークされる状態です。PCではたまたま警告が出ない場合があっても、iOSや一部環境では容赦なく弾かれます。
切り分けの要点:どの機器が“どの証明書”を配っているかを特定する
Application Gateway を使っている構成では、「App Service にバインドしている証明書」と「Application Gateway のリスナーにバインドしている証明書」が一致しているとは限りません。まずは最前段が提示する証明書を基準に確認します。
確認するべき情報
- 証明書のシリアル番号(Serial Number)
- 有効期限(Not Before / Not After)
- サムプリント(Thumbprint / SHA-1 / SHA-256)
- 発行者(Issuer) と 中間証明書チェーン
現場で速い確認方法
診断サイト(SSL Labsなど)の結果に加えて、手元端末で「いま配られている証明書」を直接確認すると早いです。
- ブラウザの証明書表示(PCのChrome/Edge等)で、シリアル番号や発行者、期限を控える
- 可能なら OpenSSL で確認する(例:証明書の提示内容を確認)
openssl s_client -connect example.com:443 -servername example.com -showcerts
この出力に含まれるサーバ証明書のシリアル番号が、SSL Labs で「revoked」と表示されているものと一致するなら、原因はほぼ確定です。
復旧の基本方針:失効済み証明書を“配信経路から完全に排除”する
復旧で重要なのは、「証明書を更新したつもり」ではなく、外部に提示される証明書が確実に新しいものへ切り替わったことを確認することです。Application Gateway 終端の場合、ここが最も事故りやすいポイントになります。
| ポイント | なぜ重要か | 確認のコツ |
|---|---|---|
| Application Gateway リスナー | クライアントが最初に見る証明書の出所 | リスナーに紐づく証明書のシリアル/期限を必ず照合 |
| App Service のバインド | バックエンドでもTLS終端/再暗号化しているなら影響 | AGWがエンドツーエンドTLSの場合は特に要確認 |
| Key Vault の参照バージョン | 参照が古いバージョン固定だと更新が反映されない | 「最新を参照」になっているか、更新後に再設定したか |
| 古い設定の残骸 | 意図せず古い証明書に戻る、または一部経路だけ古い | 複数リスナー/複数ホスト名/ルールの漏れを潰す |
復旧手順:Azure管理の有料SSL証明書を継続する場合
「Azure管理の有料証明書(GoDaddy発行)」をそのまま使い続けるなら、原則は 再発行(re-issue / re-key)して、新しい証明書を正しい場所に再バインド です。ポイントは “再発行しただけで終わらない” ことです。
手順の全体像
- 証明書を再発行(更新・再キー生成を含む)
- 新証明書を Application Gateway のリスナーに反映
- 必要に応じて App Service 側のバインドも更新
- 古い(失効済み)証明書の参照を削除・置換
- 外部から配信される証明書が切り替わったことを検証
手順を“確実にする”ための実務メモ
- リスナー単位で置き換える:Application Gateway はホスト名ごとにリスナーが分かれていることが多く、「一部だけ古い証明書が残る」事故が起きがちです。
- WAF/複数フロントがあるなら経路を固定して検証:DNSの向き先が複数あると、端末ごとに違う経路へ当たり「一部端末だけ警告」を助長します。
- 反映後は必ずシリアル番号で確認:期限だけ見ても同日に再発行されると紛らわしいため、シリアル番号やサムプリントで照合します。
Key Vault 連携で混乱しやすいポイント
今回の環境では、証明書更新の過程で Key Vault 周りが複雑化していました。実際の現場でも同様の混乱は頻発するため、整理しておくと再発防止に効きます。
起きていた状況(典型例)
- PFX をエクスポートした際、パスワードが空(null)に見えて混乱(インポート時にパスワード無しでエラーになるなど)
- 手動でシークレットを作成した結果、正しい秘密鍵が含まれない“壊れたシークレット”ができた
- Key Vault に「現在のバージョン」と表示されるものが壊れている一方、少し古いが実際には有効でエクスポート可能なバージョンが残っていた
ここで重要なのは、証明書は「公開鍵だけ」では成立しないという点です。Application Gateway や App Service にバインドするには、原則として 秘密鍵付き(PFXなど)である必要があります。手動で値を埋めたシークレットが「証明書っぽい文字列」でも、秘密鍵がなければTLS終端としては使えません。
Key Vault の“証明書関連オブジェクト”を区別する
| 種類 | 中身 | よくある落とし穴 | おすすめの扱い |
|---|---|---|---|
| Certificate | 証明書としての管理単位(発行・更新の設定も含む場合がある) | 見た目は“証明書”だが、参照先がSecret/Keyと絡み混乱する | Key Vaultで運用するなら「Certificate」としてインポート/更新し、整合性を保つ |
| Secret | PFX(Base64)などの実体が入ることが多い | 手動で作ると秘密鍵が欠ける、または形式が崩れる | 原則、手動生成は避け、正規の手順で生成されたものを使う |
| Key | 秘密鍵 | 証明書とキーの対応がズレると復旧が泥沼化 | 証明書更新時は「証明書と秘密鍵のペア」で管理する |
“壊れたシークレット”は削除してよいか?
一般論としては、すでに Application Gateway / App Service に手動アップロード済みの PFX を使っているだけなら、Key Vault 内のシークレットを削除しても即座に影響しないケースが多いです。
ただし、次の条件に当てはまる場合は注意が必要です。
- Application Gateway が Key Vault 参照で証明書を取得している(ローテーションもKey Vault前提)
- App Service 証明書と Key Vault が 自動連携されており、App Service側が “現在のバージョン” を参照している
この場合、削除によって参照が壊れ、復旧がさらに難しくなることがあります。安全に整理するなら、まず「現在どこがKey Vaultを参照しているのか」を確定し、運用方針(Key Vault連携で自動更新したいのか/手動アップロードに寄せるのか)を一度シンプルに決めるのが近道です。
実務的に最短で直す解決策:証明書プロバイダーごと新規発行に切り替える
理屈としては「再発行+正しいバインド」で直せますが、Key Vault連携や既存リソースの状態が複雑だと、原因箇所の特定に時間が溶けやすいのが現実です。今回のケースでも、最終的には次の“割り切った解決策”が最も早く確実でした。
やったこと(再現性の高い手順)
- 別のSSLプロバイダーから 新規にSSL証明書を購入(低価格帯でも可)
- ローカルPCで 秘密鍵付きPFX としてエクスポート(任意のパスワードを設定)
- そのPFXを Application Gateway にアップロードしてリスナーへバインド
- 同じPFXを App Service にもアップロードしてバインド(構成に応じて)
- 必要に応じて、バックアップ用途として Key Vault に「証明書」としてインポート
この方法のメリットは、Azure管理証明書+Key Vault同期の“ブラックボックス度”を一度リセットできる点です。何より、外部に提示される証明書が明確に切り替わるため、SSL Labs などの診断結果と実態が一致しやすくなります。
この方法が向いているケース
- 期限切れではなく失効(revoked)が絡んでいて、とにかく早く復旧させたい
- Key Vault に壊れたシークレットが混在していて、正しいバージョン追跡が難しい
- 運用上「自動更新」にこだわらず、まずは安定稼働を優先したい
復旧後の確認:iOSの警告が消えたかを“外形”でチェックする
証明書の差し替えは、差し替えた本人が「更新した」と思っていても、実際には古い証明書が残っているケースがあります。復旧後は必ず外形監視的に確認します。
- SSL Labs で revoked 表示が消えたこと(できればシリアル番号も確認)
- 複数ネットワーク(社内Wi‑Fi/モバイル回線など)で同じ結果になること
- iOS の複数端末(問題が出た端末/出なかった端末)で再確認すること
- Application Gateway の複数リスナー・複数ホスト名があるなら、全ホストで同様に確認すること
再発防止のための運用チェックリスト
- 証明書更新のたびに「シリアル番号」を記録し、切替後の配信証明書と照合する
- Application Gateway のリスナーが複数ある場合、ホスト名ごとに置換漏れがないかをチェックする
- Key Vault 参照の場合、参照が“特定バージョン固定”になっていないかを見直す(更新が反映されない典型原因)
- Key Vault に手動でシークレットを作らず、秘密鍵付きPFXの正規インポートに統一する
- SSL診断は複数使うが、矛盾したら「実際に配信されている証明書」を最優先で確認する
よくある質問
SSL Shopperで問題なしなのに、SSL Labsでrevokedになるのはなぜ?
診断サイトごとに、チェックの深さや参照する失効情報が異なることがあります。今回のように revocation(失効)に起因する問題は、失効の追跡が深いツールほど先に検知しやすいです。矛盾した場合は、ツールの結果だけで判断せず、OpenSSL等で「実際の配信証明書」を確定させるのが安全です。
「Superseded」なら、なぜ古い証明書を配ってしまうの?
更新・再発行で“新しい証明書”が作られても、Application Gateway のリスナーが古い証明書を参照し続けていれば、外部には古い証明書が提示され続けます。特に Key Vault を挟む場合は、参照の向き先(バージョン)が固定されていると、更新があっても自動で切り替わりません。
iOSだけ警告が出るなら、iOS側の設定で回避できる?
業務サイトの運用としては、クライアント側で失効チェックを無理に回避するのは現実的ではありません(セキュリティ上の観点でも推奨されません)。サーバ側で失効していない正しい証明書を配信するのが唯一の健全な解決策です。
まとめ
PCでは問題なく見えるのに、iOS端末でだけSSL警告が出るときは、まず「証明書失効(revoked)」を疑うのが近道です。今回のケースでは、CRL上で Superseded として失効扱いになっている証明書が配信され続けたことが根本原因でした。
正攻法は「再発行(re-issue / re-key)+Application Gateway/ App Service への正しいバインド」ですが、Key Vault 連携が絡んで状態が複雑な場合は、別プロバイダーで新規発行してPFXを手動アップロードする方が早く確実に復旧できることもあります。いずれの方法でも、最後は必ず “外部から見える証明書” が切り替わったことを、シリアル番号ベースで検証して締めるのが再発防止のポイントです。

コメント