LDAP 连接指南

本指南介绍了从 Ansible 主机与 LDAP 服务器(例如 Microsoft Active Directory)通信的相关信息。与 Windows 主机不同,Ansible 主机没有内置的机制来与 LDAP 服务器通信和进行身份验证,因此在 Ansible 主机上运行的插件需要一些额外的配置才能正常工作。

注意

本指南介绍了从 Ansible 主机进行 LDAP 通信。这并不适用于在远程 Windows 主机上运行的模块。有关如何配置模块身份验证的信息,请参阅 模块中的 AD 身份验证

需求

LDAP 连接代码需要 sansldappyspnego 库。可以使用 pip 安装它们:

$ python3 -m pip install --user \
    'pyspnego >= 0.8.0'
    sansldap

注意

本指南假设 python3 与 Ansible 使用的 Python 版本相同,有关 Python 版本/位置的详细信息,请参阅 ansible --version

还有一些可选依赖项可以提供额外的功能

功能

软件包

Kerberos 身份验证

pyspnego[kerberos] >= 0.8.0

服务器查找

dnspython

LAPS 解密

dpapi-ng

要安装所有可选功能,请运行:

$ python3 -m pip install --user \
    dnspython \
    dpapi-ng \
    'pyspnego[kerberos] >= 0.8.0'

Kerberos 身份验证组件需要 Kerberos 系统库。对于基于 RPM 的系统,这些库是:

$ dnf install gcc python3-devel krb5-libs krb5-devel

其他 Linux 发行版需要上述相同的软件包,但它们可能列出的名称与 dnf 使用的名称不同。

microsoft.ad.debug_ldap_client 操作插件可用于调试 Ansible 主机设置及其 LDAP 功能。它包含以下详细信息:

  • 已安装的与 LDAP 相关的 Python 包,或者如果未安装则显示导入失败消息

  • 如果安装了 Kerberos 扩展,则显示 Kerberos 主机和凭据缓存信息

  • 如果安装了 dnspython 和 Kerberos 扩展,则显示 SRV 查找信息

要使用此模块,只需运行:

$ ansible localhost -m microsoft.ad.debug_ldap_client

连接选项

连接到 Microsoft Active Directory 或 LDAP 服务器需要诸如域控制器主机名、端口、是否使用 LDAPS 或 StartTLS 以及身份验证信息等信息。部分信息可以根据 Ansible 主机环境检索,也可以通过插件选项手动指定。这些选项包括:

选项

默认值

用途

server

通过 Kerberos 进行服务器查找

LDAP 服务器主机名

port

389 或如果 tls_mode=ldaps 则为 686

LDAP 端口

tls_mode

如果 port=686 则为 LDAPS,否则为 None

TLS 细节 - LDAP、LDAP + StartTLS、LDAPS

auth_protocol

Negotiate

身份验证协议

username

None

尝试使用可用的 Kerberos 缓存

password

None

尝试使用可用的 Kerberos 缓存

服务器查找详细信息如下所述。除非指定了 tls_mode: ldaps,否则端口默认为 389。如果端口显式设置为 686,则 TLS 模式默认为 ldaps,否则默认为 389。身份验证协议默认为 negotiate,同时尝试使用隐式凭据(如果可用)。

服务器查找

如果没有显式设置服务器选项,插件将尝试根据当前环境配置查找 LDAP 服务器。这只有在以下情况下才有可能:

  • 已安装 dnspython Python 包

  • 已安装用于 Kerberos 的 pyspnego[kerberos] Python 包

  • 底层 Kerberos 库在 MIT krb5.conf 中设置了 default_realm

如果上述条件均不满足,则连接将失败,并且必须提供显式服务器。如果满足所有要求,则服务器查找工作流程如下:

  • 检索本地 Kerberos 配置的 default_realm

  • 对记录 _ldap._tcp.dc._msdcs.{{ default_realm }} 执行 DNS SRV 查找

  • 按优先级和权重对 DNS 记录进行排序,并选择第一个记录

  • 使用选定 SRV 记录上的主机名和端口进行查找

注意

如果指定了显式端口,则它将优先于 SRV 记录返回的端口。

身份验证

LDAP 连接的一个关键组件是如何用户向服务器进行身份验证。支持以下身份验证机制:

身份验证

支持加密

隐式凭据

simple

否 - 需要 TLS

是 - 显示为匿名

certificate

negotiate

是 - 使用 Kerberos

kerberos

ntlm

除非另有指定,否则使用的默认身份验证协议为 negotiate,它依赖于 pyspnego 库。有关如何安装此要求的更多信息,请参阅 需求

任何不支持加密的协议都必须与 LDAPS、StartTLS 一起使用,或者必须使用 encrypt: false 选项显式禁用加密检查。不建议禁用加密,因为它会发送没有任何保护的凭据,并且任何交换的数据都可能被任何人看到。它还需要目标服务器允许未加密的连接,因为它们可能会拒绝此类连接。

隐式凭据支持文档说明身份验证协议是否可以在没有显式指定 usernamepassword 的情况下进行身份验证。目前只有 simplenegotiate/kerberos 支持隐式凭据。有关详细信息,请参阅每个协议部分。

Simple

简单身份验证是最基本的受支持身份验证协议。它的工作原理是将用户名和密码以明文形式发送到服务器,类似于 HTTP 基本身份验证。Microsoft AD 要求用户名为sAMAccountNameuserPrincipalName帐户,但其他 LDAP 实现需要 LDAP distinguishedName。虽然在未指定用户名或密码时可以进行匿名绑定,但服务器可能会拒绝任何搜索操作,除非它已使用实际用户的凭据进行身份验证。简单身份验证不允许在未受 TLS 保护的连接上使用。可以通过禁用加密检查来允许在这样的连接上进行简单身份验证,但不建议这样做。

警告

除非使用 TLS(通过 LDAPS 或 StartTLS),否则应避免使用简单身份验证。不使用 LDAPS 将导致身份验证期间使用的凭据和后续数据暴露于窃听或篡改的风险。

证书

证书身份验证使用 TLS 客户端身份验证作为 TLS 握手的一部分,以将用户身份验证到主机。作为 TLS 握手的一部分,它只能在 LDAPS 连接或使用 StartTLS 时使用。它使用用户的证书和证书密钥进行身份验证。可以使用三个选项来指定用于身份验证的客户端证书和密钥

  • certificate - 证书,以及可选的捆绑密钥

  • certificate_key - 如果未捆绑在 certificate 中的证书密钥

  • certificate_password - 用于解密证书密钥的密码

certificatecertificate_key 可以是证书和密钥的文件路径,也可以是 PEM 编码证书/密钥的字符串。certificate 文件路径可以是 PEM、DER 或 PKCS12/PFX 编码的证书,并带有可选的密钥捆绑,而 certificate_key 文件路径可以是 PEM 或 DER 编码的密钥。如果 PEM、DER 或 PKCS12/PFX 内容中的密钥已加密,则可以使用 certificate_password 指定用于解密密钥的密码。

注意

设置这些选项取决于插件本身,这里的密钥反映的是选项名称,而不一定是插件可以自动设置和读取的 Ansible 变量。

协商

协商身份验证是 LDAP 连接使用的默认身份验证协议。它是 kerberosntlm 的组合,客户端协商使用哪个。如果可用,它将优先使用 kerberos,如果不可用,则回退到 ntlmpyspnego Python 包仅提供具有 ntlm 支持的 negotiatekerberos 支持由 pyspnego[kerberos] 附加选项提供。有关如何安装此要求的更多信息,请参阅 requirements

Kerberos

Kerberos 身份验证是 Microsoft AD 服务器支持的现代身份验证协议,也是首选的身份验证协议。只有在安装了 pyspnego[kerberos] 附加包并且主机已正确配置后,它才可用。通常,此配置是通过系统上的 /etc/krb5.conf 文件完成的。本指南不会介绍配置主机的 Kerberos 设置,因为它与环境有关。

确保主机已正确配置为使用 Kerberos 的好方法是确保以下命令有效

$ python -c "import krb5"
$ kinit [email protected]
$ kvno ldap/dc.domain.realm

注意

kvno 命令是 MIT krb5 特定的命令,在使用 Heimdal krb5(如 macOS)的主机上不可用。

python 命令确保已安装所需的 Python 库。kinit 命令将为指定的用户检索 Kerberos 票证,kvno 命令将尝试为请求的服务主体名称 (SPN) 检索服务票证。如果两个命令都有效,则 Kerberos 身份验证很可能与 LDAP 连接一起使用。

使用 kinit 命令,可以为 Ansible 设置凭据缓存以用于身份验证。通过使用 kinit 检索凭据,可以无需在 Ansible 中设置任何显式用户名和密码即可使用 LDAP 服务器进行身份验证。仍然可以使用显式凭据与 Kerberos 一起使用。

NTLM

NTLM 身份验证是一个简单的身份验证协议,可以单独使用,也可以作为 negotiate 回退的一部分(如果 kerberos 不可使用)。与 kerberos 支持不同,它通常不支持隐式凭据,因此通常需要指定显式用户名和密码才能使用。它不需要额外的主机配置,并且在安装 pyspnego 后应该可以工作。

警告

虽然 NTLM 支持加密,但根据现代标准,它被认为是不安全的。建议仅在 LDAPS 或 StartTLS 连接中使用 NTLM,其中 TLS 提供的更强大的加密和服务器检查可以减轻 NTLM 的弱点。

证书验证

使用 LDAPS 或通过 StartTLS 使用 LDAP 将执行 TLS 握手,默认情况下,客户端尝试验证服务器提供的证书。如果无法信任证书链,或者主机名与请求的主机名不匹配,则连接将失败,并显示指示原因的错误。默认信任存储位置取决于 Python 配置以及它已链接到的 SSL 库。通常情况下,它应该是操作系统的默认信任存储,但如有疑问,可以使用以下 Python 代码来验证 LDAPS 证书。请务必将 hostname 更改为应测试的 LDAP 服务器的主机名。

import socket
import ssl

hostname = 'dc.domain.com'
port = 636
context = ssl.create_default_context()

with socket.create_connection((hostname, port)) as sock:
    with context.wrap_socket(sock, server_hostname=hostname) as ssock:
        print(ssock.version())

ca_cert 连接选项可用于设置显式 CA 捆绑包以用于验证。如果 CA 捆绑包不是操作系统存储的一部分,而是位于文件系统的其他位置,这将非常有用。该值可以采用以下形式:

  • PEM 或 DER 编码证书捆绑包的文件路径

  • 包含多个 PEM 格式 CA 证书的目录路径,遵循 CApath 文档中所述的 OpenSSL 特定布局

  • 包含 PEM 编码证书的字符串

也可以使用 cert_validation 连接选项禁用证书验证。默认值为 always,但可以设置为 ignore 以禁用所有检查,或设置为 ignore_hostname 以仅禁用主机名检查。这对于使用自签名证书的测试环境很有用,但不应在生产环境中使用。

警告

禁用证书验证会消除 TLS 提供的许多好处。无法验证目标服务器是否是它声称的那一个。