AD Connector の前提条件 - AWS Directory Service

AD Connector の前提条件

AD Connector を使用して既存のディレクトリに接続するには、以下が必要です。

VPC

次のように VPC を設定します。

  • 少なくとも 2 つのサブネット。各サブネットはそれぞれ異なるアベイラビリティーゾーンにある必要があります。

  • VPC は、バーチャルプライベートネットワーク (VPN) 接続または AWS Direct Connect を通じて既存のネットワークに接続されている必要があります。

  • VPC にはデフォルトのハードウェアテナンシーが必要です。

AWS Directory Service は、2 つの VPC 構造を使用します。ディレクトリを構成する EC2 インスタンスは、AWS アカウントの外部で実行され、AWS によって管理されます。これらには、2 つのネットワークアダプタ (ETH0 および ETH1) があります。ETH0 は管理アダプタで、アカウント外部に存在します。ETH1 はアカウント内で作成されます。

ディレクトリの ETH0 ネットワークの管理 IP 範囲は、ディレクトリがデプロイされている VPC と競合しないようにするため、プログラムによって選択されます。この IP 範囲は、(ディレクトリが 2 つのサブネットで実行されるため) 次のいずれかのペアになります。

  • 10.0.1.0/24 と 10.0.2.0/24

  • 192.168.1.0/24 と 192.168.2.0/24

ETH1 CIDR の最初のオクテットをチェックすることで、競合を回避します。10 で始まる場合は、192.168.1.0/24 と 192.168.2.0/24 のサブネットを持つ 192.168.0.0/16 VPC を選択します。最初のオクテットが 10 以外である場合は、10.0.1.0/24 と 10.0.2.0/24 のサブネットを持つ 10.0.0.0/16 VPC を選択します。

選択アルゴリズムには、VPC 上のルートは含まれません。そのため、このシナリオから IP ルーティングの競合が発生する可能性があります。

VPC は次の VPC エンドポイントを使用して設定することはできません

詳細については、「Amazon VPC ユーザーガイド」の次のトピックを参照してください。

AWS Direct Connect の詳細については、「AWS Direct Connect ユーザーガイド」を参照してください。

既存の Active Directory

Active Directory ドメインを持つ既存のネットワークに接続する必要があります。

注記

AD Connector は、単一ラベルのドメインをサポートしていません。

このドメインの機能レベルは Windows Server 2003 以上である必要があります。AD Connector は、Amazon EC2 インスタンスでホストされているドメインへの接続もサポートしています。

注記

AD Connector は、Amazon EC2 のドメイン結合機能と併用する場合の読み取り専用ドメインコントローラー (RODC) をサポートしていません。

サービスアカウント

次の権限が委任されている既存のディレクトリのサービスアカウントの認証情報が必要です。

  • ユーザーおよびグループの読み取り - 必須

  • コンピュータのドメインへの結合 - シームレスなドメイン結合と WorkSpaces を使用する場合にのみ必要

  • コンピュータオブジェクトの作成 - シームレスなドメイン結合と WorkSpaces を使用する場合にのみ必要

詳細については、「権限をサービスアカウントに委任する」を参照してください。

注記

AD Connector は、AWS アプリケーションの認証および許可に Kerberos を使用します。LDAP は、ユーザーおよびグループオブジェクトの検索 (読み取りオペレーション) にのみ使用されます。LDAP トランザクションでは、変更可能なものはなく、認証情報はクリアテキストで渡されません。認証は AWS 内部サービスによって処理されます。内部サービスでは Kerberos チケットを使用して LDAP オペレーションをユーザーとして実行します。

ユーザーアクセス許可

すべての Active Directory ユーザーは、各ユーザー独自の属性を読み取るアクセス許可を持っている必要があります。具体的には次の属性があります。

  • GivenName

  • SurName

  • Mail

  • SamAccountName

  • UserPrincipalName

  • UserAccountControl

  • MemberOf

デフォルトでは、Active Directory ユーザーには、これらの属性に対する読み取りアクセス許可があります。ただし、時間の経過に伴い管理者がこれらのアクセス許可を変更する可能性があるため、AD Connector を初めて設定する前に、ユーザーがこれらの読み取りアクセス許可を持っているかどうか確認することをお勧めします。

IP アドレス

既存のディレクトリの 2 つの DNS サーバーまたはドメインコントローラーの IP アドレスを取得します。

AD Connector は、ディレクトリに接続するときに _ldap._tcp.<DnsDomainName> および _kerberos._tcp.<DnsDomainName> SRV レコードをこれらのサーバーから取得します。そのため、これらのサーバーにはこれらの SRV レコードが含まれている必要があります。AD Connector は、LDAP と Kerberos サービスの両方を提供する共通ドメインコントローラーを見つけようとします。そのため、これらの SRV レコードには、少なくとも 1 つの共通ドメインコントローラーが含まれている必要があります。SRV レコードの詳細については、Microsoft TechNet の「SRV Resource Records」(SRV リソースレコード) を参照してください。

サブネット用のポート

AD Connector で既存の Active Directory のドメインコントローラーにディレクトリリクエストをリダイレクトするには、既存のネットワークのファイアウォールで、Amazon VPC の両方のサブネットの CIDR に対して次のポートを開く必要があります。

  • TCP/UDP 53 - DNS

  • TCP/UDP 88 - Kerberos 認証

  • TCP/UDP 389 - LDAP

これらは、AD Connector をディレクトリに接続する前に必要な最小限のポートです。固有の設定によっては、追加ポートが開かれていることが必要です。

注記

既存の Active Directory ドメインの DNS サーバーまたはドメインコントローラーサーバーが VPC 内にある場合、これらのサーバーに関連付けられたセキュリティグループでは、VPC の両方のサブネットで、CIDR に対して上記のポートが開かれている必要があります。

追加のポート要件については、Microsoft TechNet の「AD and AD DS Port Requirements」(AD および AD DS ポートの要件) を参照してください。

Kerberos 事前認証

ユーザーアカウントの Kerberos 事前認証を有効にしておく必要があります。この設定を有効にする方法の詳細については、「Kerberos の事前認証が有効化されていることを確認する」を参照してください。この設定に関する一般的な情報については、Microsoft TechNet の「Preauthentication」(事前認証) を参照してください。

暗号化タイプ

AD Connector は、Active Directory ドメインコントローラーへの Kerberos を介した認証時に、次のタイプの暗号化をサポートしています。

  • AES-256-HMAC

  • AES-128-HMAC

  • RC4-HMAC

AWS IAM Identity Center (successor to AWS Single Sign-On) の前提条件

IAM Identity Center を AD Connector で使用する場合は、次の条件が満たされていることを確認する必要があります。

  • AD Connector が AWS 組織の管理アカウントに設定されている。

  • IAM Identity Center のインスタンスが AD Connector の設定先と同じリージョンにある。

詳細については、AWS IAM Identity Center (successor to AWS Single Sign-On) ユーザーガイドの「IAM Identity Center の前提条件」を参照してください。

Multi-Factor·Authentication の前提条件

AD Connector ディレクトリで Multi-Factor·Authentication をサポートするには、以下が必要です。

  • 2 つのクライアントエンドポイントを持つ、既存のネットワーク内の Remote Authentication Dial-In User Service (RADIUS) サーバー。RADIUS クライアントエンドポイントには次の要件があります。

    • エンドポイントを作成するには、AWS Directory Service サーバーの IP アドレスが必要です。これらの IP アドレスは、ディレクトリの詳細の [Directory IP Address] (ディレクトリの IP アドレス) フィールドから取得できます。

    • 2 つの RADIUS エンドポイントが同じ共有シークレットコードを使用する必要があります。

  • 既存のネットワークでは、AWS Directory Service サーバーからのデフォルトの RADIUS サーバーポート (1812) を介したインバウンドトラフィックが許可されている必要があります。

  • RADIUS サーバーと既存のディレクトリの間でユーザー名が同じである必要があります。

AD Connector で MFA を使用する場合の詳細については、「AD Connector の多要素認証を有効にする」を参照してください。

権限をサービスアカウントに委任する

既存のディレクトリに接続するには、特定の権限が委任されている既存のディレクトリの AD Connector サービスアカウントの認証情報が必要です。[Domain Admins] (ドメインの管理者) グループのメンバーにはディレクトリに接続するために十分な権限がありますが、ベストプラクティスとして、そのディレクトリへの接続に必要な最小限の権限が付与されたサービスアカウントを使用することをお勧めします。以下の手順では、Connectors という名前の新しいグループを作成後、AWS Directory Service をこのグループに接続するために必要な権限を委任し、新しいサービスアカウントをこのグループに追加する方法を説明します。

この手順は、ディレクトリに結合され、[Active Directory User and Computers] (Active Directory ユーザーとコンピュータ) MMC スナップインがインストールされたマシンで実行する必要があります。また、ドメイン管理者としてログインする必要があります。

権限をサービスアカウントに委任するには

  1. [Active Directory User and Computers] (Active Directory ユーザーとコンピュータ) を開き、ナビゲーションツリーのドメインルートを選択します。

  2. 左のペインのリストで、[Users] (ユーザー) を右クリックし、[New] (新規) を選択して、[Group] (グループ) を選択します。

  3. [New Object - Group] (新しいオブジェクト - グループ) ダイアログボックスで次のように入力し、[OK] をクリックします。

    フィールド 値/選択
    グループ名 Connectors
    グループのスコープ グローバル
    グループのタイプ セキュリティ
  4. [Active Directory User and Computers] (Active Directory ユーザーとコンピュータ) ナビゲーションツリーで、ドメインルートを選択します。メニューで [Action] (アクション) を選択し、[Delegate Control] (制御を委任する) を選択します。AD Connector が AWS Managed Microsoft AD に接続されている場合、ドメインのルートレベルで制御を委任するアクセス権限がありません。この場合、制御を委任するには、コンピュータオブジェクトが作成されるディレクトリ OU で OU を選択します。

  5. [Delegation of Control Wizard] (制御の委任ウィザード) ページで [Next] (次へ) をクリックし、[Add] (追加) をクリックします。

  6. [Select Users, Computers, or Groups] (ユーザー、コンピュータ、またはグループの選択) ダイアログボックスで「Connectors」と入力し、[OK] をクリックします。複数のオブジェクトがある場合は、上記で作成した Connectors グループを選択します。[Next] (次へ) をクリックします。

  7. [Tasks to Delegate] (委任するためのタスク) ページで、[Create a custom task to delegate] (委任するためのカスタムタスクを作成) を選択し、[Next] (次へ) をクリックします。

  8. [Only the following objects in the folder] (フォルダ内の次のオブジェクトのみ) を選択してから、[Computer objects] (コンピュータオブジェクト) と [User objects] (ユーザーオブジェクト) を選択します。

  9. [Create selected objects in this folder] (選択したオブジェクトをこのフォルダに作成) を選択し、[Delete selected objects in this folder] (このフォルダ内の選択したオブジェクトを削除) を選択します。続いて、[Next] (次へ) をクリックします。

    
                            オブジェクトの種類
  10. [Read] (読み取り) を選択し、[Next] (次へ) をクリックします。

    注記

    シームレスなドメイン結合または WorkSpaces を使用する場合は、Active Directory がコンピュータオブジェクトを作成できるように、[Write] (書き込み) アクセス許可も有効にする必要があります。

    
                            オブジェクトの種類
  11. [Completing the Delegation of Control Wizard] (制御の委任の完了ウィザード) ページの情報を確認し、[Finish] (完了) をクリックします。

  12. 強力なパスワードでユーザーアカウントを作成し、そのユーザーを Connectors グループに追加します。このユーザーは、AD Connector サービスアカウントと呼ばれます。Connectors グループのメンバーになったため、AWS Directory Service をディレクトリに接続するために十分な権限が付与されています。

AD Connector をテストする

AD Connector で既存のディレクトリに接続するには、既存のネットワークのファイアウォールで VPC の両方のサブネットの CIDR に対して特定のポートが開かれている必要があります。これらの要件が満たされるかどうかをテストするには、次の手順に従います。

接続をテストするには

  1. VPC で Windows インスタンスを起動し、RDP 経由でインスタンスに接続します。インスタンスは、既存のドメインのメンバーである必要があります。残りの手順は、この VPC インスタンスで実行します。

  2. DirectoryServicePortTest テストアプリケーションをダウンロードして解凍します。ソースコードと Visual Studio プロジェクトファイルが含まれており、必要に応じてテストアプリケーションを変更できます。

    注記

    このスクリプトは Windows Server 2003 以前のオペレーティングシステムではサポートされていません。

  3. Windows のコマンドプロンプトで、次のオプションを指定して DirectoryServicePortTest テストアプリケーションを実行します。

    注記

    DirectoryServicePortTest テストアプリケーションは、ドメインおよびフォレストの機能レベルが Windows Server 2012 R2 以下に設定されている場合にのみ使用できます。

    DirectoryServicePortTest.exe -d <domain_name> -ip <server_IP_address> -tcp "53,88,389" -udp "53,88,389"
    <domain_name>

    完全修飾ドメイン名。これは、フォレストとドメインの機能レベルをテストするために使用されます。ドメイン名を除外した場合、機能レベルはテストされません。

    <server_IP_address>

    既存のドメインのドメインコントローラーの IP アドレス。ポートはこの IP アドレスに対してテストされます。IP アドレスを除外した場合、ポートはテストされません。

    このテストアプリケーションは、VPC からドメインに必要なポートが開いているかどうかを判断し、最小のフォレストとドメインの機能レベルも検証します。

    出力は次のようになります。

    Testing forest functional level. Forest Functional Level = Windows2008R2Forest : PASSED Testing domain functional level. Domain Functional Level = Windows2008R2Domain : PASSED Testing required TCP ports to <server_IP_address>: Checking TCP port 53: PASSED Checking TCP port 88: PASSED Checking TCP port 389: PASSED Testing required UDP ports to <server_IP_address>: Checking UDP port 53: PASSED Checking UDP port 88: PASSED Checking UDP port 389: PASSED

DirectoryServicePortTest アプリケーションのソースコードは次のとおりです。

/* Copyright 2010-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. This file is licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance with the License. A copy of the License is located at http://aws.amazon.com/apache2.0/ This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Net; using System.Net.Sockets; using System.Text; using System.Threading.Tasks; using System.DirectoryServices.ActiveDirectory; using System.Threading; using System.DirectoryServices.AccountManagement; using System.DirectoryServices; using System.Security.Authentication; using System.Security.AccessControl; using System.Security.Principal; namespace DirectoryServicePortTest { class Program { private static List<int> _tcpPorts; private static List<int> _udpPorts; private static string _domain = ""; private static IPAddress _ipAddr = null; static void Main(string[] args) { if (ParseArgs(args)) { try { if (_domain.Length > 0) { try { TestForestFunctionalLevel(); TestDomainFunctionalLevel(); } catch (ActiveDirectoryObjectNotFoundException) { Console.WriteLine("The domain {0} could not be found.\n", _domain); } } if (null != _ipAddr) { if (_tcpPorts.Count > 0) { TestTcpPorts(_tcpPorts); } if (_udpPorts.Count > 0) { TestUdpPorts(_udpPorts); } } } catch (AuthenticationException ex) { Console.WriteLine(ex.Message); } } else { PrintUsage(); } Console.Write("Press <enter> to continue."); Console.ReadLine(); } static void PrintUsage() { string currentApp = Path.GetFileName(System.Reflection.Assembly.GetExecutingAssembly().Location); Console.WriteLine("Usage: {0} \n-d <domain> \n-ip \"<server IP address>\" \n[-tcp \"<tcp_port1>,<tcp_port2>,etc\"] \n[-udp \"<udp_port1>,<udp_port2>,etc\"]", currentApp); } static bool ParseArgs(string[] args) { bool fReturn = false; string ipAddress = ""; try { _tcpPorts = new List<int>(); _udpPorts = new List<int>(); for (int i = 0; i < args.Length; i++) { string arg = args[i]; if ("-tcp" == arg | "/tcp" == arg) { i++; string portList = args[i]; _tcpPorts = ParsePortList(portList); } if ("-udp" == arg | "/udp" == arg) { i++; string portList = args[i]; _udpPorts = ParsePortList(portList); } if ("-d" == arg | "/d" == arg) { i++; _domain = args[i]; } if ("-ip" == arg | "/ip" == arg) { i++; ipAddress = args[i]; } } } catch (ArgumentOutOfRangeException) { return false; } if (_domain.Length > 0 || ipAddress.Length > 0) { fReturn = true; } if (ipAddress.Length > 0) { _ipAddr = IPAddress.Parse(ipAddress); } return fReturn; } static List<int> ParsePortList(string portList) { List<int> ports = new List<int>(); char[] separators = {',', ';', ':'}; string[] portStrings = portList.Split(separators); foreach (string portString in portStrings) { try { ports.Add(Convert.ToInt32(portString)); } catch (FormatException) { } } return ports; } static void TestForestFunctionalLevel() { Console.WriteLine("Testing forest functional level."); DirectoryContext dirContext = new DirectoryContext(DirectoryContextType.Forest, _domain, null, null); Forest forestContext = Forest.GetForest(dirContext); Console.Write("Forest Functional Level = {0} : ", forestContext.ForestMode); if (forestContext.ForestMode >= ForestMode.Windows2003Forest) { Console.WriteLine("PASSED"); } else { Console.WriteLine("FAILED"); } Console.WriteLine(); } static void TestDomainFunctionalLevel() { Console.WriteLine("Testing domain functional level."); DirectoryContext dirContext = new DirectoryContext(DirectoryContextType.Domain, _domain, null, null); Domain domainObject = Domain.GetDomain(dirContext); Console.Write("Domain Functional Level = {0} : ", domainObject.DomainMode); if (domainObject.DomainMode >= DomainMode.Windows2003Domain) { Console.WriteLine("PASSED"); } else { Console.WriteLine("FAILED"); } Console.WriteLine(); } static List<int> TestTcpPorts(List<int> portList) { Console.WriteLine("Testing TCP ports to {0}:", _ipAddr.ToString()); List<int> failedPorts = new List<int>(); foreach (int port in portList) { Console.Write("Checking TCP port {0}: ", port); TcpClient tcpClient = new TcpClient(); try { tcpClient.Connect(_ipAddr, port); tcpClient.Close(); Console.WriteLine("PASSED"); } catch (SocketException) { failedPorts.Add(port); Console.WriteLine("FAILED"); } } Console.WriteLine(); return failedPorts; } static List<int> TestUdpPorts(List<int> portList) { Console.WriteLine("Testing UDP ports to {0}:", _ipAddr.ToString()); List<int> failedPorts = new List<int>(); foreach (int port in portList) { Console.Write("Checking UDP port {0}: ", port); UdpClient udpClient = new UdpClient(); try { udpClient.Connect(_ipAddr, port); udpClient.Close(); Console.WriteLine("PASSED"); } catch (SocketException) { failedPorts.Add(port); Console.WriteLine("FAILED"); } } Console.WriteLine(); return failedPorts; } } }