Windows Serverのワークフォルダー機能で証明書を自動的に更新する

カバー

[!] この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

はじめに

Windows Serverにはワークフォルダーという機能があります。「同期共有」と呼ばれるフォルダ上にユーザーのファイルを保存し、HTTPS通信でクライアントと同期する機能です。利用するクライアントに暗号化やロック画面のパスワードなどの要件を強制できる機能を持つため、BYODのようなユースケースで使用可能なほか、単純にHTTPSベースの同期共有機能として従来のオフラインファイルの代替にも使用できます。

ワークフォルダー機能を使用するには、サーバーにSSL証明書をインストールしてワークフォルダーの通信に適用します。BYODのような用途でワークフォルダーをインターネット越しに使用する場合、グローバルなSSL証明書が必要です。

一方、オフラインファイルの代替としてローカルネットワーク内のみで使用するケースでは、インターネット経由でのアクセスが必要ではなく、アクセスする端末もActive Directoryに参加しているWindows端末になります。この場合、Active Directory 証明書サービスで発行したSSL証明書を利用できます。

Active Directory 証明書サービス

Active Directory 証明書サービス(AD CS)は、Windows Serverの役割の一つで、Windows Serverで認証局(CA)としての機能を使えます。

AD CSには、スタンドアロンCAとエンタープライズCAがあります。エンタープライズCAとして構築した証明機関のルート証明書は、Active Directoryに参加したWindows端末の信頼される証明機関の一覧に登録されます。このため、エンタープライズCAから発行されたSSL証明書も、端末からは信頼された証明書として扱われます。

エンタープライズCAとして構築したAD CSでは、証明書テンプレートを用いて簡単に証明書を発行可能で自動登録の機能もあります。つまり、自動登録用に構成した証明書テンプレートを使用すれば、証明書の自動発行も実現できます。

証明書発行手順

手順

以下のセクションでは、AD CSを使用して証明書を自動的に発行するための手順を説明します。すでに構築済みのAD CSおよびワークフォルダーサーバーが存在していることを前提としています。

証明書テンプレートの作成

ワークフォルダー用に証明書を自動的に発行するための証明書テンプレートを作成します。ワークフォルダーはHTTPSベースの通信を使用します。このため元となる証明書テンプレートとして、一般的なWebサーバー向けのもの(初期状態で作成されている「Web サーバー」など)が使用可能です。

以降で説明する手順では、Webサーバー向けに初期状態で用意されている証明書で「テンプレートの複製」を実行し、自動登録用のテンプレートを作成しています。自動登録に対応するためには、複製する際に以下の設定が必要です。

  • 「テンプレート表示名」に分かりやすい名前を付け、その値から自動的に設定される「テンプレート名」をメモしておきます。これは、後ほど自動登録の際に使用します。
  • サブジェクト名が「要求に含まれる」となっていることを確認します。
  • セキュリティタブで、発行を許可するユーザーやコンピューターに対して「自動登録」を「許可」する権限を追加します。これは、自動登録を行う際にコンピューターの権限で実行するために必要な権限となります。
詳細手順

テンプレートの作成手順を画像を交えて、解説します。複製元のテンプレートに初期状態で用意されている「Web サーバー」を使用します。

  1. 「証明機関」ツールを起動し、「証明書テンプレート」を右クリックして「管理」を選択すると「証明書テンプレート コンソール」が起動します。 証明機関ツールから証明書テンプレートコンソールを起動
  2. 「証明書テンプレート コンソール」で目的の証明書テンプレートを右クリックし、「テンプレートの複製」を選択します。 証明書テンプレートコンソールでテンプレートの複製を実行
    • 普段Webサーバー向けに証明書を発行するために使用しているテンプレートであればワークフォルダーに使用可能です。初期状態で用意されている「Web サーバー」でも問題ありません。
  3. 互換設定については、運用する環境に合わせて設定してください。変更する際に表示されるダイアログは「OK」をクリックして閉じます。 互換設定の変更 証明機関の互換性の変更 受信者の互換性の変更
    • この記事では、証明機関が「Windows Server 2012 R2」、証明書の受信者が「Windows Vista /Server 2008」で動作確認しています。
  4. 「全般」タブで「テンプレート表示名」を変更します。同時に「テンプレート名」も変更されます。 テンプレート表示名の修正
    • ここで表示される「テンプレート名」は後ほど使用するので、メモを取っておきます。
    • 2022年12月現在、多くの証明書の有効期間が1年間であることを踏まえて、変更しています。ご自身の環境に合わせて設定してください。
  5. 「サブジェクト名」タブで、「要求に含まれる」にチェックが入っていることを確認します。 サブジェクト名タブの確認
  6. 「セキュリティ」タブをクリックします。
    1. 「追加」をクリックします。 セキュリティタブで許可ユーザーを追加
    2. 表示されるダイアログで、「オブジェクトの種類」をクリックします。 検索対象のオブジェクトの種類の追加
    3. 「コンピューター」にチェックを入れて、「OK」をクリックします。 コンピューターを選択
    4. 「選択するオブジェクト名を入力してください」と書かれたテキストボックスに、ワークフォルダーが動作しているサーバーのコンピューター名を入力して「OK」をクリックします。 コンピューター名の追加
    5. 対象のサーバーのコンピューターオブジェクトが選択されていることを確認し、「登録」「自動登録」にチェックを入れます。 権限の設定
    6. 証明書を要求するサーバーの分だけ、この手順を繰り返します。
  7. 「OK」を押して、ダイアログを閉じます。
  8. 「証明機関」ツールに戻り、「証明書テンプレート」を右クリックして「新規作成」→「発行する証明書テンプレート」の順にクリックします。 証明書テンプレートの発行
  9. 作成した証明書テンプレートを選択し、「OK」を押してダイアログを閉じます。 発行する証明書テンプレートの選択
  10. 「証明機関」ツールの「証明書テンプレート」に、作成した証明書テンプレートが追加されたことを確認します。 証明書テンプレートが追加されたことを確認

証明書の発行

本セクションでは、作成した証明書テンプレートを使用して証明書を実際に発行、取得する手順を解説します。

ワークフォルダーの役割を実行するサーバーで実施します。発行に使用するcertreq.exeはWindowsに同梱されており、インストールする必要はありません。

詳細手順
  1. 以下の内容で、設定ファイル(例:certreq.conf)を作成します。ファイル名は任意です。

    [NewRequest]
    Subject="CN=【ワークフォルダーのFQDN】,O=【ORGANIZATION】,L=【LOCALITY】,S=【STATE】,C=【COUNTRY】"
    Exportable=true
    ExportableEncrypted=true
    KeyAlgorithm=RSA
    KeyLength=4096
    MachineKeySet=true
    ProviderName="Microsoft RSA SChannel Cryptographic Provider"
    ProviderType=12
    RequestType = CMC
    Silent=true
    FriendlyName=【証明書を識別するための名前】
    [RequestAttributes]
    CertificateTemplate="【作成したテンプレート名】"
    [Extensions]
    2.5.29.17="{text}"
    _continue_="DNS=【ワークフォルダーのFQDN】"
    2.5.29.37="{text}"
    _continue_="1.3.6.1.5.5.7.3.2,"
    _continue_="1.3.6.1.5.5.7.3.1"
    • 【作成したテンプレート名】の部分に以前の手順で作成した自動登録に対応した証明書テンプレートの名前を記入します。
    • 【ワークフォルダーのFQDN】、【ORGANIZATION】、【LOCALITY】、【STATE】、【COUNTRY】、【証明書を識別するための名前】は環境に合わせて適切な値を記入します。
      • ORGANIZATIONには会社や組織の名前、LOCALITYには市区町村、STATEには都道府県、COUNTRYには国を示す英字2文字(日本ならJP)を入れるのが一般的です。
  2. 証明書署名要求(CSR)ファイルを作成します。

    certreq.exe -new -Q -machine 【前手順で作成した設定ファイルのパス】 【出力するCSRファイルのパス】

    これによりCSRファイルが作成され、それに対応する秘密鍵がコンピューターの証明書ストアに登録されます。

  3. 証明機関(AD CS)に作成要求を送信します。

    certreq.exe -submit -Q -config 【AD CSの識別名】 -AdminForceMachine 【前の手順で作成したCSRファイルのパス】 【出力する証明書ファイルのパス】 【出力する証明書チェインファイルのパス】
    • 証明機関からきた結果を元に、コマンドに指定したファイル名で証明書ファイルが作成されます。
    • 証明書ファイルの拡張子は.cerまたは.crt、証明書チェインファイルの拡張子は.pfxを指定します。
    • 【AD CSの識別名】には【AD CSが動作しているサーバー名】\【証明機関名】を指定します。
    • -AdminForceMachineを指定しているため、この証明書の要求は実行しているユーザーではなくサーバー(コンピューター アカウント)からの要求として扱われます。
  4. 証明書ファイルを、コンピューターの証明書ストアに登録します。

    certreq.exe -accept -Q -machine 【前の手順で取得した証明書ファイルのパス】

    なお、ドメインに参加しているコンピューターであれば、AD CSのCA証明書はコンピューターの証明書ストアに登録されているため、手動で登録する必要はありません。

作成した証明書をワークフォルダーに設定する

ワークフォルダーの証明書はUIではなく、netshコマンドで設定します。

手順

  1. ワークフォルダーに使用する証明書を設定するため、証明書のThumbprintを取得します。

    $res=$(Get-PfxCertificate 【前の手順で取得した証明書ファイルのパス】)
    echo $res.Thumbprint
  2. コンピューターの証明書ストアに証明書が登録されていることを確認します。

    $CertPath="Cert:\LocalMachine\My\"+"【前の手順で取得した証明書のThumbprint】"
    Get-Item $CertPath
  3. ワークフォルダーの証明書を設定します。

    netsh http update sslcert ipport=0.0.0.0:443 certhash=【前の手順で取得した証明書のThumbprint】 appid="{CE66697B-3AA0-49D1-BDBD-A25C8359FD5D}" certstorename=MY
    • netsh http updateはWindows Server 2016以降から使用可能です。Windows Server 2012 R2以前では、一時的に接続に影響が出ますが、deleteしてからaddを実行してください。
    • 初回設定時はupdateではなくaddを使用します。登録済みの証明書を更新する作業を想定しています。
    • ワークフォルダーにipport=0.0.0.0:443を使用している想定で記述されています。
      • hostnameを使用している場合はipport=0.0.0.0:443の代わりにhostnameport=【ワークフォルダーのFQDN】:443を指定してください。
    • appid="{CE66697B-3AA0-49D1-BDBD-A25C8359FD5D}"はワークフォルダーを示す識別子です。

証明書の発行・取得・設定の自動化

ここまでの流れは全てコマンドラインで行えるため、PowerShellとタスクスケジューラを組み合わせることで自動化できます。証明書を1年で出す場合は、目安として半年に一度更新を実行し、常に有効な証明書が設定されるようにします。

PowerShellスクリプトの作成

以下の内容で、C:\Scripts\WorkFoldersCert\Scripts\renew_workfolder_cert.ps1にPowerShellスクリプトを作成します。

<# 関数 #>
## ログ記録停止と終了
function Stop-Script ($result,$msg) {
    # ログ記録停止
    Write-Host $msg
    Stop-Transcript
    exit $result
}

<# 設定 #>
## ディレクトリ設定
$BaseDir="C:\Scripts\WorkFoldersCert\"
$ConfDir=$BaseDir+"Config\"
$TmpDir=$BaseDir+"Tmp\"
$LogDir=$BaseDir+"Logs\"
<#
### TmpDirとLogDirは古いファイルの削除を行っております。
### TmpDir、LogDirが重要なファイルを置いたディレクトリにならないようにBaseDirを設定ください。
##>

## ファイル設定
### 設定ファイル
$ConfFileName="wf.conf"

## CA設定
$CaServer="ADCS1"
$CaName="TEST-ADCS1-CA"

## ワークフォルダーの待ち受けポート
$ServicePort="ipport=0.0.0.0:443"

<# 処理 #>
## CA名
$ca=$CaServer+"\"+$CaName

## 設定ファイルのフルパス
$ConfFile=$ConfDir+$ConfFileName

## 実行日時取得
$today=$(Get-Date -UFormat "%Y%m%d_%H%M%S")

## CSRファイル名
$RequestFileName="ncs_"+$today+".csr"

## 証明書ファイル名
$CertFileName="ncs_"+$today+".crt"

## 証明書チェインファイル名
$CertChainFileName="ncs_"+$today+".pfx"

## 作業ディレクトリのフルパス
$WorkDir=$TmpDir+$today+"\"

## ログのフルパス
$LogFile=$LogDir+$today+".log"

## CSRファイルのフルパス
$RequestFile=$WorkDir+$RequestFileName

## 証明書ファイルのフルパス
$CertFile=$WorkDir+$CertFileName

## 証明書チェインファイルのフルパス
$CertChainFile=$WorkDir+$CertChainFileName

## ログ記録開始
Start-Transcript -Path $LogFile -Append

## 作業ディレクトリ作成
try {
    $res=$(New-Item -ItemType Directory -Path $WorkDir -ErrorAction Stop)
} catch {
    Stop-Script -1 $res
}

## CSRの作成
$res=certreq.exe -new -Q -machine $ConfFile $RequestFile
if ($? -eq $false) {
    Stop-Script -1 $res
}
$res=""

## 証明書の作成・取得
$res=certreq.exe -submit -Q -config $CA -AdminForceMachine $RequestFile $CertFile $CertChainFile
if ($? -eq $false) {
    Stop-Script -1 $res
}
$res=""

## 証明書のインポート
$res=certreq.exe -accept -Q -machine $CertFile
if ($? -eq $false) {
    Stop-Script -1 $res
}
$res=""

## 証明書のThumbprintを取得
try {
    $res=$(Get-PfxCertificate $CertFile -ErrorAction Stop)
    $CertThumbprint=$res.Thumbprint
} catch {
    Stop-Script -1 $res
}
$res=""

## 証明書のフルパス
$CertPath="Cert:\LocalMachine\My\"+$CertThumbprint

## 証明書のインポート確認
try {
    $res=$(Get-Item $CertPath -ErrorAction Stop)
} catch {
    Stop-Script -1 $res
}
$res=""

## 証明書の入れ替え
$res=netsh http update sslcert $ServicePort certhash=$CertThumbprint appid="{CE66697B-3AA0-49D1-BDBD-A25C8359FD5D}" certstorename=MY
if ($? -eq $false) {
    Stop-Script -1 $res
}
$res=""

## 古いファイルの削除
Get-ChildItem $TmpDir -Recurse | Where-Object {($_.LastWriteTime -lt (Get-Date).AddYears(-2))} | Remove-Item -recurse -force
Get-ChildItem $LogDir -Recurse | Where-Object {($_.LastWriteTime -lt (Get-Date).AddYears(-2))} | Remove-Item -recurse -force

Stop-Script 0

このスクリプトは、以下の想定になります。ご自分の環境に合わせて、適宜修正してください。

  • AD CSを実行するコンピューター名($CaServer):ADCS1
  • 証明機関名($CaName):TEST-ADCS1-CA
  • サービスポート($ServciePort):0.0.0.0:443
    • ワークフォルダーを【ワークフォルダーのFQDN】:443で待ち受けている場合は、$ServicePortの値をhostnameport=【ワークフォルダーのFQDN】:443に修正してください。
  • 証明書を要求するために必要な設定ファイルをC:\Scripts\WorkFoldersCert\Config\wf.confに配置
  • スクリプト実行後、設定に使用した証明書ファイルや実行ログをC:\Scripts\WorkFoldersCert\フォルダに保存

設定ファイルの作成

配置する設定ファイルのサンプルは以下です。上述のスクリプトを実行するためには、下記のファイルをwf.confとしてC:\Scripts\WorkFoldersCert\Config\フォルダに配置します。スクリプトに記述したファイルパスを変更した場合は、そちらに合わせて配置してください。

[NewRequest]
Subject="CN=workfolder.test.example.co.jp,O=EXAMPLE JP,L=Shibuya-ku,S=Tokyo,C=JP"
Exportable=true
ExportableEncrypted=true
KeyAlgorithm=RSA
KeyLength=4096
MachineKeySet=true
ProviderName="Microsoft RSA SChannel Cryptographic Provider"
ProviderType=12
RequestType = CMC
Silent=true
FriendlyName=workfolder.test.example.co.jp
[RequestAttributes]
CertificateTemplate="Webサーバー自動更新"
[Extensions]
2.5.29.17="{text}"
_continue_="DNS=workfolder.test.example.co.jp"
2.5.29.37="{text}"
_continue_="1.3.6.1.5.5.7.3.2,"
_continue_="1.3.6.1.5.5.7.3.1"
  • 使用している値(workfolder.test.example.co.jpなど)はサンプルです。SubjectFriendlyNameCertificateTemplate_continue_="DNS=~~"の値を、ご自身の環境に合わせて修正してください。
  • 証明書の鍵の長さは4096としています。変更する場合はKeyLengthを変更してください。テンプレートによっては対応していない場合もあります。

タスクスケジューラの設定

上述のスクリプトや設定ファイルを配置し、下記の内容で作成したxmlファイルをタスクスケジューラにインポートすると、3/18と9/18にタスクが実行され、半年に一度証明書が自動的に更新されます。実行日時を調整する場合は、インポート前に<Months>~</Months><Day>~</Day>を修正するか、インポート後にGUIから変更してください。

<?xml version="1.0" encoding="UTF-16"?>
<Task version="1.4" xmlns="http://schemas.microsoft.com/windows/2004/02/mit/task">
  <RegistrationInfo>
    <Date>2022-03-17T00:00:00.0000000</Date>
    <Author>Administrator</Author>
    <URI>\RenewWorkfoldersCert</URI>
  </RegistrationInfo>
  <Triggers>
    <CalendarTrigger>
      <StartBoundary>2022-03-17T05:00:00</StartBoundary>
      <Enabled>true</Enabled>
      <ScheduleByMonth>
        <DaysOfMonth>
          <Day>18</Day>
        </DaysOfMonth>
        <Months>
          <March />
          <September />
        </Months>
      </ScheduleByMonth>
    </CalendarTrigger>
  </Triggers>
  <Principals>
    <Principal id="Author">
      <UserId>S-1-5-18</UserId>
      <RunLevel>HighestAvailable</RunLevel>
    </Principal>
  </Principals>
  <Settings>
    <MultipleInstancesPolicy>IgnoreNew</MultipleInstancesPolicy>
    <DisallowStartIfOnBatteries>false</DisallowStartIfOnBatteries>
    <StopIfGoingOnBatteries>false</StopIfGoingOnBatteries>
    <AllowHardTerminate>true</AllowHardTerminate>
    <StartWhenAvailable>true</StartWhenAvailable>
    <RunOnlyIfNetworkAvailable>false</RunOnlyIfNetworkAvailable>
    <IdleSettings>
      <StopOnIdleEnd>false</StopOnIdleEnd>
      <RestartOnIdle>false</RestartOnIdle>
    </IdleSettings>
    <AllowStartOnDemand>true</AllowStartOnDemand>
    <Enabled>true</Enabled>
    <Hidden>false</Hidden>
    <RunOnlyIfIdle>false</RunOnlyIfIdle>
    <DisallowStartOnRemoteAppSession>false</DisallowStartOnRemoteAppSession>
    <UseUnifiedSchedulingEngine>true</UseUnifiedSchedulingEngine>
    <WakeToRun>true</WakeToRun>
    <ExecutionTimeLimit>PT72H</ExecutionTimeLimit>
    <Priority>7</Priority>
  </Settings>
  <Actions Context="Author">
    <Exec>
      <Command>powershell</Command>
      <Arguments>C:\Scripts\WorkFoldersCert\Scripts\renew_workfolder_cert.ps1</Arguments>
      <WorkingDirectory>C:\Scripts\WorkFoldersCert\Scripts</WorkingDirectory>
    </Exec>
  </Actions>
</Task>

このタスクは、PowerShellスクリプトをC:\Scripts\WorkFoldersCert\Scripts\renew_workfolder_cert.ps1に配置している前提になります。スクリプトの名前やパスを変更した場合は、インポート前に<Arguments>~</Arguments><WorkingDirectory>~</WorkingDirectory>をご自身の環境に合わせて修正してください。

まとめ

ワークフォルダーの証明書を自動的に更新する方法を紹介してみました。証明書を自動的に更新、設定することで、作業忘れによるワークフォルダーの無効化を防ぐことができます。


TOP
アルファロゴ 株式会社アルファシステムズは、ITサービス事業を展開しています。このブログでは、技術的な取り組みを紹介しています。X(旧Twitter)で更新通知をしています。