この記事では、Azure AD Connect(以下AADC)でArgumentOutOfRangeExceptionエラーが発生したときの原因と解決方法についてまとめています。
概要
Azure AD Connectのインストール時、[Connectディレクトリ]から[Azure ADサインイン]に遷移するときに以下のようなエラーが発生しました。。
以下はログの内容の一部です。
[13:14:03.574] [ 6] [INFO ] SyncDataProvider: Calling refresh schema on connector XXXXXXXX.com [13:14:04.199] [ 6] [ERROR] ConfigSyncDirectoriesPage: Caught exception while creating the connector for directory: XXXXXXXX.com. Exception Data (Raw): System.Management.Automation.CmdletInvocationException: Failed to set the connector. <error>E_MMS_SCHEMA_CYCLE_IN_CLASS_HIERARCHY</error> ---> Microsoft.IdentityManagement.PowerShell.ObjectModel.SynchronizationConfigurationValidationException: Failed to set the connector. <error>E_MMS_SCHEMA_CYCLE_IN_CLASS_HIERARCHY</error> 場所 Microsoft.DirectoryServices.MetadirectoryServices.UI.WebServices.MMSWebService.GetSchemaFromDirectory(Connector connector, Boolean commit) 場所 Microsoft.IdentityManagement.PowerShell.Cmdlet.UpdateADSyncConnectorSchemaCmdlet.ProcessRecord() --- 内部例外スタック トレースの終わり --- 場所 System.Management.Automation.Runspaces.PipelineBase.Invoke(IEnumerable input) 場所 System.Management.Automation.PowerShell.Worker.ConstructPipelineAndDoWork(Runspace rs, Boolean performSyncInvoke) 場所 System.Management.Automation.PowerShell.Worker.CreateRunspaceIfNeededAndDoWork(Runspace rsToUse, Boolean isSync) 場所 System.Management.Automation.PowerShell.CoreInvokeHelper[TInput,TOutput](PSDataCollection`1 input, PSDataCollection`1 output, PSInvocationSettings settings) 場所 System.Management.Automation.PowerShell.CoreInvoke[TInput,TOutput](PSDataCollection`1 input, PSDataCollection`1 output, PSInvocationSettings settings) 場所 System.Management.Automation.PowerShell.Invoke(IEnumerable input, PSInvocationSettings settings) 場所 Microsoft.Online.Deployment.PowerShell.LocalPowerShell.Invoke() 場所 Microsoft.Online.Deployment.PowerShell.PowerShellAdapter.TypeDependencies.InvokePowerShell(IPowerShell powerShell) 場所 Microsoft.Online.Deployment.PowerShell.PowerShellAdapter.InvokePowerShellCommand(String commandName, InitialSessionState initialSessionState, IDictionary`2 commandParameters, Boolean isScript) 場所 Microsoft.Azure.ActiveDirectory.Synchronization.PowerShellConfigAdapter.ConnectorConfigAdapter.UpdateConnectorSchema(Connector connector) 場所 Microsoft.Azure.ActiveDirectory.Synchronization.Config.ConnectorAdapterBase.UpdateConnectorSchema() 場所 Microsoft.Online.Deployment.Types.Providers.SyncDataProvider.UpdateConnectorSchema(ConnectorAdapterBase connectorAdapter) 場所 Microsoft.Online.Deployment.OneADWizard.UI.WizardPages.ConfigSyncDirectoriesPageViewModel.CreateADDSConnector(IDirectoryConnection directory) 場所 Microsoft.Online.Deployment.OneADWizard.UI.WizardPages.ConfigSyncDirectoriesPageViewModel.CreateConnectors(Object obj) [13:14:04.215] [ 9] [INFO ] Page transition from "Connect ディレクトリ" [ConfigSyncDirectoriesPageViewModel] to "Azure AD サインイン" [UserSignInConfigPageViewModel] [13:14:04.215] [ 9] [ERROR] RootWizardPageViewModel: An unhandled exception occurred during a page load. Exception Data (Raw): System.ArgumentOutOfRangeException: インデックスが範囲を超えています。負でない値で、コレクションのサイズよりも小さくなければなりません。 パラメーター名:index 場所 System.ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument argument, ExceptionResource resource) 場所 Microsoft.Online.Deployment.OneADWizard.UI.WizardPages.UserSignInConfigPageViewModel.OnLoad(NavigateDirection direction) 場所 Microsoft.Online.Deployment.Framework.UI.WizardPages.RootWizardPageViewModel.ActivatePage(IWizardPage page, NavigateDirection direction) [13:14:04.215] [ 9] [ERROR] A terminating unhandled exception occurred. Exception Data (Raw): System.AggregateException: 1 つ以上のエラーが発生しました。 ---> System.ArgumentOutOfRangeException: インデックスが範囲を超えています。負でない値で、コレクションのサイズよりも小さくなければなりません。 パラメーター名:index 場所 System.ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument argument, ExceptionResource resource) 場所 Microsoft.Online.Deployment.OneADWizard.UI.WizardPages.UserSignInConfigPageViewModel.OnLoad(NavigateDirection direction) 場所 Microsoft.Online.Deployment.Framework.UI.WizardPages.RootWizardPageViewModel.ActivatePage(IWizardPage page, NavigateDirection direction) 場所 Microsoft.Online.Deployment.Framework.UI.WizardPages.RootWizardPageViewModel.MoveNext() 場所 Microsoft.Online.Deployment.OneADWizard.UI.WizardPages.ConfigSyncDirectoriesPageViewModel.WaitForTaskCompletion(Task task) 場所 System.Threading.Tasks.Task.Execute() --- 内部例外スタック トレースの終わり --- ---> (内部例外 #0) System.ArgumentOutOfRangeException: インデックスが範囲を超えています。負でない値で、コレクションのサイズよりも小さくなければなりません。 パラメーター名:index 場所 System.ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument argument, ExceptionResource resource) 場所 Microsoft.Online.Deployment.OneADWizard.UI.WizardPages.UserSignInConfigPageViewModel.OnLoad(NavigateDirection direction) 場所 Microsoft.Online.Deployment.Framework.UI.WizardPages.RootWizardPageViewModel.ActivatePage(IWizardPage page, NavigateDirection direction) 場所 Microsoft.Online.Deployment.Framework.UI.WizardPages.RootWizardPageViewModel.MoveNext() 場所 Microsoft.Online.Deployment.OneADWizard.UI.WizardPages.ConfigSyncDirectoriesPageViewModel.WaitForTaskCompletion(Task task) 場所 System.Threading.Tasks.Task.Execute()<--- [13:14:04.262] [ 1] [INFO ] Page transition from "Azure AD サインイン" [UserSignInConfigPageViewModel] to "エラー" [ErrorPageViewModel] [13:14:04.262] [ 1] [INFO ] UserSignInConfigPageViewModel : UPN attribute: [13:14:13.316] [ 1] [INFO ] Opened log file at path C:\ProgramData\AADConnect\trace-20210823-131153.log
対策
今回、このエラーの原因となっていたのは同期対象のADに不正な独自クラススキーマが存在していたことでした。具体的には「構造化クラスのサブクラスである補助クラス」が存在するADに接続した場合、上記のエラーが発生します。
切り分け
まず、上記の条件がエラーの原因であるか切り分けます。
Ldifdeコマンドでtopのサブクラスでない補助クラスのdnとサブクラスを表示します。以下はADサーバで直接実行する例です。
Ldifde -f export_1.txt -d cn=schema,cn=configuration,dc=[ドメイン名] -r "(&(objectClass=classSchema)(objectClassCategory=3)(!(subClassOf=top)))" -l dn,subClassOf
出力ファイルを確認し、subClassOfが構造化クラスになっているものがあればそれがエラーの原因である可能性が高いです。筆者の環境の場合は構造クラスpersonのサブクラスである補助クラスが存在していたために発生していました。
このエラーを解決するには問題のクラスを無効化する必要があるのですが、そのクラスを使用している場合は無効化すると影響が出る場合があります。そのため、問題のクラスを使用しているか確認します。
以下のコマンドで問題となるクラスを補助クラスとして使用しているクラスを検索します。
Ldifde -f export_2.txt -d cn=schema,cn=configuration,dc=[ドメイン名] -r "(auxiliaryClass=[クラス名])"
何も出力されていなければ当該クラスは使用されていないため、以下の解決方法により無効化できます。出力された場合、その属性を使用しているシステムを停止するなどし、影響がでないようにしてから無効化します。
解決方法
スタートメニューで[ADSIエディター]と検索し、ADSIエディターを起動します。
[操作]>[接続]から接続ダイアログを起動し、[既知の名前付けコンテキストを選択する] から [スキーマ] を選択して [OK] をクリックするとスキーマの一覧が表示されます。スキーマの一覧から先程確認したクラススキーマを選択し右クリック>[プロパティ]を選択します。
属性エディターの一覧から[isDefunct]を選択し[編集]をクリックします。
[True]を選択し[OK]をクリックします。再度有効化する場合は[isDefunct]を[False]にします。
これでAADCを再度インストールすると、エラーが出なくなりました。
解説
エラー22行目から画面表示と同様のエラーが出ているのでここが原因かと思いきや、1,2行目から発生している「Calling refresh schema」の失敗が原因でした。
このエラーの原因は「構造化クラスのサブクラスである補助クラス」の存在が原因でした。なぜこのクラスがエラーを引き起こすかというと、そもそもLDAPの仕様に準拠していない状態になっているからです。
ADは、ディレクトリツリーの情報を保存するために内部でLDAPを使用しています。このLDAPでは補助クラスを構造化クラスのサブクラスにすることはできない仕様になっています。
オブジェクトクラス
LDAPにはオブジェクトクラスという概念があります。一つ一つの属性をそれぞれエントリに割り当てるのではなく、共通点のある複数の属性をオブジェクトクラスにまとめて、オブジェクトクラスをインスタンスに割り当てます。例えばユーザに割り当てる属性をまとめたperson、デバイスに割り当てる属性をまとめたdeviceなどがあります。
オブジェクトクラスには3つの種類が存在します。構造化クラス、抽象クラス、補助クラスです。
構造化クラスは唯一インスタンスを生成できるクラスです。
抽象クラスはインスタンスを生成することができないクラスです。そのままオブジェクトクラスとして使用するのではなく、構造化クラスに派生させることで使用します。
補助クラスは複数のクラスの共通の属性をまとめるクラスです。クラスを派生させ、そこに属性を保持させると完全な木構造になりますが、この場合複数のオブジェクトクラスは共通の属性を持つことができません。そこで補助クラスに共通の属性を定義し、それぞれのクラスに補助クラスの定義を含めることで実現します。
オブジェクトクラスの派生ルール
3種類のオブジェクトクラスにはスーパークラス(派生元)とサブクラス(派生先)に以下の表のようなルールがあります。これらの仕様はRFC4512で規定されています。
サブクラス | ||||
構造化クラス | 抽象クラス | 補助クラス | ||
スーパークラス | 構造化クラス | ○ | ☓ | ☓ |
抽象クラス | ○ | ○ | ○ | |
補助クラス | ☓ | ○ | ○ |
- 構造化クラスは構造化クラスのみをサブクラスにできる
- 抽象クラスはすべてのクラスをサブクラスにできる
- 補助クラスは抽象クラス、補助クラスをサブクラスにできる
以上より、補助クラスを構造化クラスのサブクラスにすることはできません。
今回のエラーの原因は規定外にも関わらずADで「構造化クラスのサブクラスである補助クラス」を設定できてしまうことでした。
インスタンスを生成する構造化クラスを共通部分として定義する補助クラスに派生させるという設計をすることは考えにくいので、設定のミスによるものではないかと考えられます。