开始使用 AD Connector
凭借 AD Connector,您可以将 Amazon Directory Service 连接到您的现有企业 Active Directory。当连接到您的现有目录时,您的所有目录数据仍保留在域控制器上。Amazon Directory Service 不复制您的任何目录数据。
AD Connector 先决条件
要使用 AD Connector 连接到您的现有目录,您需要:
- Amazon VPC
-
对 VPC 进行如下设置:
-
至少两个子网。每个子网必须位于不同的可用区。
-
必须通过虚拟专用网络 (VPN) 连接或 Amazon Direct Connect 将 VPC 连接到您的现有网络。
-
VPC 必须具有默认硬件租户。
Amazon Directory Service 使用双 VPC 结构。构成您目录的 EC2 实例在您的 Amazon 账户之外运行,由 Amazon 管理。其有
ETH0
和ETH1
两个网络适配器。ETH0
是管理适配器,存在于您的账户之外。ETH1
在您的账户内创建。目录的
ETH0
网络的管理 IP 范围以编程方式选择,以确保其不会与部署目录的 VPC 发生冲突。此 IP 范围可以是以下任一对(因为目录在两个子网中运行):-
10.0.1.0/24 和 10.0.2.0/24
-
169.254.0.0/16
-
192.168.1.0/24 和 192.168.2.0/24
我们通过检查
ETH1
CIDR 的第一个八位字节来避免冲突。如果以 10 开头,那么我们就选择一个 192.168.0.0/16 VPC,其子网为 192.168.1.0/24 和 192.168.2.0/24。如果第一个八位字节不是 10,则我们选择一个 10.0.0.0/16 VPC,其子网为 10.0.1.0/24 和 10.0.2.0/24。选择算法不包括您 VPC 上的路由。因此,这种情况可能会导致 IP 路由冲突。
有关更多信息,请参阅 Amazon VPC 用户指南 中的以下主题:
有关 Amazon Direct Connect 的更多信息,请参阅 Amazon Direct Connect 用户指南。
-
- 现有 Active Directory
-
您将需要连接到具有 Active Directory 域的现有网络。
注意
AD Connector 不支持单个标签域
。 此 Active Directory 域的功能级别必须为
Windows Server 2003
或更高版本。AD Connector 还支持连接到 Amazon EC2 实例上托管的域。注意
与 Amazon EC2 域加入功能结合使用时,AD Connector 不支持只读域控制器(RODC)。
- 服务账户
-
您必须拥有现有目录中被委派了以下权限的服务账户的凭证:
-
读取用户和组 – 必需
-
将计算机加入域 – 仅当使用无缝域加入和 WorkSpaces 时必需
-
创建计算机对象 – 仅当使用无缝域加入和 WorkSpaces 时必需
-
服务账号密码应符合 Amazon 密码要求。Amazon 密码应为:
-
长度介于 8 到 128 个字符之间(包含边界值)。
-
至少包含下列四种类别中三种类别的一个字符:
-
小写字母 (a-z)
-
大写字母 (A-Z)
-
数字 (0-9)
-
非字母数字字符 (~!@#$%^&*_-+=`|\(){}[]:;"'<>,.?/)
-
-
有关更多信息,请参阅 向您的服务账户委派权限。
注意
AD Connector 使用 Kerberos 对 Amazon 应用程序进行身份验证和授权。LDAP 仅用于用户和组对象查找(读取操作)。对于 LDAP 事务,所有都不可变,凭证也不以明文形式传递。身份验证由 Amazon 内部服务处理,该服务使用 Kerberos 票证以用户身份执行 LDAP 操作。
-
- 用户权限
-
所有 Active Directory 用户必须有权读取自己的属性。具体而言,包括以下属性:
-
GivenName
-
SurName
-
邮件
-
SamAccountName
-
UserPrincipalName
-
UserAccountControl
-
MemberOf
默认情况下,Active Directory 用户确实有权读取这些属性。但是,管理员可以随时修改这些权限,因此,您可能希望在首次设置 AD Connector 之前,验证用户是否具有这些读取权限。
-
- IP 地址
-
获取您现有目录域中两个 DNS 服务器或域控制器的 IP 地址。
AD Connector 在连接到您的目录时将从这些服务器获取
_ldap._tcp.
和<DnsDomainName>
_kerberos._tcp.
SRV 记录,因此这些服务器必须包含这些 SRV 记录。AD Connector 尝试查找将同时提供 LDAP 和 Kerberos 服务的公用域控制器,因此这些 SRV 记录必须至少包含一个公用域控制器。有关 SRV 记录的更多信息,请转到 Microsoft TechNet 上的 SRV Resource Records<DnsDomainName>
。 - 子网的端口
-
为了使 AD Connector 将目录请求重定向到您的现有 Active Directory 域控制器,现有网络的防火墙必须对 Amazon VPC 中两个子网的 CIDR 开放以下端口。
-
TCP/UDP 53 - DNS
-
TCP/UDP 88 - Kerberos 身份验证
-
TCP/UDP 389 - LDAP
这些是 AD Connector 能够连接到目录之前所需的最少端口。根据您的特定配置,您可能需要打开其他端口。
如果要使用 AD Connector 和 Amazon WorkSpaces,则需要将域控制器的 DisableVLVSupportLDAP 属性设置为 0。这是域控制器的默认设置。如果启用了 DisableVLVSupportLDAP 属性,AD Connector 将无法查询目录中的用户。这样会导致 AD Connector 无法与 Amazon WorkSpaces 配合使用。
注意
如果现有 Active Directory 域的 DNS 服务器或域控制器服务器在 VPC 内,与这些服务器关联的安全组必须向 VPC 中的两个子网的 CIDR 开放上述端口。
有关其他端口要求,请参阅 Microsoft 文档中的 AD 和 AD DS 端口要求
。 -
- Kerberos 预身份验证
-
用户账户必须启用 Kerberos 预身份验证。有关如何启用此设置的详细说明,请参阅确保已启用 Kerberos 预身份验证。有关此设置的一般信息,请访问 Microsoft TechNet 上的预身份验证
。 - 加密类型
-
当通过 Kerberos 对您的 Active Directory 域控制器进行身份验证时,AD Connector 支持以下加密类型:
-
AES-256-HMAC
-
AES-128-HMAC
-
RC4-HMAC
-
Amazon IAM Identity Center先决条件
如果计划将 IAM Identity Center 与 AD Connector 结合使用,则需要确保满足以下条件:
-
您的 AD Connector 已在 Amazon 组织的管理主账户中设置。
-
您的 IAM Identity Center 实例位于您在其中设置 AD Connector 的同一区域中。
有关更多信息,请参阅《Amazon IAM Identity Center User Guide》中的 IAM Identity Center prerequisites。
多重身份验证先决条件
为了使用您的 AD Connector 目录支持多重身份验证,您需要以下内容:
-
现有网络中具有两个客户端终端节点的远程身份验证拨入用户服务
(RADIUS) 服务器。RADIUS 客户端终端节点具有以下要求: -
要创建终端节点,您需要 Amazon Directory Service 服务器的 IP 地址。这些 IP 地址可以从目录详细信息的 Directory IP Address 字段中获取。
-
两个 RADIUS 终端节点必须使用相同的共享密码。
-
-
您的现有网络必须允许通过默认的 RADIUS 服务器端口 (1812) 从 Amazon Directory Service 服务器传入入站流量。
-
您的 RADIUS 服务器与您的现有目录的用户名必须相同。
有关通过 MFA 使用 AD Connector 的更多信息,请参阅 为 AD Connector 启用多重身份验证。
向您的服务账户委派权限
要连接到您的现有目录,必须在现有目录中拥有被委托了某些权限的 AD Connector 服务账户的凭证。尽管 Domain Admins 组的成员有足够的权限连接到目录,但是作为最佳实践,您应使用仅具有连接到目录所需的最小权限的服务账户。以下过程演示如何创建名为 Connectors
的新组,委派将 Amazon Directory Service 连接到该组所需的必要权限,然后将新服务账户添加到该组。
必须在已加入到目录且已安装 Active Directory User and Computers MMC 管理单元的计算机上执行此过程。您还必须以域管理员身份登录。
向您的服务账户委派权限
-
打开 Active Directory User and Computers 并在导航树中选择您的域根。
-
在左侧窗格的列表中,右键单击 Users,选择 New,然后选择 Group。
-
在 New Object - Group 对话框中,输入以下内容,然后单击 OK。
字段 值/选择 组名 Connectors
Group scope Global Group type 安全性 -
在 Active Directory 用户和计算机导航树中,选择确定将在其中创建计算机账户的组织单位(OU)。在菜单中,选择 Action,然后选择 Delegate Control。您可以一直选择到域的父 OU,因为权限会传播到子 OU。如果您的 AD Connector 已连接到 Amazon Managed Microsoft AD,则将无法访问域根级别的委托控制。在这种情况下,要委托控制权,请在您的目录 OU 下选择将在其中创建计算机对象的 OU。
-
在 Delegation of Control Wizard 页面上,单击 Next,然后单击 Add。
-
在 Select Users, Computers, or Groups 对话框中,输入
Connectors
,然后单击 OK。如果找到多个对象,请选择上面创建的Connectors
组。单击下一步。 -
在 Tasks to Delegate 页面上,选择 Create a custom task to delegate,然后选择 Next。
-
选择 Only the following objects in the folder,然后选择 Computer objects 和 User objects。
-
选择 Create selected objects in this folder,然后选择 Delete selected objects in this folder。然后选择下一步。
-
选择 Read,然后选择 Next。
注意
如果您将使用无缝域加入或 WorkSpaces,则还必须启用写入权限,以便 Active Directory 可以创建计算机对象。
-
在 Completing the Delegation of Control Wizard 页面上验证信息,然后单击 Finish。
-
使用强密码创建一个用户账户,并将该用户添加到
Connectors
组。此用户将被称为您的 AD Connector 服务账户,由于其现在是Connectors
组的成员,因此具有足够的权限将 Amazon Directory Service 连接到目录。
测试 AD Connector
为使 AD Connector 能够连接您的现有目录,现有网络的防火墙必须向 VPC 中的两个子网的 CIDR 开放特定的端口。要测试是否满足这些条件,请执行以下步骤:
测试 连接
-
在 VPC 中启动一个 Windows 实例并通过 RDP 连接它。实例必须是您现有域的成员。在该 VPC 实例上执行剩余步骤。
-
下载并解压缩 DirectoryServicePortTest 测试应用程序。其中包含源代码及 Visual Studio 项目文件,您可以根据需要修改该测试应用程序。
注意
Windows Server 2003 及更低版本的操作系统不支持此脚本。
-
在 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 应用程序的源代码。
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; } } }
创建 AD Connector
要使用 AD Connector 连接到现有目录,请执行以下步骤。在开始此过程之前,请确保您已满足了AD Connector 先决条件中确定的先决条件。
注意
您无法使用 Cloud Formation 模板创建 AD Connector。
使用 AD Connector 连接
-
在 Amazon Directory Service 控制台
导航窗格中,选择目录,然后选择设置目录。 -
在选择目录类型页面上,选择 AD Connector,然后选择下一步。
-
在 Enter AD Connector information (输入 AD Connector 信息) 页面上,提供以下信息:
- 目录大小
-
从小型或大型大小选项中进行选择。有关大小的更多信息,请参阅AD Connector。
- 目录描述
-
目录的可选描述。
-
在 Choose VPC and subnets (选择 VPC 和子网) 页面上,提供以下信息,然后选择 Next (下一步)。
- VPC
-
目录的 VPC。
- 子网
-
为域控制器选择子网。两个子网必须位于不同的可用区。
-
在 Connect to AD (连接到 AD) 页面上,提供以下信息:
- 目录 DNS 名称
-
现有目录的完全限定名称,例如
corp.example.com
。 - 目录 NetBIOS 名称
-
现有目录的短名称,例如
CORP
。 - DNS IP 地址
-
现有目录中至少一个 DNS 服务器的 IP 地址。这些服务器必须可从步骤 4 中指定的每个子网访问。只要指定的子网和 DNS 服务器 IP 地址之间存在网络连接,这些服务器就可以位于 Amazon 外部。
- 服务账户用户名
-
现有目录中用户的用户名称。有关该账户的更多信息,请参阅AD Connector 先决条件。
- 服务账户密码
-
现有用户账户的密码。此密码区分大小写,且长度必须介于 8 到 128 个字符之间。至少,它还必须包含下列四种类别中三种类别的一个字符:
-
小写字母 (a-z)
-
大写字母 (A-Z)
-
数字 (0-9)
-
非字母数字字符 (~!@#$%^&*_-+=`|\(){}[]:;"'<>,.?/)
-
- 确认密码
-
重新键入现有用户账户的密码。
-
在 Review & create (检查并创建) 页面上,检查目录信息并进行任何必要的更改。如果信息正确,请选择 Create directory (创建目录)。目录创建需要几分钟时间。创建后,Status 值将更改为 Active。
有关随 AD Connector 创建的内容的更多信息,请参阅与 AD Connector 一起创建的内容。