AWS Managed Microsoft AD環境でADFSサーバーを構築する
しばたです。
通常ADFSサーバーを構築するためにはDomain Admin
権限が必要であり、Domain Admin
権限を利用できないAWS Managed Microsoft AD(以後Microsoft AD)環境において通常の手順でADFSサーバーを構築しようとすると以下の様に権限エラーとなってしまいます。
本記事ではこのエラーを回避してMicrosoft AD環境でADFSサーバーを構築する手順について説明します。
参考情報
非Domain AdminユーザーでADFSサーバーを構築する手順についてドキュメントは非常に少なく、チェコのMicrosoft Docsにある下記のドキュメントとAWS Security Blogの記事があるくらいです。
- Creating an AD FS Farm without domain admin privileges
-
How to Enable Your Users to Access Office 365 with AWS Managed Microsoft AD
(一応この他に上記を参考にしたと思しきQiitaの記事もあったりしたのですが、必須でない手順が混ざっているなど不正確な記述が多かったのでここでは紹介を控えておきます)
また、この他にAWSが公式に提供しているクイックスタートのリポジトリがあり、こちらの内容も一部参考にしています。
(ただし、このクイックスタートはEC2 Active Directory環境前提でありそのままの内容では使えませんのでご注意ください)
検証環境
今回の検証環境は下図となります。
パブリックサブネットにADFS Web Application Proxy(ADFS WAP)サーバー、プライベートサブネットにADFSサーバーとMicorosft ADを配置します。
ADFSサーバーがインターネットアクセス可能にするためにNAT Gatewayを配置しています。
加えてMicrosoftのドキュメントを基に各サービス間で必要なポートを開けるセキュリティグループを設定しておきます。
その他詳細は以下。
Micorosft AD
項目 | 設定値 | 備考 |
---|---|---|
エディション | Standard | |
ドメイン名 | corp.shibata.tech | |
NetBIOSドメイン名 | CORP | |
ADFS用gMSA | corp\adfs-srevice | 詳細は後述 |
ADFSサーバー
項目 | 設定値 | 備考 |
---|---|---|
インスタンスタイプ | t3.medium | |
OS | 日本語版 Windows Server 2016 | AMI : ami-0b26f62143241dc18 |
コンピューター名 | ADFS01 | |
ドメイン | corp.shibata.tech に参加 | |
Windows Firewall | 無効に変更 | 通信制御はセキュリティグループで実施 |
ADFS WAPサーバー
項目 | 設定値 | 備考 |
---|---|---|
インスタンスタイプ | t3.medium | |
OS | 日本語版 Windows Server 2016 | AMI : ami-0b26f62143241dc18 |
コンピューター名 | WAP01 | |
ドメイン | corp.shibata.tech に参加 | |
Windows Firewall | 無効に変更 | 通信制御はセキュリティグループで実施 |
その他
- 外部に公開するサーバー名は
sts.shibata.tech
- 証明書は自己署名証明書を使用
- このためADFS WAPサーバーやクライアント端末で証明書を無条件信頼する様にしています
- 各サーバーでの作業は Admin ユーザーで実施
- PowerShellコンソールは「管理者として実行」が基本
ADFSサーバー、ADFS WAPサーバー構築に至るまでの環境構築については割愛します。
ADFSサーバー (ADFS01) の構築
サーバーがcorp.shibata.tech
ドメインに参加した時点をスタート地点とします。
ADFSサーバー構築前に幾つか前準備を行います。
前準備1 : gMSAの作成
本記事では参考資料とは異なりADFSサービスの実行ユーザーをグループ管理サービスアカウント(gMSA)にします。
Microsoft AD環境ではKDSルートキーは作成済みですのでいきなりNew-ADServiceAccountコマンドレットを実行しgMSAを作成します。
1 | New-ADServiceAccount -Name 'adfs-service' –DNSHostName 'adfs01' |
アカウント名をadfs-service
、利用可能なサーバーをADFSサーバー(adfs01)とします。
前準備2 : 証明書の作成
ADFSでは通常「サービス通信証明書」にパブリックな証明書を使用しますが、本記事では自己証明書を使い検証します。
また「トークン署名証明書」および「トークン暗号化解除」証明書は通常であればADFSが自動生成するのですが、本記事では後述の都合によりこの証明書を使います。
証明書はPowerShellからNew-SelfSignedCertificate
コマンドレットを使いざっくり以下の様に作成しました。
1 2 3 4 5 6 7 8 9 10 11 | $params = @{ Subject = 'sts.shibata.tech' DnsName = 'sts.shibata.tech' CertStoreLocation = 'cert:\LocalMachine\My' KeyAlgorithm = 'RSA' KeyLength = 2048 KeyExportPolicy = 'Exportable' NotAfter = ( Get-Date ).AddYears(5) } $cert = New-SelfSignedCertificate @params $cert |
また、ADFS WAPの構築時にこの証明書を使いますのでExport-PfxCertificateコマンドレットを実行して適当なディレクトリにエクスポートし保存しておいてください。
1 2 3 4 | # WAPおよびクライアント用にエクスポートしておく (要管理者権限) # ※エクスポート先およびパスワードは適当なので適宜変更してください mkdir C:\Temp Export-PfxCertificate -Cert $cert -FilePath "C:\temp\adfs.pfx" -Password ( ConvertTo-SecureString "P@ssw0rd" -AsPlainText -Force ) |
1. ADFSサーバーの構築 (機能の追加)
ここからADFSサーバーの構築を開始します。
はじめにInstall-WindowsFeatureコマンドレットを使い「Active Directory Federation Services」の機能を追加します。
1 | Install-WindowsFeature -Name 'ADFS-Federation' -IncludeManagementTools |
2. ADFSサーバーの構築 (ADFSコンテナーの作成)
ここからADFSサーバーの設定に入るのですが、通常ADFSファームを作る場合はドメイン内の[ドメイン名]/Program Data/Microsoft
2つのコンテナーオブジェクトを作成します。
(オンプレ環境でADFSサーバーを構築した場合)
でこの[ドメイン名]/Program Data/Microsoft
にオブジェクトを作成するにはDomain Admin権限が必要であり、Microsoft ADでエラーとなる原因でもあります。
このため参考元の記事ではコンテナーをMicrosoft ADでアクセス可能な[ドメイン名]/[NetBIOSドメイン名]/
(既定のOU)配下に作成しています。
本記事ではMicrosoft Docsの記事で紹介されているスクリプトをgMSA専用にカスタマイズし関数化しました。
以下の関数を実行すると[ドメイン名]/[NetBIOSドメイン名]/
配下にADFS
とランダムなGUID
のコンテナーを作成し、その設定情報を$adminConfig
変数に格納します。
※$adminConfig変数は後で使います
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 | # gMSA専用関数 function New-NonDADkmContainerForgMSA { [ CmdletBinding ()] param ( [ Parameter ( Mandatory = $True )] [string] $AcctToAclDkmContainer ) $userNameSplit = $AcctToAclDkmContainer .Split( "\" ) if ( $userNameSplit .Length -ne 2) { Write-error "Specify non-DA local admin user in 'domain\username' format" return $false } # The OU Name is a randomly generated Guid [string] $guid = ( New-Guid ).Guid Write-Host ( "OU Name" + $guid ) $ouName = $guid $initialPath = "OU=$($userNameSplit[0])," + ( Get-ADDomain ).DistinguishedName $ouPath = "CN=ADFS," + $initialPath $ou = "CN=" + $ouName + "," + $ouPath Write-Host ( "Creating organizational unit with DN: " + $ou ) if ( $null -eq ( Get-ADObject -Filter {distinguishedName -eq $ouPath })) { Write-Host ( "First creating initial path " + $ouPath ) New-ADObject -Name "ADFS" -Type Container -Path $initialPath } New-ADObject -Name $ouName -Type Container -Path $ouPath # get gMSA SID $strSID = ( Get-ADServiceAccount -Identity $userNameSplit [1]).SID # set acl to ADFS cottainer object Import-Module ActiveDirectory try { Push-Location ad: [System.DirectoryServices.ActiveDirectorySecurityInheritance] $adSecInEnum = [System.DirectoryServices.ActiveDirectorySecurityInheritance] ::All $ace1 = New-Object System.DirectoryServices.ActiveDirectoryAccessRule $strSID , "GenericRead" , "Allow" , $adSecInEnum $ace2 = New-Object System.DirectoryServices.ActiveDirectoryAccessRule $strSID , "CreateChild" , "Allow" , $adSecInEnum $ace3 = New-Object System.DirectoryServices.ActiveDirectoryAccessRule $strSID , "WriteOwner" , "Allow" , $adSecInEnum $ace4 = New-Object System.DirectoryServices.ActiveDirectoryAccessRule $strSID , "DeleteTree" , "Allow" , $adSecInEnum $acl = Get-Acl -Path $ou $acl .AddAccessRule( $ace1 ) $acl .AddAccessRule( $ace2 ) $acl .AddAccessRule( $ace3 ) $acl .AddAccessRule( $ace4 ) Set-Acl -Path $ou -AclObject $acl } finally { Pop-Location } return @{ "DKMContainerDn" = $ou } } # ADFSコンテナーを作成し、設定情報を変数に格納 # ※ $adminConfig 変数は後で使用する $adminConfig = New-NonDADkmContainerForgMSA 'corp\adfs-service' |
結果この様にコンテナーが作成されます。
3. ADFSサーバーの構築 (ADFSファームの構築)
ここまでを踏まえてADFSファームの構築に取り掛かれます。
ADFSファームを作るにはADFSモジュールにあるInstall-AdfsFarmコマンドレットを使用します。
本記事では構築前にTest-AdfsFarmInstallationコマンドレットを実行し事前検証をしています。
細かい解説は後述しますが以下のコマンドを実行するとADFSファームを構築できます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | # 証明書情報を取得 $cert = Get-ChildItem Cert:\LocalMachine\My\ | Where-Object { $_ .Subject -eq 'CN=sts.shibata.tech' } # ADFSファームを構築する際のローカル管理者権限を持つユーザーの認証情報 $localAdminCred = Get-Credential 'corp\admin' # SigningCertificateThumbprint, DecryptionCertificateThumbprint を指定してADFSファームを作成 $params = @{ CertificateThumbprint = $cert .Thumbprint SigningCertificateThumbprint = $cert .Thumbprint DecryptionCertificateThumbprint = $cert .Thumbprint FederationServiceName = 'sts.shibata.tech' GroupServiceAccountIdentifier = 'corp\adfs-service$' Credential = $localAdminCred OverwriteConfiguration = $true AdminConfiguration = $adminConfig Verbose = $true } # 検証 Test-AdfsFarmInstallation @params # インストール Install-AdfsFarm @params |
Install-AdfsFarmでは証明書の指定に-CertificateThumbprint
(サービス通信証明書)のみ指定し、-SigningCertificateThumbprint
(トークン署名証明書)および-DecryptionCertificateThumbprint
(トークン暗号化解除証明書)は未指定でADFSサーバーが自動生成する証明書を利用するのがデフォルトなのですが、ここで両パラメーターを指定しない場合、デフォルトの証明書を[ドメイン名]/Program Data/Microsoft
配下に作成しようとしエラーとなってしまいます。
このためMicrosoft ADでADFSを作成する場合はトークン署名証明書、トークン暗号化解除証明書ともに自前で設定してやる必要があります。
この場合証明書の自動更新機能は使えない様です。
ADFSサーバーの設定も自動更新がオフにされ、Update-ADFSCertificateコマンドレットを使い自動更新を試みても下図の様にエラーとなってしまいます。
少し余談が入ってしまいましたがInstall-AdfsFarmに成功すると下図の様になります。
これでADFSサーバーの構築が完了し管理コンソールから各種設定を行うことができます。
ADFS WAPサーバー (WAP01) の構築
前準備1 : HOSTSファイルの設定
ADFS WAPサーバーではsts.shibata.tech
は内部のADFSサーバー(WAP01)を指す必要があります。
最終的にsts.shibata.tech
はDNSからはグローバルIPアドレス(EIP)を返す様にすることになるので、ADFS WAPサーバーではHOSTSファイルを設定してやる必要があります。
HOSTSファイルに
1 | <WAP01のIP> sts.shibata.tech |
の設定を追加します。
前準備2 : 証明書のインポート
今回は検証用に自己署名証明書を使うので最初にエクスポートしておいた証明書を「ローカルコンピューター\個人」にインポートしておきます。
1 2 3 4 5 6 7 | # エクスポートした証明書が C:\temp\adfs.pfx にある前提 $params = @{ FilePath = 'C:\temp\adfs.pfx' CertStoreLocation = 'cert:\localMachine\my' Password = ( ConvertTo-SecureString "P@ssw0rd" -AsPlainText -Force ) } Import-PfxCertificate @params |
また、この証明書を信頼済み扱いするために「信頼されたルート証明機関」にもインポートしておいてください。(本記事ではこの手順は割愛します)
1. ADFS WAPサーバーの構築 (機能の追加)
ここからADFS WAPサーバーの構築を開始します。
はじめにInstall-WindowsFeatureコマンドレットを使い「Web アプリケーション プロキシ」の機能を追加します。
1 | Install-WindowsFeature Web-Application-Proxy -IncludeManagementTools |
2. ADFS WAPサーバーの構築 (WAPの構成)
続けてWebApplicationProxyモジュールのInstall-WebApplicationProxyコマンドレットでWAPを構成します。
こちらは細かい説明は不要かと思います。
1 2 3 4 5 6 7 8 | # ローカル管理者権限を持つユーザーの認証情報 $localAdminCred = Get-Credential 'corp\admin' $params = @{ FederationServiceName = 'sts.shibata.tech' CertificateThumbprint = ( Get-ChildItem Cert:\LocalMachine\My\ | Where-Object { $_ .Subject -eq 'CN=sts.shibata.tech' }).Thumbprint FederationServiceTrustCredential = $localAdminCred } Install-WebApplicationProxy @params |
インストールに問題なければ下図の様になります。
ADFSの管理コンソールからWAPが有効になっていることが確認できればOKです。
動作確認
これでADFSおよびADFS WAP環境が構築できましたので簡単に動作確認をしてみます。
や
の内容を参考にAWSマネジメントコンソールへのSSO環境を作ってみました。
こちらの細かい手順は割愛しますが、その結果作成したADFS WAPのサインイン画面から
ドメインユーザー(tarou.yamada@corp.shibata.tech
)でログインし、
SSOによりマネジメントコンソールにアクセスできました。
最後に
以上となります。
Microsoft ADではDomain Admin権限を利用することができないため、ADFSの構築にはひと手間かけてやる必要あり制約も付きますが決して不可能ではありません。
需要は多くないかもしれませんが本記事の内容が誰かの役に立てば幸いです。