Azure APIM から Azure Functions を呼び出すと「SSL/TLS のセキュア チャネルを作成できません」になる原因と対処法

Azure API Management(APIM)経由で Azure Functions を呼ぶと「SSL/TLS のセキュア チャネルを作成できません」とだけ表示され、内部モード+VNet 接続+プライベート エンドポイントなど要素が多いと、原因がどこにあるのか分かりにくくなります。本記事では、実際に発生しやすい構成を例に、TLS バージョン不一致を中心とした原因と、切り分け・解決の具体的な手順を整理します。

目次

事象の概要:APIM(内部モード)から Functions を呼ぶと TLS エラー

今回の想定シナリオは次のような構成です。

  • Azure API Management:Internal モード(VNet 内部)
  • バックエンド:Azure Functions(関数アプリ / App Service)
  • APIM の「テスト(Test)」画面からバックエンドを呼び出すと失敗

APIM のトレースログでは、次のようなエラーが記録されます。

forward-request ... "The request was aborted: Could not create SSL/TLS secure channel."

日本語のポータル画面では「SSL/TLS のセキュア チャネルを作成できませんでした」と表示されることもあります。

このメッセージはあくまで「TLS のハンドシェイクが確立できなかった」という意味であり、HTTP レベル(ステータスコード 4xx/5xx)まで到達していません。ネットワーク(VNet / NSG / プライベート エンドポイント)ではなく、TLS レイヤでこけていることがポイントです。

構成の整理:どこで TLS が張られているのか

今回のような構成では、主に下図の TLS 経路を意識する必要があります。

経路送信元宛先TLS の役割
① クライアント → APIMブラウザ / アプリAPI Management の公開 FQDNインターネット経由の TLS。公開証明書。
② APIM → FunctionsAPIM(Internal モード)関数アプリ(appname.azurewebsites.net など)今回ここで失敗。APIM がバックエンドへ HTTPS で接続。

テスト画面で実行したリクエストは、最終的に ② の経路で Functions に送られます。したがって、今回のエラーはほぼ確実に 「APIM → Functions 間の TLS」 に起因します。

よくある勘違い:「プライベート エンドポイントがないと TLS に失敗する?」

Internal/VNet 構成だと、どうしても「プライベート エンドポイント周り」を疑いがちです。しかし、今回のような 『SSL/TLS のセキュア チャネルを作成できません』 エラーは、プライベート エンドポイントの有無とは直接関係ありません。

観点プライベート エンドポイントの役割今回のエラーとの関係
主目的トラフィックを VNet 内に閉じる(閉域化・ゼロトラスト強化)なし(TLS が通る / 通らないは別問題)
通信の可否DNS 解決結果とルーティングを変える到達不可ならタイムアウト等。TLS エラーとは別タイプ。
TLS ハンドシェイク関与しない(暗号処理はサーバ/クライアントの設定次第)TLS バージョンや証明書設定の方が支配的

プライベート エンドポイントは「セキュリティ/到達性」の話であり、今回の TLS エラーの一次原因ではないと考えるのが合理的です。

今回の主因:関数アプリの「最小 TLS バージョン」不一致

もっとも多いパターンが、関数アプリ側で設定している 最小 TLS バージョン と、APIM 側が利用する TLS バージョンが噛み合っていないケースです。

典型的な例:

  • 関数アプリの「最小 TLS バージョン」が 1.3 に固定されている
  • APIM のアウトバウンド通信が TLS 1.2 までしか話せないリージョン/SKU/内部実装で動いている
  • 結果として、APIM → Functions のハンドシェイクが成立せず、
    「Could not create SSL/TLS secure channel」が返る

実際の現場では、関数アプリ側の「最小受信 TLS バージョン」を 1.2 に戻した瞬間に問題が解消するケースが非常に多いです。

関数アプリの TLS 設定を確認する手順(ポータル)

Azure ポータルからの確認手順は次の通りです。

  1. 対象の 関数アプリ を開く
  2. 左メニューの「設定」→「構成」を選択
  3. 「全般設定」タブを開く
  4. 「最小受信 TLS バージョン」 の項目を確認
  5. 推奨値は TLS 1.2
    (APIM と Functions の両方がサポートするバージョンに揃える)
  6. 値を変更したら「保存」→「再起動」が必要な場合は再起動
項目変更前(例)変更後(例)備考
最小受信 TLS バージョンTLS 1.3TLS 1.2APIM が 1.3 を話せない場合にエラーとなる

ポータルから変更して反映を待ち、再度 APIM のテスト画面から呼び出して成功するか確認します。

スクリプトから TLS 設定を変更する(補足)

Infrastructure as Code(IaC)運用をしている場合は、CLI で最小 TLS を揃えると管理しやすくなります。例えば Azure CLI の場合:

az functionapp config set \
  --resource-group <リソースグループ名> \
  --name <関数アプリ名> \
  --min-tls-version 1.2

ARM/Bicep/terraform などでも同等のプロパティがあるため、APIM と Functions の両方について「最小 TLS 1.2」に揃えておく設計が安全です。

原因候補その2:相互 TLS(mTLS/クライアント証明書)の要求

Azure Functions 側で クライアント証明書必須(mTLS) にしている場合、APIM がクライアント証明書を提示しなければ TLS ハンドシェイクで失敗します。この場合も「SSL/TLS のセキュア チャネルを作成できません」といったメッセージで見分けがつきにくくなります。

設定パターンAPIMFunctions結果
通常の TLS のみ証明書提示なしクライアント証明書:無視成功(サーバ証明書のみで確立)
mTLS だが APIM 側未設定証明書提示なしクライアント証明書:必須ハンドシェイク失敗(今回のようなエラー)
mTLS 完全構成クライアント証明書提示クライアント証明書:必須成功(クライアント証明書で認証)

Functions 側の mTLS 設定を確認する

関数アプリの mTLS 設定は、ポータルでは次の場所で確認できます。

  1. 対象の関数アプリを開く
  2. 「設定」→「構成」→「全般設定」
  3. 「クライアント証明書モード」 の値を確認
クライアント証明書モード意味APIM からのアクセスへの影響
無視クライアント証明書を送っても見ないAPIM 側で証明書設定がなくても OK
任意送られてくれば参照するが必須ではないAPIM 側で証明書がなくても TLS 自体は成立
必須クライアント証明書がないと拒否APIM から証明書を提示しないと TLS 失敗

mTLS が要件として不要であれば、まずは 「無視」 に変更して状況が改善するかを確認するのが手っ取り早いです。

APIM からクライアント証明書を提示する設定例

要件上、Functions 側で mTLS を必須にしたい場合には、APIM にクライアント証明書を登録し、特定のバックエンド呼び出しで提示させる必要があります。

  1. APIM の「証明書」ブレードでクライアント証明書(.pfx)をアップロード
  2. 証明書のサムプリント(thumbprint)を控える
  3. 該当 API のポリシーを編集し、authentication-certificate を追加
<policies>
  <inbound>
    <base />
    <authentication-certificate thumbprint="<証明書のサムプリント>" />
  </inbound>
  <backend>
    <base />
  </backend>
  <outbound>
    <base />
  </outbound>
  <on-error>
    <base />
  </on-error>
</policies>

証明書の CN/SAN と Functions 側で検証するホスト名が一致しているか、ルート CA が信頼されているかも忘れずに確認してください。

原因候補その3:証明書チェーンやホスト名の問題

TLS バージョンや mTLS 設定が正しい場合でも、サーバ証明書側の問題でハンドシェイクが失敗することがあります。

  • 独自ドメイン(カスタムドメイン)+独自証明書を利用している
  • 中間 CA 証明書が正しく連結されていない
  • 証明書の有効期限が切れている
  • APIM から見たときのホスト名と証明書の CN/SAN が一致していない

特に多いのが、中間証明書を含まないチェーン不備の証明書です。ブラウザから直接 Functions にアクセスしたときは OS が補完してくれて気づきにくいのに、APIM からの接続では素直に失敗する、というパターンがあります。

チェック項目確認方法の一例
証明書の有効期限ブラウザ、OpenSSL、証明書ビューアなどで確認
証明書チェーンの正当性OpenSSL の s_client -showcerts などで検証
ホスト名と CN/SAN の一致APIM が接続している FQDN と証明書の SAN を突き合わせ

Azure Functions / App Service の既定ドメイン(.azurewebsites.net)をそのまま使っている場合は、Microsoft 管理の証明書が使われるため、この種の問題は起きにくいですが、カスタムドメイン利用時には必ず確認しておきたいポイントです。

プライベート エンドポイントは「必須」ではないが推奨

繰り返しになりますが、プライベート エンドポイント(PE)がないことが今回の TLS エラーの原因ではありません。しかし、社内システムとして閉域に閉じたいケースでは、関数アプリにも PE を張るのが実運用としてはベストプラクティスです。

プライベート エンドポイントを使う場合のチェックポイント

  • Functions 用のプライベート エンドポイントを作成
    • ターゲットタイプ:Web サイト(azurewebsites.net)
    • 接続先 VNet / サブネットは APIM と同じ、またはルーティングで到達可能なもの
  • プライベート DNS ゾーン:privatelink.azurewebsites.net を作成
  • プライベート DNS ゾーンを VNet にリンク(APIM が属する VNet)
  • NSG / UDR で 443/TCP がブロックされていないことを確認
目的設定TLS エラーへの影響
閉域化PE + プライベート DNS直接の原因にはならないが、到達不能だと別種のエラーになる
TLS ハンドシェイク証明書、TLS バージョン、mTLS今回のエラーの主因はこちら側

まとめると、「TLS の合意(バージョン・証明書)」と「ネットワークの到達性(PE / DNS)」は別レイヤの話であり、それぞれを独立して切り分けることが重要です。

切り分けに使えるチェックリスト

実際に調査する際は、次の順番で確認していくと原因に辿り着きやすくなります。

1. 関数アプリの最小 TLS バージョン

  • ポータルまたは IaC 定義で 「最小受信 TLS バージョン」= TLS 1.2 になっているか
  • 変更した場合は「保存」後に再試行する
  • App Service プランを共有する他のアプリにも影響がないか確認

2. mTLS(クライアント証明書)の有無

  • クライアント証明書モードが「必須」になっていないか
  • mTLS が必要な場合:
    • APIM にクライアント証明書を登録済みか
    • 該当 API のポリシーで <authentication-certificate> を設定しているか
  • mTLS が不要な場合:
    • まずは Functions 側のモードを「無視」にして挙動を確認

3. サーバ証明書/カスタムドメイン設定

  • カスタムドメインを使っている場合は、証明書の有効期限・チェーンを確認
  • APIM からアクセスしている FQDN と証明書の CN / SAN が一致しているか
  • 中間 CA 証明書が欠落していないか(特に手動アップロード時)

4. ネットワーク(プライベート エンドポイント / DNS / NSG)

  • APIM と Functions(またはそのプライベートエンドポイント)が同じ VNet、もしくはピアリングされた VNet 内か
  • プライベート DNS ゾーン privatelink.azurewebsites.net が正しく構成・リンクされているか
  • サブネットの NSG / UDR で 443/TCP がブロックされていないか

APIM のテスト画面以外からの確認も有効

APIM のテスト画面だけを見ていると、「APIM なのか Functions なのか」「TLS なのかネットワークなのか」が切り分けづらいことがあります。VNet 内の別 VM から直接 Functions に対して curl したり、Invoke-WebRequest を投げたりしてみると、問題のレイヤが見えやすくなります。

# 例:VNet 内のテスト VM から
curl -v https://&lt;your-function-app-name&gt;.azurewebsites.net/api/health

ここで同様に TLS エラーが発生する場合は、APIM ではなく Functions 側の証明書/TLS 設定に問題がある可能性が高くなります。一方で、テスト VM からは成功するのに APIM だけ失敗する場合は、APIM の SKU / リージョン特性(サポートする TLS バージョンや暗号スイート)や、APIM 側のネットワークルールを疑うべき状況です。

実運用でのベストプラクティス

今回のようなトラブルを避けるために、設計段階で次のような方針を決めておくと運用が楽になります。

1. 「TLS 1.2 を共通の最低ライン」にする

  • APIM、Functions、App Service、他のバックエンドすべてで、最小 TLS 1.2 を前提に設計する
  • TLS 1.0 / 1.1 はセキュリティ観点から廃止する方向で統一する
  • TLS 1.3 を有効にする場合は、1.2 と併用し「1.3 のみ」にしない

2. mTLS を使う場合は「証明書ライフサイクル」を仕組み化

  • クライアント証明書の有効期限をカレンダー/監視に登録
  • 更新手順(APIM 側の入れ替え、Functions 側の検証方法など)をドキュメント化
  • ステージング環境での疎通確認を自動化(例:APIM から Functions へのヘルスチェック API)

3. プライベート エンドポイントと DNS をテンプレート化

  • Functions / Web Apps / Storage など、PE を張るリソースごとに標準テンプレートを用意
  • プライベート DNS ゾーンの作成&リンクも IaC 化し、手作業による設定漏れを防ぐ
  • APIM の VNet にすべての必要なプライベート DNS ゾーンをリンクしておく

まとめ:調査の優先度とおすすめの進め方

最後に、今回の「Azure APIM 経由で Azure Functions をテストすると『SSL/TLS のセキュア チャネルを作成できません』になる」問題を解決するうえでの、おすすめの調査・対応順を整理します。

  1. 最小 TLS バージョンを揃える
    • まずは関数アプリの「最小受信 TLS バージョン」を TLS 1.2 に設定
    • APIM 側も TLS 1.2 を話せる前提で設計
  2. mTLS(クライアント証明書)の設定を確認
    • mTLS が不要なら Functions 側のクライアント証明書モードを「無視」に
    • mTLS が必要なら、APIM にクライアント証明書を登録し、ポリシーで authentication-certificate を設定
  3. サーバ証明書(特にカスタムドメイン)を再確認
    • 有効期限、チェーン、中間証明書、CN/SAN とホスト名の一致をチェック
  4. ネットワーク(PE / DNS / NSG)の整合性を確認
    • プライベート エンドポイントと privatelink.azurewebsites.net の DNS 設定
    • 443/TCP をブロックする NSG / UDR がないか

重要なのは、「TLS の合意(バージョン・証明書)」を最優先で確認し、そのうえでネットワーク構成(プライベート エンドポイントや DNS)を整理するという順番です。プライベート エンドポイントはセキュリティ強化・閉域化のためには非常に有用ですが、今回のような「SSL/TLS のセキュア チャネルを作成できません」エラーそのものの根本原因ではないことを押さえておきましょう。

この記事が、Azure API Management と Azure Functions を組み合わせた構成で TLS 周りのトラブルに遭遇した際の、原因切り分けと再発防止の一助になれば幸いです。

この記事を書いた人

実務の現場で詰まりがちなポイントを地図にするITブログ「IT trip」を運営。Windows/Office(Teams・Excel)からSQL、サーバ運用、ガジェットまで、再現性のある手順と“なぜそうなるか”を丁寧に解説します。読んだらすぐ試せること、そして迷った人の次の一歩が見えることを大切にしています。

コメント

コメントする

目次