[2019年度版] Let’s Encryptの証明書を使ってRD GatewayでWindowsサーバに接続
しばたです。
先日は自己署名証明書を使ってRD Gatewayサーバーを構築する手順を紹介しましたが、今であれば自己署名証明書ではなくLet's Encryptを使って低コストでSSL証明書を利用することもできます。
本記事ではLet's Encryptの証明書を使ってRD Gatewayに設定する手順を紹介します。
前提条件
本記事ではRoute 53上にgateway01.shibata.classmethod.info
というホスト名を登録しこれを使うものとします。
(Route 53周りの設定については本記事では触れません)
RD Gatewayサーバーの構成と構築
RD Gatewayサーバーの構築手順については前回の記事の通りです。
前回の記事の延長として自己証明書をLet's Encryptの証明書切り替えるシナリオで進めていきます。
Posh-ACMEを使ったSSL証明書の作成
WindowsでLet's Encryptの証明書を発行するためのツールとしてはwin-acmeが有名ですが、本記事ではPowerShellモジュールとして提供されているPosh-ACMEを使います。
DNS検証(DNS-01)のための前準備
Let's Encryptで使われるACMEプロトコルではドメインの検証方法がいくつかありますが、本記事ではRD Gatewayで設定されるIISにあまり手を入れたくないのとDNSにRoute 53を使っているというのもありDNS検証(DNS-01)で行うことにします。
(実環境ではドメインの検証方法はその環境に応じてそれぞれ変わることになります)
Posh-ACMEでもプラグインの形でRoute 53でのDNS検証に対応しており、その手順が以下のドキュメントに記載されています。
このドキュメントではIAMユーザーおよびIAMロールを設定する手順が紹介されています。
本記事はEC2のRD Gatewayサーバー上で作業を行いますのでIAMロールを作成しEC2インスタンスにアタッチする方法を採用します。
1. IAMロールの作成とアタッチ
詳細は前掲のドキュメントを参照してほしいのですがPosh-ACMEでDNS検証をするためには以下のポリシーが要求されます。
{
"Version": "2012-10-17",
"Statement": [
{
"Action": [
"route53:ListHostedZones"
],
"Resource": "*",
"Effect": "Allow"
},
{
"Action": [
"route53:GetHostedZone",
"route53:ListResourceRecordSets",
"route53:ChangeResourceRecordSets"
],
"Resource": "arn:aws:route53:::hostedzone/*",
"Effect": "Allow"
}
]
}
このポリシーを持つIAMロール(+インスタンスプロファイル)を生成するCloudFormationテンプレートを作りましたので、これを参考に生成したIAMロールをRD Gatewayサーバーにアタッチしておきます。
AWSTemplateFormatVersion: 2010-09-09
Parameters:
RoleName:
Description: "Input Posh-ACME role name."
Type: String
Default: "PoshACMERole"
Resources:
# IAM Role
PoshACMERole:
Type: AWS::IAM::Role
Properties:
RoleName:
Fn::Sub: "${RoleName}"
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: "Allow"
Principal:
Service:
- "ec2.amazonaws.com"
Action:
- "sts:AssumeRole"
Path: "/"
Policies:
- PolicyName: 'R53_Zone_Editor'
PolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: "Allow"
Resource: "*"
Action:
- "route53:ListHostedZones"
- Effect: "Allow"
Resource: "arn:aws:route53:::hostedzone/*"
Action:
- "route53:GetHostedZone"
- "route53:ListResourceRecordSets"
- "route53:ChangeResourceRecordSets"
# Instance Profile
PoshACMERoleInstanceProfile:
Type: "AWS::IAM::InstanceProfile"
Properties:
InstanceProfileName:
Fn::Sub: "${RoleName}"
Path: "/"
Roles:
- Ref: PoshACMERole
2. AWSPowerShellモジュールのインストール
今回はEC2インスタンス上で作業するためAWSPowerShellモジュールはデフォルトでインストール済みですので追加の作業は不要です。
Posh-ACMEではDNS検証のための認証でプロファイルを使う場合のみAWSPowerShellモジュールが必要となります。
3. Posh-ACMEのインストール
ここから本題に入ります。
GD Gateway サーバーにログインし、Install-Module
を使いPosh-ACMEモジュールをインストールします。
Install-Module -Name Posh-ACME -Scope CurrentUser
4. SSL証明書の生成
SSL証明書の生成はNew-PACertificate
コマンドレットで行えます。
引数に証明書のホスト名や検証方式を選択します。
本記事では以下の引数を指定しています。
- 第一引数 : ホスト名 (gateway01.shibata.classmethod.info)
- -AcceptTOS : 利用規約に自動で同意する
- -DnsPlugin Route53 : Route53によるDNS検証を行う
- -PluginArgs @{R53UseIAMRole=$true} : IAMRoleを使ってDNS検証を行う
New-PACertificate "<Your RD Gateway server FQDN>" -AcceptTOS -DnsPlugin Route53 -PluginArgs @{R53UseIAMRole=$true}
実行後Eメールアドレスが登録されていない警告が表示されていますが、今回はこれを無視します。
本番環境での運用を行う場合は-Contact
パラメーターを指定しメールアドレスの登録も一緒に行うと良いでしょう。
そしてGet-PACertificate
コマンドレットで生成した証明書情報を確認すると以下の通りとなり、ユーザープロファイル配下のフォルダに各種ファイルが保存されていることがわかります。
Get-PACertificate | Format-List
5. SSL証明書のインポート
RD Gatewayでは秘密鍵を含む証明書をローカルコンピューター\個人
にインポートしておく必要があります。
Import-PfxCertificate
コマンドレットを使い生成した証明書(PFX形式の方)をインポートします。
# 生成した証明書情報を取得
$pacert = Get-PACertificate
# ローカルコンピューター\個人 に証明書をインポート
Import-PfxCertificate -FilePath $pacert.PfxFile -CertStoreLocation 'Cert:\LocalMachine\My\' -Password $pacert.PfxPass
6. SSL証明書をRD Gatewayに登録
証明書をインポートできれば後の手順は前回と変わりありません。
RemoteDesktopServices
モジュールをインポートしてSet-Item
で証明書を更新してください。
更新内容を反映させるにはサービスの再起動が必要となります。
# RDGatewayに証明書をセット
Import-Module RemoteDesktopServices
Set-Item -Path 'RDS:\GatewayServer\SSLCertificate\Thumbprint' -Value $pacert.Thumbprint
# サービス再起動
Stop-Service TSGateway
Start-Service TSGateway
GDゲートウェイマネージャーの画面からも証明書が更新されていることが確認できます。
クライアントからの接続確認
これでLet's Encryptの証明書でRD Gatewayサーバーを公開することができました。
クライアントからの接続は前回と変わりありません。
リモートデスクトップクライアントで設定するRDゲートウェイサーバーを更新したホスト名にすればOKです。
今回はちゃんと公開されている証明書ですのでクライアント側でのインポート作業は不要です。
証明書の更新
最後に証明書を更新する方法を解説して終わりにします。
生成した証明書を更新するにはSubmit-Renewal
を呼び出すだけでOKです。
今回は最初に生成してからまだ間もないため-Force
パラメーターをつけて強制的に更新をかけておきます。
# 必要に応じて -Force パラメーターを付ける
$pacert = Submit-Renewal
$pacert
ちょっとわかりにくいですがこれで証明書は更新され新しくなっています。
あとは「5. SSL証明書のインポート」以降の手順を繰り返すだけでRD Gatewayの証明書を更新できます。
本記事では具体的な手順までは紹介しませんが、これくらいの内容であれば一連の手順をスクリプト化し、タスクスケジューラなどを使い定期実行させて証明書を自動更新させることも容易かと思います。