AWS Managed Microsoft AD + AD CS で実現する Client VPN 証明書自動配布・失効管理
2026/10/08
はじめに
社内リモートアクセス基盤として AWS Client VPN を採用する際、多くの現場で悩ましいのが「クライアント証明書の配布・更新・失効」の運用ですよね。証明書を手作業で発行・配布していては、対象端末が増えるたびに管理コストが跳ね上がり、退職者や紛失端末への対応も後手に回りがちになってしまいます。
本記事では、以下の要件を満たす構成を、AWS Managed Microsoft AD と AD CS(Active Directory Certificate Services) を組み合わせて構築した際の手順を、実際に検証したフローに沿ってまとめます。
満たすべき要件
- クライアント端末に保管する証明書の秘密鍵は、エクスポートできないようにする
- 端末へのクライアント証明書配布は自動化する(ドメイン参加すれば自動配布)
- 証明書の有効期限到来時、ドメイン参加している状態なら自動更新される
- ドメイン参加先は AWS Managed Microsoft AD
- AD を管理するサーバーは Windows Server(ここに AD CS を同居)
- 端末紛失・端末返却・職員退職時に、確実に証明書を失効させる構成
全体アーキテクチャ
ポイントは、AWS Client VPN が 「サーバー証明書」 と 「クライアントCA証明書」 という役割の異なる2種類の証明書を要求するという点です。この役割を混同すると最初の一歩でつまずくため、まず全体像を押さえておきます。
| 証明書 | 用途 | ACMでの登録先 |
|---|---|---|
| CA(ルート)証明書 | クライアント証明書の信頼元 | クライアントCA証明書 ARN |
| サーバー証明書 | VPNサーバーが端末に提示する身分証明書 | サーバー証明書 ARN |
| クライアント(コンピューター)証明書 | 端末がVPNサーバーに提示する身分証明書 | 端末のローカル証明書ストアのみ(ACM登録不要) |
それでは、実際の構築手順を順に見ていきましょう。
Step 0〜1: 前提となる基盤の準備
Step 0: AD CSの役割追加準備
Windows Server の「サーバーの役割追加」から Active Directory Certificate Service の機能を有効化する準備を行います(実際のインストールは Step 6 で PowerShell から実施します)。
Step 1: AWS Managed Microsoft AD の構築
AWSマネジメントコンソールから AWS Managed Microsoft AD を構築します。ドメイン名は今回 hyron.example とする。
Step 2〜5: 管理用サーバーの準備とドメイン参加
Step 2: 管理用ドメインユーザーの作成
管理用のドメインユーザーを作成し、AWS Delegated Administrators グループに所属させます。AWS Managed Microsoft AD では、オンプレミスのAD CSのようにドメイン管理者権限を直接扱えないため、このグループへの所属が AD CS 構築における実質的な管理者権限として機能します。
Step 3〜4: AD管理用Windowsサーバーの構築とドメイン参加
AD CSを同居させる管理用のWindows Serverを構築し、AWS Managed Microsoft ADへドメイン参加させます。
注意点: ドメイン参加の事前に、ネットワークアダプターのDNS設定をAD(Managed AD)のDNS IPアドレスに向けておく必要があります。これを怠るとドメインが名前解決できず参加に失敗します。参加後は必ずPCを再起動する。
Step 5: 特権管理者でのログイン
AD特権管理者(hyron\Admin 等)で、AD管理用のWindowsサーバーへログインします。
Step 6〜7: AD CS(エンタープライズ ルートCA)の構築
Step 6: 証明書サービスのインストール
管理者権限のPowerShellで以下を実行します。
Install-WindowsFeature Adcs-Cert-Authority -IncludeManagementTools
Step 7: CAセットアップウィザードの実行
サーバーマネージャーの通知(黄色い旗)から「対象サーバーにActive Directory証明書サービスを構成する」を実行し、以下の設定で進めます。
| 項目 | 設定値 |
|---|---|
| 資格情報 | hyron\Admin であることを確認 |
| 役割サービス | 証明書機関 |
| セットアップの種類 | エンタープライズ CA (Enterprise CA) |
| CAの種類 | ルート CA (Root CA) |
| 秘密キー | 新しい秘密キーを作成する |
| 暗号化プロバイダー | RSA#Microsoft Software Key Storage Provider |
| キーの長さ | 2048 |
| ハッシュアルゴリズム | SHA256 |
| 秘密キーのエクスポート許可 | 必ずチェックを入れる |
| CAの共通名 | 既定値(例: hyron-CA) |
| 有効期間 | 10年 |
重要: ここで「暗号化プロバイダーによって提供される秘密キーのエクスポートを許可する」に必ずチェックを入れておきます。これを怠ると、後の Step 11 でルートCA証明書を秘密鍵付きでエクスポートしようとした際に、ACMインポートに必要な .pfx 形式でのエクスポートができなくなります(ACMの import-certificate API は証明書の種別を問わず秘密鍵とのセットでのインポートを必須とするため)。
有効期間を10年としているのは、この後発行するサーバー証明書(10年)・クライアント証明書(1年、自動更新あり)が、CA自身の有効期間を超えないようにするためです。
Step 8〜10: クライアント(端末用)証明書テンプレートの構成
ここが今回の要件①(秘密鍵エクスポート禁止)と②③(自動配布・自動更新)を実現する中核部分です。
Step 8: 端末用自動更新証明書テンプレートの作成
certtmpl.msc を開き、標準テンプレート 「ユーザー (User)」 を複製して、以下の通り設定します。
設計上の重要ポイント: 複製元は「ユーザー」テンプレートですが、後述の Subject Name タブと GPO の設定(コンピューターの構成側)により、実質的にコンピューター単位で証明書を扱う構成にしています。ユーザー単位で運用すると、AWS Client VPN Desktop Client が端末のログインユーザーストアではなく LocalMachine ストアの証明書を優先的に参照する実装上の癖と噛み合わず、接続に失敗するケースがあるため、コンピューター証明書として扱う設計としています。
① 全般 (General) タブ
- テンプレート表示名: ClientVPN-AutoEnroll-Template
- 有効期間: 1年、更新期間(Renewal period): 6週間
- 「Active Directoryで証明書を発行する」: チェックON
② 要求処理 (Request Handling) タブ
- 「プライベートキーのエクスポートを許可する」: チェックOFF(未チェック)のまま
これにより要件①(端末から秘密鍵を持ち出せないようにする)が実現されます。
③ 互換性 (Compatibility) タブ
- 証明書機関: Windows Server 2016
- 証明書の受信者: Windows 10 / Windows Server 2016
④ セキュリティ (Security) タブ
- 「追加」→ SG-ClientVPN-Computers を検索して追加(※このグループは Step 10 で作成するため、テンプレート設定はグループ作成後に仕上げます)
- 以下3つにチェック:
- 読み取り(Read)
- 登録(Enroll)
- 自動登録(Autoenroll)
⑤ Subject Name タブ
- Subject Name format: 「Common name」を選択
- 「Include this information in alternate subject name」: ☑ DNS name
ハマりやすいポイント: この項目が既定の None のままだと、発行された証明書の Subject(CN)フィールドが空になり、コンピューター名はSAN(Subject Alternative Name)にのみ格納されます。.ovpn ファイルで指定する cryptoapicert “SUBJ:…” は Subject(CN)を文字列検索する仕組みのため、Subjectが空の証明書は接続時に一切ヒットせず「ローカル証明書が見つからない」エラーになります。必ずCommon nameを選択してください。
すべて設定できたら「適用」→「OK」で保存します。
Step 8-5: テンプレートのアクティブ化
certsrv.msc を開き、「証明書テンプレート」フォルダを右クリック→「新規作成」→「発行する証明書テンプレート」から ClientVPN-AutoEnroll-Template を選択して有効化します。
Step 9: グループポリシー(GPO)による自動配備の有効化
gpmc.msc を開き、以下の手順でGPOを作成・設定します。
- 対象ドメイン(hyron.example)直下の「Group Policy Objects」を右クリック→新規作成、名前は GPO-ClientVPN-AutoEnroll
- 作成したGPOを編集し、以下の階層へ移動:
コンピュータの構成 > ポリシー > Windowsの設定 > セキュリティの設定 > 公開キーのポリシー (Public Key Policies)
- 「証明書サービス クライアント – 自動登録」を開き、以下を設定: – 構成モデル: 有効 (Enabled) – ☑ 期限切れの証明書を更新、保留中の証明書を破棄、およびエクスポートされた証明書を自動更新する – ☑ 証明書テンプレートを使用する証明書を更新する
上記2つのチェックが、要件③「有効期限到来時に自動更新される」の実体です。証明書の有効期間の残りが少なくなると、Windowsのバックグラウンド処理がこのポリシーに基づき自動的に更新要求をCAへ送信します。
-
「適用」→「OK」
-
対象ドメイン配下 hyron OU の「Computers」フォルダを右クリック→「Link an Existing GPO…」→ GPO-ClientVPN-AutoEnroll を選択してリンク
重要: GPOの設定場所が「コンピュータの構成」であり、リンク先もコンピューターオブジェクトが配置されるOU(Computers)である点が、この構成の肝です。ユーザーの構成側に設定してしまうと、狙い通りのコンピューター単位の自動登録にはなりません。
- 反映確認(管理者権限のPowerShellで実行):
powershell
certutil -CATemplates
一覧に ClientVPN-AutoEnroll-Template が表示されればOKです。
Step 10: クライアント端末から証明書自動配布する許可設定
自動登録の対象を制御するための専用セキュリティグループを作成します。
New-ADGroup -Name "SG-ClientVPN-Computers" `
-GroupScope Global `
-GroupCategory Security `
-Path "OU=Computers,OU=hyron,DC=hyron,DC=example"
Get-ADGroup -Identity "SG-ClientVPN-Computers"
対象PCがドメイン参加してコンピューター名が判明した時点で、以下のコマンドでグループに追加します(この作業は端末を追加するたびに毎回必要です)。
Add-ADGroupMember -Identity "SG-ClientVPN-Computers" -Members "対象PC名$"
コンピューターアカウントを指定する際は、ホスト名の末尾に $ を付ける必要があります。これを忘れると Cannot find an object with identity エラーになります。
Get-ADGroupMember -Identity "SG-ClientVPN-Computers"
追加できたことを確認したら、Step 8④で保留にしていたテンプレートのセキュリティタブに戻り、SG-ClientVPN-Computers へ「読み取り」「登録」「自動登録」を正式に許可します。
Step 11: CA証明書のエクスポートとACMへのインポート
Client VPNの「クライアントCA証明書 ARN」に登録するため、AD CSのルートCA証明書を秘密鍵付きでエクスポートし、ACMにインポートします。
なぜ秘密鍵が必要か: 「CA証明書は公開鍵だけで良いのでは」と考えがちですが、AWS ACMのimport-certificateAPIは証明書の種類を問わず必ず秘密鍵とのセットでのインポートを要求します。 これはAWS ACMの仕様上の制約です。
CA証明書(秘密鍵付き)のエクスポート
- 管理サーバーで mmc を起動
- 「ファイル」→「スナップインの追加と削除」→「証明書」を追加
- 管理対象は「コンピューター アカウント」→「ローカル コンピューター」を選択
- 「個人」→「証明書」フォルダを開き、CA証明書(例: hyron-CA)を右クリック→「すべてのタスク」→「エクスポート」
エクスポートウィザードでは以下を選択します。
| 項目 | 設定 |
|---|---|
| 秘密キーのエクスポート | 「はい、秘密キーをエクスポートします」に必ずチェック |
| ファイル形式 | 個人情報交換 – PKCS #12 (.PFX)(既定のまま) |
| セキュリティ | パスワードにチェックし、任意のパスワードを設定 |
| 暗号化 | AES256-SHA256 |
補足: ルートCA自体からこの方法でエクスポートする場合と、CAバックアップウィザード(すべてのタスク → CA証明書のバックアップ)を使う場合の2通りがありますが、いずれの方法でも「秘密キーとCA証明書」の両方を含む形でエクスポートできていれば問題ありません。
AWS CloudShellでのPEM変換とACMインポート
エクスポートした .pfx ファイルをCloudShellにアップロードし、以下を実行します。
# CA秘密鍵の抽出(パスワードを聞かれるので、エクスポート時に設定したものを入力)
openssl pkcs12 -in hyron-ca.pfx -nocerts -nodes -out adcs-root-ca.key
# CA証明書(公開鍵)の抽出
openssl pkcs12 -in hyron-ca.pfx -clcerts -nokeys -out adcs-root-ca.crt
# 東京リージョンのACMへインポート
aws acm import-certificate \
--certificate fileb://adcs-root-ca.crt \
--private-key fileb://adcs-root-ca.key \
--region ap-northeast-1
実行結果として返る CertificateArn を記録しておきます(後のClient VPN構築で使用)。
セキュリティ上の注意: ルートCAの秘密鍵をAWS側にアップロードすることは、PKI全体の信頼の根幹をAWSに渡すことを意味します。より安全性を高めたい場合は、ルートCA自体ではなく、Client VPN専用の「下位(中間)CA」を発行し、その秘密鍵をACMにインポートする方式を検討してください。
証明書が正しくCA証明書として認識されるかは、以下のコマンドで事前確認できます。
openssl x509 -in adcs-root-ca.crt -noout -text | grep -A3 "Basic Constraints"
# X509v3 Basic Constraints: critical
# CA:TRUE
Step 12〜13: サーバー証明書の構成とACMへのインポート
Client VPNの「サーバー証明書 ARN」に登録するため、AD CSからサーバー用の証明書を個別に発行します。
役割の混同に注意: ACMの「サーバー証明書 ARN」のプルダウンには、自身がCA(認証局)である証明書は自動的に除外される仕様のため、Step 11でインポートしたルートCA証明書はここには表示されません。サーバー証明書はCAとは別の、エンドエンティティ証明書として個別に発行する必要があります。
Step 12: サーバー証明書テンプレートの構成
certtmpl.msc で標準テンプレート 「Web Server」 を複製し、以下を設定します。
① 全般タブ
- テンプレート表示名: ClientVPN-Server-Template
- 有効期間: 10年、更新期間: 6週間
- 「Active Directoryで証明書を発行する」: チェックON
② 要求処理タブ
- 「プライベートキーのエクスポートを許可する」: チェックON(サーバー証明書はACMへ秘密鍵付きでインポートするため必須)
③ 互換性タブ
- 証明書機関: Windows Server 2016
- 証明書の受信者: Windows 10 / Windows Server 2016
④ セキュリティタブ
- Authenticated Users に対して、以下3つが「許可」になっていることを確認(Full Controlでも可):
- 読み取り(Read)
- 登録(Enroll)
- 自動登録(Auto-Enroll)
設定後、certsrv.msc の「証明書テンプレート」から ClientVPN-Server-Template を新規発行として有効化します。
Step 13: サーバー証明書のリクエストとエクスポート
- 管理サーバーで mmc を起動し、「個人」→「証明書」を右クリック→「すべてのタスク」→「新しい証明書を要求」
- ウィザードを進め、ClientVPN-Server-Template の警告マークをクリックして詳細設定に入る
- サブジェクト名: – 種類: 共通名(Common Name) → 値: Server-hyron.example → 追加 – 別名: 種類: DNS → 値: Server-hyron.example → 追加
- 適用し、警告が消えたことを確認して「登録」
発行された証明書を、Step 11と同様の手順(mmc → エクスポート → 秘密キー付き.PFX → CloudShellでPEM変換)でACMへインポートします。
openssl pkcs12 -in hyron-server.pfx -nocerts -nodes -out vpn-server.key
openssl pkcs12 -in hyron-server.pfx -clcerts -nokeys -out vpn-server.crt
aws acm import-certificate \
--certificate fileb://vpn-server.crt \
--private-key fileb://vpn-server.key \
--region ap-northeast-1
こちらも CertificateArn を記録しておきます。
Step 14: Client VPNエンドポイントの構築
Client VPNエンドポイントの構築については、本記事では割愛させていただきます。
Step 15: .ovpn設定ファイルの構成
Client VPNエンドポイントからダウンロードした基本の .ovpn ファイルに、以下を追記します。
cryptoapicert "SUBJ:hyron.example"
<ca>
-----BEGIN CERTIFICATE-----
(AD CSのルート証明書の中身のみ記載。秘密鍵は含めない)
-----END CERTIFICATE-----
</ca>
SUBJ: にはADのドメイン名を指定します。Step 8⑤で証明書テンプレートのSubject Name formatをCommon nameに設定したことで、各端末の証明書のCNはコンピューター名.hyron.exampleという形式になります。SUBJ:は文字列の部分一致で証明書ストアを検索する仕組みのため、ドメイン名部分(hyron.example)だけを指定しておけば、この.ovpnファイルを全端末に共通で配布でき、端末ごとにファイルを作り分ける必要がありません。
Step 16: クライアント端末からのサーバー証明書自動リクエストの流れ
- クライアント端末を AWS Managed Microsoft AD にドメイン参加させます(事前にDNS設定をAD側に向けておく)。参加後はPCを再起動します。
- ドメインユーザーでWindowsにログインします。
- Win + R → certlm.msc を起動します(ローカルコンピューターの証明書ストア)。
- GPOにより自動配布された証明書を右クリックし、「すべてのタスク」→「Manage Private Keys…」を選択します。
- 利用するドメインユーザーを追加し、権限として フルコントロール(Full Control) と 読み取り(Read) を付与します。
この手順により、ドメインユーザーとしてログインしたセッションから、コンピューター証明書ストアにある秘密鍵へのアクセスが可能になります。AWS Client VPN Desktop Clientがこの証明書を参照して相互認証を行う際に必要な権限設定です。
Step 17〜19: VPNクライアントの設定と接続確認
- AWS Client VPN Desktop Client をダウンロード・インストールします。
- Step 15で作成した .ovpn ファイルを、Client VPNアプリのプロファイルとして追加します。
- 接続を実行し、正常にVPNトンネルが確立できることを確認します。
接続後は、以下のような疎通確認を行います。
# 内部リソースへの疎通確認
ping <管理サーバーのプライベートIP>
# ドメイン名前解決の確認
nslookup hyron.example
証明書の更新・失効設計
自動更新の仕組み(要件③)
Step 9で設定したGPOの自動登録ポリシーにより、証明書の有効期間の残りが少なくなると、対象PCがバックグラウンドで自動的に更新要求をCAへ送信します。ただし、この自動更新はPCがCA(管理サーバー)にネットワーク到達可能なタイミングでのみ実行されます。 常時リモートでVPN接続時のみ社内ネットワークに到達できる端末の場合、更新タイミングとVPN接続のタイミングが噛み合わず証明書が失効してしまうリスクがあるため、定期的な出社時のLAN接続や、期限前アラートによる手動更新の運用ルールを併用することを推奨します。
手動更新が必要な場合は、certlm.msc から対象証明書を右クリック→「すべてのタスク」→「証明書の更新(Renew Certificate with New Key)」で実施できます。
サーバー証明書の更新
サーバー証明書は自動更新されないため、有効期限(今回10年)に注意し、期限到来前に手動で再発行・ACMへの再インポート・Client VPNエンドポイントのARN差し替えを行う必要があります。CloudWatchの DaysToExpiry メトリクスを使って期限切れを事前に検知する仕組みを構築しておくと安心です。
確実な失効の仕組み(要件⑥)
端末紛失・返却・退職時には、証明書を確実に失効させる必要があります。AWS Client VPNは CRL(Certificate Revocation List) のみをサポートしており、OCSPには対応していません。
失効の流れは以下の通りです。
# ① AD CSで対象証明書を失効させる(シリアル番号を指定)
certutil -revoke <証明書のシリアル番号> 1
# ② 最新のCRLを再発行
certutil -crl
# ③ 生成したCRLをClient VPNエンドポイントへ反映
aws ec2 import-client-vpn-client-certificate-revocation-list \
--client-vpn-endpoint-id cvpn-endpoint-xxxxxxxxxxxxxxxxx \
--certificate-revocation-list file://adcs.crl \
--region ap-northeast-1
台数が多い環境では、S3へのCRLアップロードをトリガーに、EventBridge + Lambdaで③のAPI呼び出しを自動化する構成に発展させることも可能です。小規模な運用であれば、退職・紛失発生時に上記3ステップを確実に実行するという運用ルールの徹底でも、実効性のある失効管理が実現できます。
まとめ:要件と実現方法の対応
| 要件 | 実現方法 |
|---|---|
| ① 秘密鍵のエクスポート禁止 | クライアント証明書テンプレートの要求処理タブで「プライベートキーのエクスポートを許可する」をオフに設定 |
| ② 証明書配布の自動化 | GPOの「コンピュータの構成」側で自動登録を有効化し、SG-ClientVPN-Computersグループへのコンピューターアカウント追加をトリガーに自動配布 |
| ③ 有効期限到来時の自動更新 | GPO自動登録ポリシーにより、ドメイン参加+ネットワーク到達可能な状態でバックグラウンド自動更新 |
| ④ AWS Managed Microsoft ADへのドメイン参加 | AD管理用Windows ServerをManaged ADにドメイン参加させ、AD CSをエンタープライズ ルートCAとして構成 |
| ⑤ Windows ServerでのAD CS運用 | 管理サーバー(Windows Server)にAD CSロールを同居させて構築 |
| ⑥ 確実な失効の仕組み | AD CSでの証明書失効 + CRL再発行 + Client VPNへの反映(将来的にS3+Lambdaで自動化可能) |
証明書テンプレートの一見地味な設定項目(Subject Name format、秘密鍵エクスポート可否、GPOの適用対象がユーザーかコンピューターか)一つで、期待通りに動くか動かないかが大きく左右されます。特に Subject Name format を Common name にしておくことと、GPOをコンピュータの構成側で設定することは、Client VPNとの相性の観点から特に重要なポイントでした。
同じような構成を検討されている方の一助になれば幸いです。