はじめに
お疲れ様です。矢儀 @yuki_ink です。
Oracle Database@AWSの利用のために、OCIコンソールへのログイン環境を整えないといけませんでした(VMクラスタの構築まではAWS側からできるが、その上のDBの構築やパッチ適用などはOCIコンソールから!)
ADFS(Active Directory Federation Services)は、Microsoftが提供する認証連携(フェデレーション)サービスです。
ADFSを利用すれば、社内のAD(Active Directory)のIDを使って、社外のクラウドサービスやWebアプリにシングルサインオン(SSO)できます。
ADFSは現在でも多くの企業で利用されていますが、近年は Microsoft Entra ID(旧 Azure AD) やOIDCベースの認証へ移行するケースも増えています。
一方で、オンプレミスADとの密接な連携や、閉域網環境での運用が求められるケース(特に、閉域網の中でも、さらにアクセス元IPアドレスを制御したいようなケース)では、現在でもADFSが有効な選択肢となります。
というわけで、EC2でADFSを起動して、OCIコンソールにSSOします!!!
概要
今回の検証では 「ADユーザ test@yagi.local(※)の認証情報で、OCI IAMユーザ test@yagi.local にフェデレーションすること」 を目指します。
※「yagi.local」ドメインの「test」ユーザ
ユーザのマッピングはこのようになります。
AD の UPN(test@yagi.local)⇒ OCI IAM ユーザ名(test@yagi.local)
AWSのマネジメントコンソールでADFS連携しようとするとIAMユーザではなくIAMロールを利用しますが、OCIのフェデレーションでは、AWS STS AssumeRole のようにロールへスイッチする構成ではなく、OCI IAMユーザへ直接マッピングする構成になります。
サーバとしてはAmazon EC2で「Windows Server 2022」を利用し、その中で以下のサービスを稼働させます。
今回は検証のため、サービスごとにサーバの分離はしません。
| サービス | 役割 / 概要 | 今回の検証での目的 |
|---|---|---|
| Active Directory Domain Services (ADDS) | Windowsドメイン環境を提供し、ユーザーや認証情報を管理する。 |
yagi.local ドメインを構築し、ADFSの認証基盤として利用する。 |
| Active Directory Federation Services (ADFS) | 外部サービスとのシングルサインオン(SSO)を実現する認証連携機能。 |
yagi.local のユーザーでOCIコンソールへログインできるようにする。 |
| Active Directory Certificate Services (ADCS) | 証明書の発行・管理を行う認証局(CA)。 | ADFS用のSSL証明書を発行し、HTTPS通信を有効にする。 |
| DNS Server | 名前解決を行い、ホスト名とIPアドレスを対応付ける。 |
yagi.local や adfs.yagi.local の名前解決を行う。 |
全体アーキテクチャ
今回の構成では、ADFS (adfs.yagi.local) はVPC内部からのみアクセス可能なプライベート構成としています。
そのため、本記事の構成でOCIコンソールへSSOできるのは、内部NWからADFSへ到達できるユーザに限定されます。
インターネット上の任意端末からOCIへSSOさせる場合は、ADFS Proxy(WAP: Web Application Proxy)やリバースプロキシを利用して、ADFSを安全に外部公開する構成が必要になりますが、本記事の趣旨ではないので詳細は触れません🙇♀️
前提条件
- AWSアカウントおよびOCIアカウントが作成済みであること
- EC2インスタンス用のVPCおよびサブネットが構成済みであること
STEP 1: EC2 インスタンスの作成
ADFS用と検証用とで、2つインスタンスを起動します。
1-1. ADFS用 EC2 インスタンスの作成
以下の通り、EC2インスタンスを作成します。
| 項目 | 推奨値 |
|---|---|
| AMI | Windows Server 2022 Base |
| インスタンスタイプ | t3.large |
| ストレージ | 60GB (gp3) |
| IAMロール | 指定なし |
ADFS用EC2インスタンスにアタッチするセキュリティグループの設定は以下の通りです。
| ポート | プロトコル | 用途 | ソース |
|---|---|---|---|
| 3389 | TCP | RDP(構築・管理用) | 操作端末のグローバルIP(インターネット経由) |
| 443 | TCP | ADFS HTTPS(SAMLエンドポイント) | VPC CIDR |
| 53 | TCP/UDP | DNS | VPC CIDR |
1-2. 検証用 EC2 インスタンスの作成
以下の通り、EC2インスタンスを作成します(ブラウザが使えればいいので、適当でいいです😇)
| 項目 | 推奨値 |
|---|---|
| AMI | Windows Server 2022 Base |
| インスタンスタイプ | t3.small |
| ストレージ | 30GB (gp3) |
| IAMロール | 指定なし |
検証用EC2インスタンスにアタッチするセキュリティグループの設定は以下の通りです。
| ポート | プロトコル | 用途 | ソース |
|---|---|---|---|
| 3389 | TCP | RDP(構築・管理用) | 操作端末のグローバルIP(インターネット経由) |
STEP 2: Active Directory ドメインサービス (ADDS) の構築
yagi.local ドメインを構築し、フェデレーション検証用のADユーザを作成します。
ここから、ADFS用EC2インスタンスにRDP接続して操作を進めます。
2-1. コンピュータ名の変更
Administrator でログイン後、PowerShellを管理者として実行し、コンピュータ名を変更して再起動します。
今回は YAGI-DC-ADFS01 としました。
Rename-Computer -NewName "YAGI-DC-ADFS01" -Restart
再起動後、再度RDP接続します。
2-2. OSの日本語化
ここで、OSの日本語化をしておきます(ADの構築とは直接関係ないですが😅)
こちらのスクリプトを参考にさせていただきました。
管理者権限で、以下のPowerShellスクリプトを実行します。
日本語化スクリプト
function Invoke-LanguagePackCabFileDownload
{
[CmdletBinding()]
param (
[Parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[string] $LangPackIsoUri,
[Parameter(Mandatory = $true)]
[long] $OffsetToCabFileInIsoFile,
[Parameter(Mandatory = $true)]
[long] $CabFileSize,
[Parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[string] $CabFileHash,
[Parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[string] $DestinationFilePath
)
$request = [System.Net.HttpWebRequest]::Create($LangPackIsoUri)
$request.Method = 'GET'
# Set the language pack CAB file data range.
$request.AddRange('bytes', $OffsetToCabFileInIsoFile, $OffsetToCabFileInIsoFile + $CabFileSize - 1)
# Donwload the language pack CAB file.
$response = $request.GetResponse()
$reader = New-Object -TypeName 'System.IO.BinaryReader' -ArgumentList $response.GetResponseStream()
$fileStream = [System.IO.File]::Create($DestinationFilePath)
$contents = $reader.ReadBytes($response.ContentLength)
$fileStream.Write($contents, 0, $contents.Length)
$fileStream.Dispose()
$reader.Dispose()
$response.Close()
$response.Dispose()
# Verify integrity of the downloaded language pack CAB file.
$fileHash = Get-FileHash -Algorithm SHA1 -LiteralPath $DestinationFilePath
if ($fileHash.Hash -ne $CabFileHash) {
throw ('The file hash of the language pack CAB file "{0}" is not match to expected value. The download was may failed.') -f $DestinationFilePath
}
}
function Set-LanguageOptions
{
[CmdletBinding()]
param (
[Parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[string] $UserLocale,
[Parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[string] $InputLanguageID,
[Parameter(Mandatory = $true)]
[int] $LocationGeoId,
[Parameter(Mandatory = $true)]
[bool] $CopySettingsToSystemAccount,
[Parameter(Mandatory = $true)]
[bool] $CopySettingsToDefaultUserAccount,
[Parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[string] $SystemLocale
)
# Reference:
# - Guide to Windows Vista Multilingual User Interface
# https://docs.microsoft.com/en-us/previous-versions/windows/it-pro/windows-vista/cc721887(v=ws.10)
$xmlFileContentTemplate = @'
<gs:GlobalizationServices xmlns:gs="urn:longhornGlobalizationUnattend">
<gs:UserList>
<gs:User UserID="Current" CopySettingsToSystemAcct="{0}" CopySettingsToDefaultUserAcct="{1}"/>
</gs:UserList>
<gs:UserLocale>
<gs:Locale Name="{2}" SetAsCurrent="true"/>
</gs:UserLocale>
<gs:InputPreferences>
<gs:InputLanguageID Action="add" ID="{3}" Default="true"/>
</gs:InputPreferences>
<gs:MUILanguagePreferences>
<gs:MUILanguage Value="{2}"/>
<gs:MUIFallback Value="en-US"/>
</gs:MUILanguagePreferences>
<gs:LocationPreferences>
<gs:GeoID Value="{4}"/>
</gs:LocationPreferences>
<gs:SystemLocale Name="{5}"/>
</gs:GlobalizationServices>
'@
# Create the XML file content.
$fillValues = @(
$CopySettingsToSystemAccount.ToString().ToLowerInvariant(),
$CopySettingsToDefaultUserAccount.ToString().ToLowerInvariant(),
$UserLocale,
$InputLanguageID,
$LocationGeoId,
$SystemLocale
)
$xmlFileContent = $xmlFileContentTemplate -f $fillValues
Write-Verbose -Message ('MUI XML: {0}' -f $xmlFileContent)
# Create a new XML file and set the content.
$xmlFileFilePath = Join-Path -Path $env:TEMP -ChildPath ((New-Guid).Guid + '.xml')
Set-Content -LiteralPath $xmlFileFilePath -Encoding UTF8 -Value $xmlFileContent
# Copy the current user language settings to the default user account and system user account.
$procStartInfo = New-Object -TypeName 'System.Diagnostics.ProcessStartInfo' -ArgumentList 'C:\Windows\System32\control.exe', ('intl.cpl,,/f:"{0}"' -f $xmlFileFilePath)
$procStartInfo.UseShellExecute = $false
$procStartInfo.WindowStyle = [System.Diagnostics.ProcessWindowStyle]::Minimized
$proc = [System.Diagnostics.Process]::Start($procStartInfo)
$proc.WaitForExit()
$proc.Dispose()
# Delete the XML file.
Remove-Item -LiteralPath $xmlFileFilePath -Force
}
# Download the language pack CAB file for Japanese.
#
# Reference:
# - Windows Server 2022 - Evaluation Center
# https://www.microsoft.com/en-us/evalcenter/evaluate-windows-server-2022
$langPackFilePath = Join-Path -Path $env:TEMP -ChildPath 'Microsoft-Windows-Server-Language-Pack_x64_ja-jp.cab'
$params = @{
LangPackIsoUri = 'https://software-static.download.prss.microsoft.com/pr/download/20348.1.210507-1500.fe_release_amd64fre_SERVER_LOF_PACKAGES_OEM.iso'
OffsetToCabFileInIsoFile = 0x107d35800L
CabFileSize = 54130307
CabFileHash = '298667B848087EA1377F483DC15597FD5F38A492'
DestinationFilePath = $langPackFilePath
}
Invoke-LanguagePackCabFileDownload @params -Verbose
# Install the language pack.
Add-WindowsPackage -Online -NoRestart -PackagePath $langPackFilePath -Verbose
# Delete the language pack CAB file.
Remove-Item -LiteralPath $langPackFilePath -Force -Verbose
# Install the Japanese language related capabilities.
Add-WindowsCapability -Online -Name 'Language.Basic~~~ja-JP~0.0.1.0' -Verbose
Add-WindowsCapability -Online -Name 'Language.Fonts.Jpan~~~und-JPAN~0.0.1.0' -Verbose
Add-WindowsCapability -Online -Name 'Language.OCR~~~ja-JP~0.0.1.0' -Verbose
Add-WindowsCapability -Online -Name 'Language.Handwriting~~~ja-JP~0.0.1.0' -Verbose # Optional
Add-WindowsCapability -Online -Name 'Language.Speech~~~ja-JP~0.0.1.0' -Verbose # Optional
Add-WindowsCapability -Online -Name 'Language.TextToSpeech~~~ja-JP~0.0.1.0' -Verbose # Optional
# Set the time zone for the current computer.
Set-TimeZone -Id 'Tokyo Standard Time' -Verbose
$params = @{
UserLocale = 'ja-JP'
InputLanguageID = '0411:{03B5835F-F03C-411B-9CE2-AA23E1171E36}{A76C93D9-5523-4E90-AAFA-4DB112F9AC76}'
LocationGeoId = 122 # Japan
CopySettingsToSystemAccount = $true
CopySettingsToDefaultUserAccount = $true
SystemLocale = 'ja-JP'
}
Set-LanguageOptions @params -Verbose
# Restart the system to take effect changes.
Restart-Computer
2-3. ADDS ロールのインストール
PowerShellを管理者として起動し、以下のコマンドを実行します。
Install-WindowsFeature AD-Domain-Services -IncludeManagementTools
2-4. ドメインコントローラの構築
PowerShellを管理者として起動し、以下のコマンドを実行します。
Import-Module ADDSDeployment
Install-ADDSForest `
-DomainName "yagi.local" `
-DomainNetBiosName "YAGI" `
-ForestMode "WinThreshold" `
-DomainMode "WinThreshold" `
-InstallDns:$true `
-SafeModeAdministratorPassword (ConvertTo-SecureString "P@ssw0rd!Dsrm" -AsPlainText -Force) `
-Force:$true
Install-ADDSForest コマンドの実行後、自動で再起動が走ります。
フォレスト・ドメインの機能レベルを指定する WinThreshold は、Windows Server 2016 の機能レベルを指します。
2-5. ADユーザ test の作成
PowerShellを管理者として起動し、以下のコマンドを実行します。
New-ADUser `
-Name "test" `
-GivenName "Test" `
-Surname "User" `
-SamAccountName "test" `
-UserPrincipalName "test@yagi.local" `
-AccountPassword (ConvertTo-SecureString "UserP@ssw0rd!" -AsPlainText -Force) `
-Enabled $true `
-PasswordNeverExpires $true
# 確認(ユーザ名・UPN・有効状態を確認)
Get-ADUser -Identity "test" -Properties UserPrincipalName, Enabled, PasswordNeverExpires |
Select-Object Name, SamAccountName, UserPrincipalName, Enabled, PasswordNeverExpires
STEP 3: Active Directory 証明書サービス (ADCS) の構築と証明書発行
ADFSのHTTPS通信に使用するSSL証明書を発行するため、ドメイン内認証局(ADCS)を構築します。
3-1. ADCS ロールのインストール
PowerShellを管理者として起動し、以下のコマンドを実行します。
Install-WindowsFeature AD-Certificate, ADCS-Cert-Authority, ADCS-Web-Enrollment -IncludeManagementTools
3-2. エンタープライズ ルートCA の構成
PowerShellを管理者として起動し、以下のコマンドを実行します。
Install-AdcsCertificationAuthority `
-CAType EnterpriseRootCA `
-CACommonName "Yagi-Local-RootCA" `
-CADistinguishedNameSuffix "DC=yagi,DC=local" `
-KeyLength 4096 `
-HashAlgorithmName SHA256 `
-ValidityPeriod Years `
-ValidityPeriodUnits 10 `
-CryptoProviderName "RSA#Microsoft Software Key Storage Provider" `
-Force
インストール後、CA サービスが起動していることを確認します。
Get-Service certsvc
# Status が Running であることを確認
3-3. ADFS 用証明書テンプレートの作成
ADCSの既定テンプレート「Web Server」を複製し、ADFS用にカスタマイズします。
- スタートメニューから
certsrv.msc(証明機関)を起動します。 -
[証明書テンプレート]を右クリックして[管理]を選択します。 -
Web Serverテンプレートを右クリックして[テンプレートの複製]を選択します。 - 複製後、以下のタブを設定します。
| タブ | 設定内容 |
|---|---|
| 全般 | テンプレート表示名: ADFS-SSL
|
| 要求処理 |
秘密キーのエクスポートを許可する にチェック |
| セキュリティ |
YAGI-DC-ADFS01$(コンピュータアカウント)に 登録 権限を追加▼コンピュータアカウントは、 場所の指定 をドメインとして、オブジェクトの種類の選択 をコンピュータにすると表示されます。 ▼ 登録 権限を追加して適用します。
|
続いて、テンプレートを CA に追加します。
-
certsrv.mscの[証明書テンプレート]を右クリックします。 -
[新規作成]→[発行する証明書テンプレート]を選択します。 -
ADFS-SSLを選択してOKをクリックします。
[証明書テンプレート] に ADFS-SSL が表示されれば完了です。

3-4. ADFS 用 SSL 証明書の要求と発行
CSR(証明書署名要求)の作成
adfs_cert_request.inf として以下の内容のファイルを作成し、Cドライブ直下に配置します。
[Version]
Signature="$Windows NT$"
[NewRequest]
Subject = "CN=adfs.yagi.local, OU=IT, O=Yagi, L=Tokyo, S=Tokyo, C=JP"
KeySpec = 1
KeyLength = 2048
Exportable = TRUE
MachineKeySet = TRUE
SMIME = FALSE
PrivateKeyArchive = FALSE
UserProtected = FALSE
UseExistingKeySet = FALSE
ProviderName = "Microsoft RSA SChannel Cryptographic Provider"
ProviderType = 12
RequestType = PKCS10
KeyUsage = 0xa0
HashAlgorithm = SHA256
[EnhancedKeyUsageExtension]
OID = 1.3.6.1.5.5.7.3.1 ; サーバー認証
[Extensions]
; Subject Alternative Name (SAN) - VPC内プライベートFQDNのみ
2.5.29.17 = "{text}"
_continue_ = "dns=adfs.yagi.local&"
_continue_ = "dns=YAGI-DC-ADFS01.yagi.local&"
今回はADFSへのプライベート通信のみを想定するため、SANにはプライベートFQDNのみを記載します(パブリックFQDNは不要です)。
証明書ベースの認証を使用しないため、certauth.adfs.yagi.local をSANに含めていません。
certauth.* はADFSの証明書認証エンドポイント用のFQDNです。
SANに含めないと Install-AdfsFarm 実行時に、SANが certauth.* をサポートしていないことを示す警告メッセージが表示されます。
警告メッセージは無視して問題ないですが、気になるようならSANの記述に以下を追加してください。
_continue_ = "dns=certauth.adfs.yagi.local&"
PowerShellを管理者として起動し、以下のコマンドを実行してCSRを生成します。
certreq -new C:\adfs_cert_request.inf C:\adfs_cert_request.csr
certreq -new 実行時に The parameter is incorrect と表示される場合、.inf ファイルの文字コードが原因となっていることがあります。
ファイルをBOM無しUTF-8またはANSIで保存し直して再実行してみてください。
CSR を CA に送信して証明書を発行
PowerShellを管理者として起動し、以下のコマンドを実行します。
certreq -submit -attrib "CertificateTemplate:ADFS-SSL" `
C:\adfs_cert_request.csr `
C:\adfs_cert.cer
コマンド実行後、「証明機関の一覧」が表示されるので、OK をクリックします。

certreq -submit 実行時に The permissions on the certificate template do not allow the current user to enroll for this type of certificate と表示される場合、テンプレートのセキュリティ設定でコンピュータアカウントに 登録 権限が付与されていないことが考えられます。
3-3の証明書テンプレート設定にて、コンピュータアカウント YAGI-DC-ADFS01$ に 登録 権限の追加をしましたが、その設定が反映されているか確認してください。
証明書を個人ストアにインストール
PowerShellを管理者として起動し、以下のコマンドを実行します。
certreq -accept C:\adfs_cert.cer
3-5. ルートCA証明書のエクスポート
後続のSTEP 10で検証用サーバに信頼させるため、ルートCA証明書をエクスポートします。
PowerShellを管理者として起動し、以下のコマンドを実行します。
$caName = (Get-ItemProperty "HKLM:\SYSTEM\CurrentControlSet\Services\CertSvc\Configuration").Active
certutil -store "Root" "$caName" C:\YagiRootCA.cer
エクスポートした YagiRootCA.cer は検証用サーバへの転送が必要なため、保管しておきます。
STEP 4: Active Directory Federation Services (ADFS) の構築
ADFSロールをインストールし、STEP 3で発行したSSL証明書を使ってADFSファームを構成します。
4-1. ADFS ロールのインストール
PowerShellを管理者として起動し、以下のコマンドを実行します。
Install-WindowsFeature ADFS-Federation -IncludeManagementTools
4-2. ADFS の構成
PowerShellを管理者として起動し、以下のコマンドを実行します。
# 証明書取得
$cert = Get-ChildItem Cert:\LocalMachine\My | Where-Object { $_.Subject -like "*adfs.yagi.local*" }
$cert | Format-List Subject, Thumbprint, NotAfter
# ADFS構成
Import-Module ADFS
Install-AdfsFarm `
-CertificateThumbprint $cert.Thumbprint `
-FederationServiceName "adfs.yagi.local" `
-FederationServiceDisplayName "Yagi ADFS" `
-ServiceAccountCredential (Get-Credential -Message "ADFSサービスアカウントのパスワードを入力" -UserName "YAGI\Administrator")
Install-AdfsFarm コマンド実行後、サービスアカウントのパスワードを入力するポップアップが表示されます。

今回は検証環境のため Administrator をADFSサービスアカウントとして利用しています。
実運用では、以下のような専用アカウントの利用が推奨されます。
- gMSA(Group Managed Service Account)
- ADFS専用のドメインユーザ
特にgMSAを利用すると、サービスアカウントのパスワード管理をActive Directory側で自動化できるため、安全かつ運用負荷を低減できます。
4-3. Install-AdfsFarm 実行後の再起動
ADFSファームの構成が完了すると再起動を促すメッセージが表示されるので、OSを再起動します。
PowerShellを管理者として起動し、以下のコマンドを実行します。
Restart-Computer
再起動後、再度RDP接続します。
4-4. DNS Aレコードの登録
adfs.yagi.local の名前解決ができるよう、DNSにAレコードを登録します。PowerShellを管理者として起動し、以下のコマンドを実行します。
# YAGI-DC-ADFS01自身のプライベートIPを取得
$ip = (Get-NetIPAddress -AddressFamily IPv4 -InterfaceAlias "Ethernet*").IPAddress
# adfs.yagi.local のAレコードを登録
Add-DnsServerResourceRecordA -ZoneName "yagi.local" -Name "adfs" -IPv4Address $ip
# 確認
Get-DnsServerResourceRecord -ZoneName "yagi.local" -Name "adfs"
$ip に複数のIPアドレスが取得される場合(複数NICやループバック等)、Add-DnsServerResourceRecordA が失敗することがあります。
その場合は、 Get-NetIPAddress -AddressFamily IPv4 -InterfaceAlias "Ethernet*" で一覧を確認し、プライベートIPを直接 -IPv4Address "172.31.xx.xx" のように指定してください。
4-5. ADFSサービスの確認
PowerShellを管理者として起動し、以下のコマンドを実行してADFSサービスが起動していることを確認します。
Get-Service adfssrv
# Status が Running であることを確認
4-6. フェデレーションメタデータの取得
PowerShellを管理者として起動し、以下のコマンドを実行してメタデータXMLを取得します。
Invoke-WebRequest -Uri "https://adfs.yagi.local/federationmetadata/2007-06/federationmetadata.xml" `
-OutFile "C:\ADFS_FederationMetadata.xml" `
-UseBasicParsing
後続で取得するOCI の SP メタデータファイルと混ざらないように、「ADFS_FederationMetadata.xml」というファイル名でCドライブ直下に出力しています。
STEP 5: OCI側の Identity Federation 設定
OCIコンソールにADFSをIDプロバイダとして登録し、IdPポリシーを設定してOCIコンソールと連携させます。
5-1. フェデレーション画面へのアクセス
- OCIコンソールにログインします。
-
ハンバーガーメニュー→アイデンティティとセキュリティ→ドメインを開きます。 - ADFS連携するユーザが存在するドメインを選択します(今回は
Defaultドメイン)。 -
フェデレーションタブをクリックします。
5-2. OCI の SP メタデータのエクスポート
IDプロバイダを追加する前に、OCI側のSPメタデータをエクスポートします。
このファイルは後続のADFS設定(STEP 6)で使用します。
-
フェデレーションタブ上部のSAMLメタデータのエクスポートボタンをクリックします。
-
メタデータ・ファイルが選択されていることを確認します。 -
自己署名証明書を含むメタデータの行のXMLのダウンロードをクリックします。
- ダウンロードされたXMLファイル(
ADFS_Metadata.xml)を保管しておきます。
自己署名証明書を含むメタデータ を使用することで、ADFS側のCRL/OCSPチェックをバイパスできるようです。
5-3. SAML IdP(IDプロバイダ)の追加
IdPの作成
| 項目 | 入力値 |
|---|---|
| 名前 | ADFS-yagi-local |
| 説明 | AWS EC2上のADFS (yagi.local) |
| IdPメタデータのインポート | STEP 4-6 で取得した ADFS_FederationMetadata.xml をアップロード |
| リクエストされた名前IDフォーマット |
なし(デフォルト) |
| アイデンティティ・プロバイダ・ユーザー属性 |
SAMLアサーション名ID(デフォルト) |
| マップ先(アイデンティティ・ドメイン・ユーザー属性) |
ユーザー名(デフォルト) |
ADFSはSTEP 6-3で設定する emailAddress 形式でNameID(test@yagi.local)を送信します。
OCI側は受け取ったNameIDの値をそのままユーザー名として検索するため、デフォルト設定で正しくマッピングされます。
できました。
IdPの作成直後は、ステータスが 非アクティブ になっているので、次の手順でアクティブ化します。

IdPのアクティブ化とポリシー設定
IdPポリシーのルール設定
- 遷移先の画面で
IdPポリシーの作成をクリックします。
- 名前に
ADFS Federation Policyを入力します(任意の名前で構いません)。 -
アイデンティティ・プロバイダ・ポリシーの作成をクリックします。
- 遷移先の画面で
IdPルールの追加をクリックします。
- 以下を入力して
IdPルールの追加をクリックします。
| 項目 | 設定値 |
|---|---|
| ルール名 | ADFS-yagi-local-rule |
| アイデンティティ・プロバイダの割当て | ADFS-yagi-local |
| 式配置 |
式で始まる ※デフォルト |
| ユーザー名式の入力 | 空欄 ※デフォルト(すべてのユーザーを対象とする) |
| ユーザーを除外 | ADFSを経由させたくないユーザ(特権ユーザー等)を指定する |
| クライアントIPアドレスでフィルタ | 任意の場所 |
ユーザーを除外 に指定したユーザはこのIdPルールの対象外となり、OCIのローカル認証(パスワードログイン)が使用されます。
ルートユーザーや緊急アクセス用の特権ユーザーはここに登録しておくことを推奨します。
IdPとOCIコンソールの連携
STEP 6: ADFS に OCI の証明書利用者信頼 (Relying Party Trust) を追加
ADFS側にOCIをサービスプロバイダ(SP)として登録し、SAMLアサーションに含めるクレームルールを設定します。
6-1. ADFS 管理コンソールの起動
6-2. 証明書利用者信頼の追加
PowerShellを管理者として起動し、以下のコマンドを実行します。
事前にSTEP 5-2でエクスポートした ADFS_Metadata.xml を C:\OCI_SP\ 配下に配置してておいてください。
# OCIのSPメタデータXMLを C:\OCI_SP\ 配下に配置済みとして実行
# (STEP 5-2 でエクスポートした ADFS_Metadata.xml を YAGI-DC-ADFS01 に転送し、
# ADFS側のメタデータ ADFS_FederationMetadata.xml と混同を避けるため、別フォルダに配置)
$metadataPath = "C:\OCI_SP\ADFS_Metadata.xml"
Add-AdfsRelyingPartyTrust `
-Name "OCI-Console" `
-MetadataFile $metadataPath `
-AutoUpdateEnabled $false `
-MonitoringEnabled $false `
-Enabled $true
# 確認
Get-AdfsRelyingPartyTrust -Name "OCI-Console"
6-3. 要求発行変換規則 (Claim Issuance Policy) の設定
OCI IAM ユーザ名(test@yagi.local)と AD の UPN(test@yagi.local)を一致させるため、NameID に UPN の値をそのままメールアドレス形式で送信する規則を設定します。
PowerShellを管理者として起動し、以下のコマンドを実行します。
ユーザ名マッピングの方針:
- AD ユーザ UPN:
test@yagi.local- SAML NameID として送信する値:
test@yagi.local(UPN、emailAddress形式)- OCI IAM ユーザ名も
test@yagi.localで作成しておくことで、NameID の値と完全一致し自動的にマッピングされる。
項目 値 AD UPN test@yagi.localADFS が NameID として送信する値 test@yagi.localOCI が検索する IAM ユーザ名 test@yagi.local
# 規則1: AD から UPN と sAMAccountName を取得
$rule1 = @"
@RuleTemplate = "LdapClaims"
@RuleName = "Get AD Attributes"
c:[Type == "http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsaccountname",
Issuer == "AD AUTHORITY"]
=> issue(store = "Active Directory",
types = (
"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/upn",
"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/samaccountname"
),
query = ";userPrincipalName,sAMAccountName;{0}",
param = c.Value);
"@
# 規則2: UPN を NameID(emailAddress形式)として送信
# → "emailAddress" はSAMLのNameIDフォーマットの識別子名であり、
# 実際にメールアドレスとして有効である必要はない。
# "@" を含む文字列であれば "test@yagi.local" のようなローカルドメインでも問題なく動作する。
# → OCIはこの値("test@yagi.local")を文字列としてIAMユーザ名と照合する。
$rule2 = @"
@RuleName = "Send UPN as NameID"
c:[Type == "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/upn"]
=> issue(Type = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier",
Issuer = c.Issuer,
OriginalIssuer = c.OriginalIssuer,
Value = c.Value,
ValueType = c.ValueType,
Properties["http://schemas.xmlsoap.org/ws/2005/05/identity/claimproperties/format"] =
"urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress");
"@
Set-AdfsRelyingPartyTrust `
-TargetName "OCI-Console" `
-IssuanceTransformRules ($rule1 + $rule2)
# 設定確認
Get-AdfsRelyingPartyTrust -Name "OCI-Console" | Select-Object -ExpandProperty IssuanceTransformRules
6-4. 発行承認規則 (Issuance Authorization Rules) の設定
デフォルトでは全ユーザのトークン発行が拒否されるため、許可する規則を追加します。
PowerShellを管理者として起動し、以下のコマンドを実行します。
# ADFS に正常認証できたユーザーは、OCI-Console へのトークン発行を許可する
$authRule = @"
@RuleTemplate = "AllowAllAuthzRule"
=> issue(Type = "http://schemas.microsoft.com/authorization/claims/permit",
Value = "true");
"@
Set-AdfsRelyingPartyTrust `
-TargetName "OCI-Console" `
-IssuanceAuthorizationRules $authRule
# 設定確認
Get-AdfsRelyingPartyTrust -Name "OCI-Console" | Select-Object -ExpandProperty IssuanceAuthorizationRules
STEP 7: OCI IAM ユーザの設定
ADユーザのUPNと一致するユーザ名でOCI IAMユーザを作成し、フェデレーテッド認証を有効化します。
7-1. IAMユーザの作成
- OCIコンソールにログインします。
-
ハンバーガーメニュー→アイデンティティとセキュリティ→ドメインを開きます。 -
Defaultドメインをクリックします。 -
ユーザー管理タブをクリックします。 - ユーザの
作成ボタンをクリックします。 - 以下を入力して
作成をクリックします。
| 項目 | 値 |
|---|---|
| 名 |
TEST(任意) |
| 姓 |
ADFS(任意) |
| ユーザー名として電子メール・アドレスを使用 | オフ |
| ユーザー名 | test@yagi.local |
| 電子メール | 有効なメールアドレス(例: test@example.com) |
ユーザー名として電子メール・アドレスを使用 をオフにすることで、ユーザー名と電子メールを別々に設定できます。
.local ドメインのメールアドレスは一般的なインターネットメールとしては利用できないため、電子メール欄には実在する有効なアドレスを入力する必要があります。
※電子メール として test@yagi.local を指定するとエラーになります。
認証に使用されるのはユーザー名(test@yagi.local)のみであり、電子メールはOCIからの通知用途にすぎません。
なお、OCI IAM のユーザ名には @ を含めることができます。
ここでは、OCI IAM のユーザ名と AD の UPN と完全一致させることが重要です。
ADFSフェデレーションの検証が目的なので、今回はグループの指定はしません。
7-2. IAMユーザのフェデレーテッドの有効化
- 作成したユーザー
test@yagi.localをクリックします。 -
ユーザーの編集ボタンをクリックします。
-
アイデンティティ・プロバイダ情報セクションのフェデレーテッドをオンにします。
-
変更の保存をクリックします。
・・・
この設定を行うことで、当該のIAMユーザではOCIのローカル認証(パスワードログイン)は利用できなくなります。
この状態で、ログイン画面の「Forgot Password?」ボタンをクリックして、当該のIAMユーザのパスワードリセットを行おうとしても、それができないことは確認済みです。
パスワード・リセット通知送信済 と表示されますが、実際にそのメールは届きません。

STEP 8: フェデレーテッドユーザのMFA無効化設定(任意)
OCI Identity Domains のデフォルト設定では、すべてのIAMユーザにMFAが要求されます。
「AD側でADユーザのMFAが設定されていてOCI側でのMFAは必須ではない」というケースでは、フェデレーテッドユーザのMFA無効化が可能です。
こちらのブログに従って、OCI側のMFAを無効化するサインオンルールを追加します。
8-1. サインオン・ポリシーへのルール追加
- OCIコンソールにログインします。
-
ハンバーガーメニュー→アイデンティティとセキュリティ→ドメイン→Defaultを開きます。 -
ドメイン・ポリシー→サインオン・ポリシー→Security Policy for OCI Consoleを選択します。 -
サインオン・ルールの追加をクリックします。
- 以下を設定します。
| 項目 | 設定値 |
|---|---|
| ルール名 | Federated-Users-NoMFA |
| 条件(認証アイデンティティ・プロバイダ) |
ADFS-yagi-local を選択 |
| その他の設定 | すべてデフォルトのまま |
ここで、追加ファクタの要求 がオフになっていることを確認してください。
「ほんまにMFAオフでええんか?」と同意を求めるチェックボックスが表示されるので、✅を入れて、理由も入れておきます。

追加 をクリックして、ルールが追加できればOKです。
8-2. ルールの優先度を最高位に設定
優先度ポリシーに基づき、追加したルールを最上位に配置する必要があります。
- ルール一覧で
Federated-Users-NoMFAを選択します。 -
優先度の編集をクリックします。
-
Federated-Users-NoMFAの優先度を1に設定します。
それに従って、他のルールの優先度も調整します(1個優先度を下げる)
STEP 9: DNS 設定の確認
ADDS インストール時にDNSサーバロールも同時にインストールされているため、YAGI-DC-ADFS01 自身がDNSサーバとして機能します。
DNSサーバとして正しく動作していることを確認します。
PowerShellを管理者として起動し、以下のコマンドを実行します。
Get-Service DNS
# Status が Running であることを確認
Get-DnsServerZone | Select-Object ZoneName, ZoneType
# "yagi.local" ゾーンが存在することを確認
STEP 10: 検証用サーバの準備
AD・ADFSサーバ(YAGI-DC-ADFS01)側の設定が完了したら、検証用サーバ(ドメイン非参加)で以下の設定を行います。
動作確認の前提として、内部CAが発行した証明書を信頼させ、adfs.yagi.local の名前解決ができる状態にします。
ここから、検証用EC2インスタンスにRDP接続して操作を進めます。
10-1. ルートCA証明書のコピー
YAGI-DC-ADFS01 でエクスポートした YagiRootCA.cer を検証用サーバのCドライブ直下にコピーします(RDP経由でファイル転送)。
10-2. ルートCA証明書のインポート
検証用サーバ上でPowerShellを管理者として起動し、以下のコマンドを実行します。
certutil -addstore "Root" C:\YagiRootCA.cer
続いて、以下のコマンドでインポートを確認します。
Get-ChildItem Cert:\LocalMachine\Root | Where-Object { $_.Subject -like "*Yagi*" } |
Select-Object Subject, Thumbprint, NotAfter
# "Yagi-Local-RootCA" が表示されれば信頼済み
10-3. DNSサーバの設定
検証用サーバのネットワークアダプタに、YAGI-DC-ADFS01 のプライベートIPをDNSサーバとして設定します。
PowerShellを管理者として起動し、以下のコマンドを実行します。
# ネットワークインターフェース名(Ethernet)を確認
Get-NetAdapter
# DNSサーバをYAGI-DC-ADFS01のプライベートIPに設定
Set-DnsClientServerAddress -InterfaceAlias "Ethernet" -ServerAddresses "172.31.xx.xx"
# 確認
Get-DnsClientServerAddress -InterfaceAlias "Ethernet"
Set-DnsClientServerAddress 実行時に No MSFT_DNSClientServerAddress objects found と表示される場合、インターフェース名が Ethernet と異なります。
Get-NetAdapter で実際のインターフェース名を確認し、-InterfaceAlias に正しい名前を指定してください。
10-4. 名前解決の確認
PowerShellを管理者として起動し、以下のコマンドを実行して adfs.yagi.local が正しく解決されることを確認します。
Resolve-DnsName adfs.yagi.local
# YAGI-DC-ADFS01のプライベートIPが返ることを確認
10-5. ADFS の動作確認(検証用サーバのブラウザから)
ブラウザから以下のURLにアクセスし、ADFSのログインページが表示されることを確認します。
https://adfs.yagi.local/adfs/ls/idpinitiatedsignon
An error occurred - The resource you are trying to access is not available. と表示されますが、想定通りです。
これはIdP起点(IdP-initiated)のSSOでADFSに直接アクセスした際、発行承認規則(Issuance Authorization Rules)でユーザーのアクセスが拒否されているために発生します(ADFSサーバ側のイベントビューアーでは「EventID 325」で記録されています)。
SP起点(SP-initiated)のSSO(OCIコンソールのログイン画面からADFSにリダイレクトされるフロー)では発生しないため、SSOの動作確認が正常に完了していれば無視して問題ありません。
が、もしエラーを解消したい場合は、ADFS側でIdP起点のSSOを有効にします。
# IdP起点のSSOの有効化
Set-AdfsProperties -EnableIdPInitiatedSignonPage $true
# 確認
Get-AdfsProperties | Select-Object EnableIdPInitiatedSignonPage
IdP起点のSSOの有効化が完了したら、再度 https://adfs.yagi.local/adfs/ls/idpinitiatedsignon にアクセスしてみてください。
ID・パスワードの入力フォームが出てくるはずです。
STEP 11: 動作確認
検証用サーバからOCIコンソールにアクセスし、ADFS認証でログインできることを確認します。
- 検証用サーバのブラウザからOCIコンソールのURLにアクセスします。
https://www.oracle.com/cloud/sign-in.html - テナント名を入力して
次へをクリックします。 -
ADFS-yagi-localをクリックします。
- AD FS のログインページにリダイレクトされることを確認します。
- ユーザ名
test@yagi.local/ パスワードUserP@ssw0rd!を入力します。 - OCI マネジメントコンソールに
test@yagi.localユーザとしてログインできることを確認します。
OCIコンソールへのSSOが確認できました!
ADFSのログインページで認証後、何らかのエラーが表示される場合は、「YAGI-DC-ADFS01」側のイベントビューアー(eventvwr.msc)を開き、 アプリケーションとサービスログ → AD FS → Admin からエラーの詳細を確認してください。
通信フロー
最後に、本構成におけるSAML SSOの通信フローを整理します。
各通信がインターネット経由か内部NW経由かに着目してください。
認証時のSAMLアサーションはブラウザ経由で運ばれ(③〜⑧)、ADFSとOCIが直接SAMLアサーションを送受信するわけではありません。
また、③〜⑤・⑧のブラウザ↔ADFS間の通信から、⑥⑦のAD認証まで、すべて内部NW(VPC内)に閉じた通信です。
この構成により、ADFSを開発・本番で分けて内部NWのFWで通信制御することで、OCI側のIPアドレスによるアクセス制御に頼らずに環境の分離を実現できます。
補足(全IAMユーザへのADFS強制について)
OCIの全IAMユーザに強制的にADFSを利用させる設定も可能です。
しかし、ADFSサーバや内部NWで障害が発生し、ADFS認証が利用できなくなったとき、暫定対応として一時的にIAMユーザのパスワード認証を利用することも想定されます。
そのため、本記事では、あくまでOCIコンソールの認証画面ではOCIのローカル認証(パスワードログイン)とADFS認証を選択できるようにし、IAMユーザ側の設定(STEP 7-2)でIdPをADFSに誘導してあげることを推奨します。
これにより、一般ユーザはADFS認証に限定するが、ルートユーザーや緊急アクセス用の特権ユーザーはADFS認証を利用しない、という設計が可能になります。










