.NET 8/EF Core 7移行でSQL Server接続エラーを解決:Encrypt=true・TrustServerCertificate・証明書設定の完全ガイド

.NET 6 までは接続文字列に Encrypt を書かなくても SQL Server に普通に繋がっていたのに、.NET 8(EF Core 7/8)へ移行した途端に証明書エラーで接続できない――そんな相談が急増しています。原因は「ドライバー側の既定値が Encrypt=true に変わった」こと。この記事では、従来通りの動作をすぐに復旧する方法から、開発・本番での最適な暗号化設定、証明書導入の実務ポイントまで、現場の運用に耐えるレベルで徹底解説します。

目次

.NET 8/EF Core 7 以降で何が変わったのか

SQL Server への接続を担うクライアント・ドライバー(Microsoft.Data.SqlClient)は、バージョン 4.x 以降で 既定値の Encrypt を false→true に変更しました。EF Core 7/8 もこれを取り込み、.NET 8 のアプリでは明示しない限り TLS による暗号化とサーバー証明書の検証が行われます。

  • 接続文字列に Encrypt を書かない=Encrypt=true と同義
  • サーバー側に「信頼できる証明書」が無い/名前が一致しない → 証明書エラー
  • よくあるエラー:“The certificate chain was issued by an authority that is not trusted.”、“A connection was successfully established with the server, but then an error occurred during the pre-login handshake.”

この挙動はセキュリティ強化のための仕様です。従来の「暗号化なし」が前提の接続文字列は、アップグレード後に見直しが必要になります。

すぐに使える対処パターン早見表

目的接続文字列例解説
従来通り暗号化なしで接続したい(暫定)Server=servername;Database=dbname;Trusted_Connection=True;Encrypt=falseEncrypt を false に明示。既定値が true に変わったため、書かないと証明書検証が動いてエラーになります。
開発環境だけ証明書検証を無視して暗号化したいServer=localhost;Database=dbname;Trusted_Connection=True;Encrypt=true;TrustServerCertificate=true通信自体は暗号化(TLS)のまま、TrustServerCertificate で証明書チェーン検証をスキップ。ローカル開発・CI向け。本番では非推奨。
本番環境で安全に暗号化したいEncrypt=true を維持し、信頼されたサーバー証明書を SQL Server に導入ルート CA で信頼された証明書を使えば TrustServerCertificate は不要。FQDN の一致と SAN 設定が重要。

パラメータの意味と既定値(EF Core 7/8/Microsoft.Data.SqlClient)

キー意味既定値注意点
Encryptネットワーク通信を TLS で暗号化するかtrue暗号化を無効化すると盗聴リスク。やむを得ない場合の暫定手段に限定。
TrustServerCertificateサーバー証明書のチェーン検証を省略するかfalse開発用途のみ推奨。本番で true は中間者攻撃に脆弱。
HostNameInCertificate証明書の CN/SAN として期待するホスト名を明示未設定接続で IP を使う場合やエイリアス使用時の“名前不一致”対策に有効。
Trusted_Connection / Integrated SecurityWindows 認証の利用未設定SQL 認証なら User ID と Password を使用。

環境ごとの接続文字列設計(安全な運用モデル)

構成ポリシー

  • 開発:Encrypt=true;TrustServerCertificate=true(ローカルや一時的な開発 DB)。
  • ステージング:できる限り本番同等の正式証明書を配布。TrustServerCertificate=false。
  • 本番:Encrypt=true を堅持。信頼されたサーバー証明書を必須。

appsettings.*.json の例

環境ごとに接続文字列を分離します。ASP.NET Core なら環境変数 ASPNETCORE_ENVIRONMENT で自動切替できます。

{
  "ConnectionStrings": {
    "Default": "Server=localhost;Database=SampleDb;Trusted_Connection=True;Encrypt=true;TrustServerCertificate=true"
  }
}
{
  "ConnectionStrings": {
    "Default": "Server=stg-sql.example.local;Database=SampleDb;Encrypt=true;TrustServerCertificate=false"
  }
}
{
  "ConnectionStrings": {
    "Default": "Server=prod-sql.example.com;Database=SampleDb;Encrypt=true"
  }
}

EF Core(DbContext)での設定例

builder.Services.AddDbContext<AppDbContext>(options =>
    options.UseSqlServer(
        builder.Configuration.GetConnectionString("Default"),
        sql => sql.EnableRetryOnFailure())); // 接続自動再試行(推奨)

ADO.NET(SqlConnectionStringBuilder)での例

var csb = new SqlConnectionStringBuilder
{
    DataSource = "prod-sql.example.com",
    InitialCatalog = "SampleDb",
    Encrypt = true,
    TrustServerCertificate = false,
    IntegratedSecurity = true
};
using var conn = new SqlConnection(csb.ConnectionString);
await conn.OpenAsync();

エラーの代表例と対処の対応表

エラーの抜粋原因対処
The certificate chain was issued by an authority that is not trusted.自己署名または未知の CA による証明書正式 CA のサーバー証明書に置換。暫定なら TrustServerCertificate=true を開発限定で使用。
The target principal name is incorrect.接続先名と証明書の CN/SAN が不一致(IP で接続、別名使用など)FQDN で接続/DNS を修正/HostNameInCertificate を設定。
Pre-login handshake errorTLS ハンドシェイク失敗(古いプロトコルや暗号スイート)OS/SQL Server の TLS 設定を更新。最新パッチ適用。

本番での正攻法:SQL Server に正式証明書を配備する

企業内 CA や公的 CA で発行したサーバー証明書を SQL Server に割り当てます。ポイントは「名前の一致」と「鍵の扱い」です。

要件

  • 鍵長 2048bit 以上、Key Usage = Digital Signature / Key Encipherment。
  • EKU に Server Authentication (1.3.6.1.5.5.7.3.1)。
  • CN または SAN に 接続で使用する FQDN(例:prod-sql.example.com)。
  • 秘密鍵はコンピューター アカウントに所有権。SQL Server サービス アカウントに読み取り権限。

Windows(オンプレ/VM)の手順概要

  1. 証明書を「ローカル コンピューター → 個人(Personal)」ストアへインポート(秘密鍵付き)。
  2. SQL Server 構成マネージャー → SQL Server ネットワークの構成 → プロトコル → 証明書 タブで割り当て。
  3. 必要なら「強制暗号化(Force Encryption)= 有効」にし、SQL Server サービスを再起動。
  4. SELECT encrypt_option FROM sys.dm_exec_connections WHERE session_id = @@SPID; で暗号化状態を確認。

Linux/コンテナでのポイント

  • サーバー秘密鍵(PEM)と証明書チェーン(PEM)を SQL Server が参照するパスへ配置し、権限を適切に設定。
  • Docker では証明書をボリュームでマウント。開発用は TrustServerCertificate=true を併用して構築の複雑さを抑える。

開発・CI の現実解:安全性と利便性の落としどころ

ローカル開発や短命の CI データベースに正式証明書を配るのはコストが高い場面が多いでしょう。次の方針が実務的です。

  • ローカル/CI:Encrypt=true;TrustServerCertificate=true。接続先は原則 localhost(または開発用 DNS)に限定。
  • 機微データを扱う検証環境:本番同等の証明書を導入して TrustServerCertificate=false を維持。
  • 接続先省略や IP 指定を避ける:証明書の名前一致に失敗しやすい。

名前不一致に強い設定:HostNameInCertificate の活用

DNS エイリアスや可用性グループのリスナー名を使う場合、証明書の CN/SAN と接続先名が一致するように設計するのが原則です。どうしても一致しない事情があるときは、接続文字列に HostNameInCertificate を付けて「証明書にはこの名前が入っているはず」を明示できます。

Server=10.0.0.12;Database=AppDb;Encrypt=true;
HostNameInCertificate=prod-sql.example.com;TrustServerCertificate=false

ただし、恒久対策は DNS と証明書の正規化です。暫定利用に留めましょう。

Azure SQL / マネージド DB を使う場合

  • 管理サービスは既に信頼された証明書を配備済みのため、原則 Encrypt=true のままで問題ありません。
  • ファイアウォールやプライベート エンドポイントを併用し、IP 接続ではなく FQDN 接続に統一します。

EF Core の移行で見落としがちな差分

  • ドライバーの乗り換え:System.Data.SqlClient と Microsoft.Data.SqlClient は別物。EF Core 7/8 は後者を使用。
  • リトライとタイムアウト:暗号化切替直後はネットワーク負荷やスキャンの影響で遅延が出ることも。EnableRetryOnFailure と CommandTimeout を設計に入れる。
  • 接続プール:設定変更後はアプリのリサイクルや再起動でプールをクリア。

セキュリティ観点の推奨事項(チェックリスト)

  • 本番は Encrypt=true 固定、TrustServerCertificate=false。
  • 証明書の CN/SAN と接続 FQDN の厳密一致を確認(IP 接続を避ける)。
  • サーバー証明書の 有効期限監視と 自動更新(ACME/企業内 CA)を整備。
  • アプリ設定は 環境ごとに分離(appsettings.Development.json / .Production.json)。
  • ログに 接続文字列の資格情報を書き出さない(PII マスク)。

運用テスト:暗号化の有効性を確認する

T-SQL で現在セッションを確認

SELECT session_id, encrypt_option
FROM sys.dm_exec_connections
WHERE session_id = @@SPID;
-- encrypt_option が TRUE なら暗号化済み

アプリ側での簡易確認

接続が確立できない場合は例外メッセージの先頭数行をログに残しておくと原因特定が早くなります(ただし秘密情報はマスク)。

Docker Compose を使った開発テンプレート(最小構成)

開発用途として、証明書配布の手間を省きつつ暗号化を保つ例です。

services:
  sql:
    image: mcr.microsoft.com/mssql/server:2022-latest
    environment:
      - ACCEPT_EULA=Y
      - SA_PASSWORD=Your_strong_password_123
    ports:
      - "1433:1433"
  web:
    build: .
    environment:
      - ConnectionStrings__Default=Server=localhost,1433;Database=AppDb;
        User ID=sa;Password=Your_strong_password_123;
        Encrypt=true;TrustServerCertificate=true

この場合、通信は暗号化されますが証明書の真正性は検証しません。本番構成では必ず正式証明書に切り替えてください。

移行計画の作り方:ゼロダウンタイムを狙う手順

  1. 現行の接続文字列を棚卸しし、Encrypt と TrustServerCertificate の有無を洗い出し。
  2. 本番 SQL Server に正式証明書を先行配備(Force Encryption はまだ無効)。
  3. アプリ側で Encrypt=true を有効にして段階リリース。動作ログで証明書エラーの無いことを確認。
  4. 最後に SQL Server 側の Force Encryption を有効化(必要な場合)。

Q&A(現場でよく聞かれること)

Q. とりあえず Encrypt=false に戻すのはダメ?

A. 緊急避難としては有効ですが、平文通信になり盗聴のリスクがあります。恒久対策は正式証明書の導入です。

Q. TrustServerCertificate=true はどこまで許される?

A. 開発・CI まで。本番や機微データを扱う環境では禁止を推奨します。

Q. IP アドレスで接続しても大丈夫?

A. 証明書は通常 FQDN ベースで発行されるため、IP では名前不一致になりやすいです。FQDN で接続しましょう。

Q. Always On 可用性グループ/リスナー名は?

A. 証明書の SAN にリスナー名を含め、アプリもリスナー名(FQDN)で接続します。

まとめ

.NET 8/EF Core 7 以降では Encrypt=true が既定になりました。アップグレード後の証明書エラーは「バグ」ではなく「正しい保護」が働いた結果です。短期的に従来動作へ戻す方法(Encrypt=false)もありますが、推奨される道は「正式証明書を導入し、Encrypt=true を維持する」こと。開発では TrustServerCertificate=true を活用して利便性を確保しつつ、ステージング以降は本番同等の暗号化・検証を適用する――この二段構えが、セキュリティと生産性の両立に最も効きます。

付録:すぐに使える接続文字列スニペット集

用途スニペット
ローカル開発(Windows 認証)Server=(localdb)\\MSSQLLocalDB;Database=DevDb;Encrypt=true;TrustServerCertificate=true;Trusted_Connection=True
ローカル開発(SQL 認証)Server=localhost;Database=DevDb;User ID=sa;Password=***;Encrypt=true;TrustServerCertificate=true
オンプレ本番(正式証明書)Server=prod-sql.example.com;Database=AppDb;Encrypt=true;TrustServerCertificate=false;Integrated Security=true
名前不一致が避けられない暫定Server=10.0.0.12;Database=AppDb;Encrypt=true;HostNameInCertificate=prod-sql.example.com

付録:トラブルシューティング・フロー

  1. 接続文字列に Encrypt が無ければ 明示追加(true か false)。
  2. Encrypt=true で失敗したらメッセージに「chain」「principal name」等の文字列が無いか確認。
  3. 「chain」系なら信頼されていない証明書 → 正式証明書に置換 or 開発限定で TrustServerCertificate=true。
  4. 「principal name」系なら名前不一致 → FQDN で接続/DNS 修正/HostNameInCertificate。
  5. 改善しなければ SQL Server の ERRORLOG と OS のイベントログを確認。TLS のバージョン/暗号スイート設定を見直し。

最後に:判断の基準

  • 可搬性:FQDN と正規の証明書に揃えるほど移行や DR が楽。
  • 最小権限:証明書の秘密鍵権限は SQL Server サービス アカウントのみに限定。
  • 監査性:設定変更・証明書更新はチケット化し、満了前に自動アラート。

これらを押さえておけば、.NET 8 への移行後もエラーに足を取られず、安全な暗号化通信を当たり前の前提として運用できます。

この記事を書いた人

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

コメント

コメントする

目次