Windows Server 2016で作成したActive Directory 証明書サービス(ADCS)をWindows Server2022の環境に移行する検証を行いました。
公式ドキュメントに沿って実施しましたが、いくつかの注意点、躓いたポイントを紹介します。
■躓きポイント 一覧
新規CAサーバ構築前に旧CAサーバを削除する必要があるのか
レジストリバックアップについて
有効期限が延長されたCRL発行について
復元時のレジストリ修正
GUIでの動作確認(GUI側エラー対応)
非常にニーズの少ない検証だと思いますが記録として残しています。
なお、移行の検証行ったのはスタンドアロンCAで、非フェールオーバークラスタ環境です。
まず、MSドキュメントとしては以下を参考にしました。
この通りに実行すれば基本的には問題無いのですが、非常にドキュメントが長く、わかり辛い部分もあります。
新規CAサーバ構築前に旧CAサーバを削除する必要があるのか
まず最初に躓いたのは、下記リンクの引用部分です。
以下文章をどのように解釈すればよいか迷いました。
バックアップ手順を完了した後、Active Directory Certificate Services サービス (Certsvc) を停止して、より多くの証明書の発行を防ぐ必要があります。 CA 役割サービスを宛先サーバーに追加する前に、CA 役割サービスをソース サーバーから削除する必要があります。
移行を簡略化するには、これらの手順で作成したバックアップ ファイルを同じ場所に格納する必要があります。 この場所には、移行先サーバーからアクセスできる必要があります。
この文章は、「旧 CA のアンインストールは必須ではないが、AD 上の競合を避けるために停止と登録情報の削除が推奨される」 というこを意味しています。しかしながら、新環境ADCSを構築する前に、旧環境ADCSを削除するというのは必須ではなく、旧環境ADCSの停止 という操作で代替できます。
また、後半の文章、「この場所には、移行先サーバーからアクセスできる必要があります」というのも回りくどく、直ぐにわからなかったです。要するに、新環境でCAを復元するときに利用するので新環境サーバ上に配置しておいてください(新環境サーバーからアクセス可能な場所に配置しておいてください)ということのようです。
なお、以下部分でも同様のことが記載されています。
バックアップ手順を完了した後、移行先サーバーに CA 役割サービスをインストールする前に、ソース サーバーから CA 役割サービスを削除することが重要です
移行元 CA と移行先 CA は同じ共通名を共有するため、移行先サーバーに CA 役割サービスをインストールした後にソース サーバーから CA 役割サービスを削除すると、移行先 CA に必要な構成データが削除され、その操作が妨げられます。
また「警告」で以下のようにも記載されています。
推奨されませんが、一部の管理者は、移行が失敗した場合にソース CA を迅速にオンラインにできるように、ソース サーバーに CA 役割サービスをインストールしたままにすることを選択できます。 移行先サーバーへの移行が完了した後は、ソース サーバーから CA 役割サービスを削除しないでください。
エンタープライズ CAもスタンドアロン CAも、CA名に紐づいた構成データを Active Directory に登録します。その為、
移行では「旧CA」と「新CA」が同じ CA名を持つため、AD DS上では同じオブジェクトを参照します。
もし新CAをインストールした後に旧CAを削除すると、新CAが必要とする構成データまで消えてしまい、移行が壊れる可能性があります。
その可能性(必要な新CAのデータまで削除されないように)旧CAの役割サービスを事前に削除することが推奨されているのです。
しかし、繰り返しますが、旧CA機能の事前アンインストールは必須ではなく、旧CAサーバを停止し、新CAサーバと同時に起動しないように注意しておけば問題はありません。事前に実施しないと移行ができないような記載にも見えるのですが、あくまで推奨です。
ドキュメントには、「(新CAサーバの)コンピューター名をソース サーバーと同じ名前に変更します」という手順まで記載されています。これは、後述するレジストリ設定での不整合を回避する推奨方法ですが、この手順にしても、レジストリを適切に修正することができれば、必須ではありません。旧CAサーバと新CAサーバのコンピュータ名が異なっていても、移行は可能です。
レジストリバックアップについて
続いて、レジストリバックアップ 部分です。
には以下のような記載があります。DBバックアップのときはタブで分かれているのに、急にGUIとCUIの手順が並記されているのでわかり辛いです。以下抜粋部分は同じことを言っています。

レジストリのバックアップは結局、以下のようなコマンドで取得すれば問題ありません。
reg export “HKLM\SYSTEM\CurrentControlSet\Services\CertSvc\Configuration“ “C:\work\REG\ca_config_backup.reg“
もちろん、GUI上から取得しても問題ありません。
レジストリについては、CA復元時に、躓くポイントになることが多いので、確実にバックアップするようにしましょう。
有効期限が延長されたCRL発行について
続いて、以下の延長CRLの部分です。
以下文章をどのように解釈すればよいか迷ったので記載します。
CA の移行を開始する前に、計画された移行期間を超える有効期間の CRL を発行することをお勧めします。CRL の有効期間は、少なくとも移行のために計画されている時間の長さである必要があります。
これは、移行期間中にクライアント コンピューター上の証明書検証プロセスを続行できるようにするために必要です。
移行する CA ごとに有効期間が延長された CRL を発行する必要があります。
この手順は、CRL の使用不能の影響を受ける可能性のある証明書が多数存在する可能性があるため、ルート CA にとって特に重要です。
既定では、CRL の有効期間は CRL 発行期間に 10% を加えたものになります。
適切な CRL の有効期間を決定したら、CRL 発行間隔を設定し、次の手順を実行して CRL を手動で発行します。証明書失効リストの公開をスケジュールし、 証明書失効リストを手動で発行します。
こちらは、CA を移行している間に「失効リスト(CRL)」が期限切れにならないように、
移行期間をカバーできる有効期限が長めの CRL を事前に発行しておきましょう、という意味です。
ここでいう「移行期間」とは 旧 CA 停止 から 新 CA 稼働までのCA空白時間のことを指します。
なぜ有効期限が長めのCRLが必要かというと、
移行中は旧 CA が停止し、新 CA がまだ稼働していないため、CRL の更新ができません。この間に CRL が期限切れになると、クライアントは証明書検証に失敗してしまうからです。
移行期間をカバーできる長さの CRL を事前に発行しておけば、クライアントはその CRL を使い続けられるため認証エラーを防げます。
ただし、もちろん有効期限を長めにしたCRLを保持していないクライアントが、移行期間中にアクセスした場合、CRLを再取得しようとする為、当然証明書検証は失敗します。延長 CRL は 「移行期間中の認証エラーを減らすための低減策」であり、完全な解決策ではありません。
なお、ドキュメントの「重要」という注意事項にも記載されていますが、
CRL を長くしすぎると「失効した証明書が長期間有効に見えてしまう(=失効している証明書で認証が通ってしまう)」ため、あくまで移行期間をカバーできる最小限の延長にとどめることがセキュリティ的には安全と言えます。
CRLの期間調整とは別に、「移行期間(CA不在期間)をできるだけ短くすること」これが最も重要だと思います。
以下に、現在のCRL有効期限の確認、変更手順を記載します。
■現在のCRL有効期限確認
Powershellで赤文字のコマンドを実行してください。デフォルト設定から変更していない環境であれば以下戻り値となるはずです。
PS C:\Users\certAdmin> certutil -getreg CA\CRLPeriod
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\CertSvc\Configuration\pxtserver-CA\CRLPeriod: CRLPeriod REG_SZ = Weeks
CertUtil: -getreg コマンドは正常に完了しました。PS C:\Users\certAdmin> certutil -getreg CA\CRLPeriodUnits
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\CertSvc\Configuration\pxtserver-CA\CRLPeriodUnits: CRLPeriodUnits REG_DWORD = 1
CertUtil: -getreg コマンドは正常に完了しました。
PS C:\Users\certAdmin>
まず、上記コマンドでCRL の発行間隔が確認できます。発行間隔は「1週間ごと」です。(単位がWeeksで値が1です)
CRL の「有効期間」は、この発行間隔に 10% を加えた値になります(既定動作)。
つまり、上記設定では、1週間(7日)+10%(0.7日)=約7.7日間有効な CRL が発行されます。
■CRL有効期限変更
Powershellで以下コマンドを順番に実行してください。青字部分は、必要によって変更してください。
certutil -setreg CA\CRLPeriodUnits 30
certutil -setreg CA\CRLPeriod “Days”
上記は、CRL の発行間隔を「30日ごと」に設定しています。
CRLPeriodUnits 30 → 単位の数値を 30 に設定
CRLPeriod “Days” → 単位を「日」に設定
という具合です。この場合、
30日 × 1.1 = 33日間有効な CRL が発行されます。
設定変更後は CA サービスの再起動が必要になる場合がある為、変更を行った場合は、以下を続けてコマンドするのがよいです。
net stop certsvc
net start certsvc
certutil -crl
証明書サービスを再起動し、
certutil -crl で、 新しい CRL を即時発行しています。設定値変更後は、「■現在のCRL有効期限確認」で値の変更を確認することも可能です。
なお、CRL有効期限を変更した場合、CA移行完了後は、元の値に切戻しておいた方がよいです。有効期限が長すぎるCRLはセキュリティリスクになる為です。
復元時のレジストリ修正
続いて、新CAサーバで、旧CAサーバのレジストリを復元する以下手順部分です。
まず、記載のとおり、新CAサーバで旧CAサーバで実行したのと同じ手順で、レジストリのバックアップを取得しましょう。

上記ドキュメントの、「重要」では、要するに、旧CAサーバのレジストリを復元するけれども、設定値によっては新CAサーバの値が必要になるよ、と言っています。
この後、以下のように何度もこれと同じようなことを言っている注意書きが掲載されています。


レジストリの修正が非常に重要で、間違ったパラメータがあると正常動作しない可能性がある為です。
新サーバでレジストリのバックアップを取得した後は、旧サーバのレジストリとの差分を事前に確認しておきましょう。

比較時に注意が必要だとおもったレジストリ値を記載します。
| [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\CertSvc\Configuration] | ||
| キー名 | サンプル値 | 意味 |
| Active | sys-pxtCertServer-CA | 現在アクティブな CA インスタンス名。AD CS がこの CA として動作中。 |
| DBDirectory | C:\Windows\system32\CertLog | CA データベースファイル(cert.edb)の保存場所。 |
| DBLogDirectory | C:\Windows\system32\CertLog | トランザクションログ(*.log)の保存場所。 |
| DBTempDirectory | C:\Windows\system32\CertLog | 一時ファイル(*.tmp)の保存場所。 |
| DBSystemDirectory | C:\Windows\system32\CertLog | システムファイル(*.chk など)の保存場所。 |
| WebClientCAMachine | pxtCertServer.sys.pxt.internal | Web Enrollment クライアントが接続する CA サーバーの FQDN。 |
| WebClientCAName | sys-pxtCertServer-CA | Web Enrollment クライアントが使用する CA の表示名。 |
| WebClientCAType | 3 | CA の種類:3 はエンタープライズ CA。 |
| DBLastFullBackup | hex:… | CA データベースの最終フルバックアップ日時(FILETIME形式)。 |
まず、DBDirectory,DBLogDirectory,DBTempDirectory,DBSystemDirectoryの値は、旧CAサーバと新CAサーバで揃っている必要があります。これらは、DB関連ファイルのパス指定である為、このファイルパスにDBファイルを配置してやる必要があります。これらの整合性がとれていないと(レジストリ値と実体がそろっていないと)証明機関サービスが正常起動しません。
青字の、WebClientCAMachine、WebClientCAName、WebClientCATypeは、旧CAサーバにのみ存在し、新CAサーバには存在しませんでした。この差分については害はないようです。これらは、
「Web Enrollment(Webベースの証明書要求)」機能に関連するレジストリ値です。 機能インストール時の選択で「証明機関(Certification Authority)」の役割だけをインストールした場合には生成されません。 つまり、Web Enrollment 機能をインストールしていない新 CA サーバーにこれらの値が存在しないのは正常です。
新CAサーバの機能インストールについては、ドキュメントの以下箇所で、CA移行に関しては最初に「証明機関」の役割を最初にインストールするように指示がありました。

その為、ドキュメントどおりに進んだ場合で、旧CAサーバにWeb Enrollement機能をインストールしていた場合、差分として表示される可能性があります。
この差分状態のままレジストリをインポートしても害は無いようですが、Web Enrollement機能をインストール予定ではない場合、値を削除しておいた方がよいようです。筆者はそのままインポートしましたが、害はありませんでした。
| [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\CertSvc\Configuration\sys-pxtCertServer-CA] | ||
| キー名 | サンプル値 | 意味 |
| DSConfigDN | CN=Configuration,… | AD の構成コンテナ DN。CA の登録情報が格納される。 |
| DSDomainDN | DC=ppt,… | CA が属する AD ドメインの DN。 |
| CAServerName | pxtCertServer.sys.pxt.internal | CA サーバーの FQDN。 |
赤字のCAServerName は旧CAサーバのサーバ名と、新CAサーバのサーバ名が異なる場合、要修正です。
旧CAサーバのレジストリをそのままインポートしただけでは動作に支障をきたしてしまう可能性があります。このレジストリは、インポート後に正しい値に修正する必要があります。
事前に新旧サーバのレジストリ値をよく比較しておき、インポート作業に臨んでください。
レジストリ値インポートは、GUI上でregファイルをダブルクリックすることでもよいですが、以下のようにコマンドラインでも可能です。
net stop certsvc
reg import <<インポート対象レジストリバックアップファイル.reg>>
net stop certsvcで証明機関サービスを停止してからインポートしてください。reg importコマンドの戻り値は一見エラーのように見えますが、正しく終了しました と表示されていれば正常終了です。
PS C:\Users\CertAdmin> reg import “C:\work\REG\ca_config_backup.reg”
reg : この操作を正しく終了しました。 発生場所 行:1 文字:1
+ reg import “C:\work\REG\ca_config_ba … ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : NotSpecified: (この操作を正しく終了しました。:String) [], RemoteException + FullyQualifiedErrorId : NativeCommandError
PS C:\Users\pptadmin>
上記操作の後、事前に確認していたとおり、
CAServerName を移行先のホスト名に合わせて修正してください。その他、 パスやドライブ文字が異なる場合(DBDirectoryなどの値の修正が必要な場合)も、移行先環境に合わせて修正しましょう。
手順に沿って、CA移行作業を進めてきた前提ですが、レジストリ値復元の後、以下のような形で正常性確認が取れます。(基本的にはMSドキュメントに沿う形で実施すればよく、以下は参考です。筆者はレジストリ設定などで躓いた為、このような確認に行きつきました)
まず、サービス起動前に、データベースの整合性を確認します。
esentutl /g “C:\Windows\System32\CertLog\<CA名>.edb”
esentutl /g コマンドでデータベース整合性確認が可能です。ファイルパス、<CA名>部分は適宜置き換えてください。
実行例は以下です。
PS C:\Users\CertAdmin> esentutl /g “C:\Windows\System32\CertLog\pxtserver-CA.edb”
Extensible Storage Engine Utilities for Microsoft(R) Windows® Version 10.0 Copyright (C) Microsoft Corporation.
All Rights Reserved. Initiating INTEGRITY mode…
Database: C:\Windows\System32\CertLog\pxtserver-CA.edb Temp.
Database: .\TEMPINTEG984.EDB Checking database integrity.
Scanning Status (% complete)
0 10 20 30 40 50 60 70 80 90 100
|—-|—-|—-|—-|—-|—-|—-|—-|—-|—-|
……………………………………………
Integrity check successful.
Operation completed successfully in 2.141 seconds.
PS C:\Users\CertAdmin>
「successful」と表示されれば、DB整合性は問題ありません。
上記表示を確認後、サービスを起動します。
net start certsvc
起動したサービスが正常に応答しているかどうかは、以下コマンド実行でチェックできます。
certutil -ping
GUIでの動作確認(GUI側エラー対応)
ドキュメントに記載のとおり、
までの手順を実行すれば、手順としては完了です。「宛先 CA で証明書拡張機能を確認する」、「 証明機関スナップインを使用して拡張機能を確認する」、「証明書テンプレートの一覧を復元する」などは必要に応じて実施してください。先述したリンク「CAを復元する」という手順の中で、DBとレジストリの復元が完了していれば、証明機関のGUIが起動できるはずです。※「フェールオーバー クラスタリングの追加手順」も本Blogでは実行していません。必要に応じて実施してください。
証明機関 のGUIを起動すると、正常に起動はするものの、各証明書の情報を閲覧しようとすると、MMC上で以下のようなエラーが発生したことがあります。

「指定されたファイルが見つかりません。0x80070002(WIN32:2 ERROR_FILE_NOT_FOUND)」
このようなエラーが出た場合、まずは、公式ドキュメントの記事通りに作業してきたかを確認してください。特に、本記事で記載した、
をしっかりと確認してください。DB格納場所のパスが間違っていないか、新CAの物理サーバ名は正しく設定されているか、などです。
上記、全ての設定が正しいのに、なぜか、MMC上でだけ上記エラーが発生してしまう、という方は以下をお試しください。
※筆者はこの事象にハマって数日を費やしました。もし、同じような事象の方がいた場合に参考になると幸いです。
・新規でコマンドラインから証明書を発行し、OS再起動
・それでもだめならWindowsUpdateを実施する
というものです。
1.INFファイル用意
まず、以下をコピーしてtest.infファイルとして保存します。
[Version]
Signature=”$Windows NT$” [NewRequest]
Subject = “CN=TestUser”
KeySpec = 1
KeyLength = 2048
Exportable = TRUE
MachineKeySet = TRUE
SMIME = FALSE
PrivateKeyArchive = FALSE
UserProtected = FALSE
UseExistingKeySet = FALSE
RequestType = PKCS10
KeyUsage = 0xA0
2.INFから要求ファイル(REQ)を生成
「1」で作成したinfファイルを引数に、以下のようにコマンドします。
certreq -new test.inf test.req
これで、test.reqファイルが作成されます。
コマンド例です。「要求が作成されました」と表示され、test.reqファイルが作成されれば成功です。
PS C:\Users\certAdmin> certreq -new “C:\pxtwork\test.inf” “C:\pxtwork\test.req”
CertReq: 要求が作成されました
3.要求ファイルを CA に提出
「2」で作成したtest.reqを引数に以下のようにコマンドします。
certreq -submit test.req
コマンド例です。「提出されています」と表示されれば成功です。
PS C:\Users\certAdmin> certreq -submit “C:\pxtwork\test.req” 要求 ID: 2 要求 ID: “2” 証明書の要求は保留中です: 提出されています (0)
PS C:\Users\certAdmin>
4.要求を承認して発行
「3」で実行した際に表示された要求ID、及びFQDN+CA名 を引数に要求を承認します。
certutil -config <CA_FQDN\>¥<CA_NAME> -resubmit <RequestID>
コマンド例は以下です。FQDNが「pxtCertServer.sys.pxt.internal」、CA名が「sys-pxtCertServer-CA」、要求IDが「2」の場合の例です。
certutil -config “pxtCertServer.sys.pxt.internal\sys-pxtCertServer-CA” -resubmit 2
PS C:\Users\certAdmin> certutil -config “pxtCertServer.sys.pxt.internal\sys-pxtCertServer-CA” -resubmit 2 証明書は発行されました CertUtil: -resubmit コマンドは正常に完了しました。
PS C:\Users\certAdmin>
1~4が実施できた場合、証明機関の機能的な動作としては正常であり、MMC上の表示だけがおかしいということになります。上記が実施出来た後は、OS再起動 or WindowsUpdateを行ってください。
「指定されたファイルが見つかりません」というエラーが消えて、旧CAサーバで発行済みの証明書が表示できれば、成功です。

筆者が検証したのは、Windows Server 2022で、Windows Updateの修正パッチに証明機関(ADCS)に関連するものはありませんでした。しかし、何故か、最新パッチをあてて解決したこともあるので、ここに記しておきます。
以上、非常にニッチな話題となり恐縮ですが、どこかで、誰かの役に立てることを、祈ります。

(この記事が参考になった人の数:2)