LDAP清单指南

本指南介绍了此集合中包含的LDAP清单插件的相关信息。此清单插件可用于从LDAP服务器源(例如Microsoft Active Directory)构建清单。

连接信息

有关如何配置LDAP连接的详细信息,请参阅LDAP连接指南。插件文档中描述的每个连接选项都在以下所示的清单yml配置文件中指定。

plugin: microsoft.ad.ldap

# LDAP connection options can be defined in the yaml config.
auth_protocol: simple
username: UserName
password: MyPassword123
tls_mode: ldaps

属性

LDAP清单插件可用于根据计算机对象的LDAP属性为其检索到的每个主机设置自定义事实。通过清单插件定义中的attributes选项检索自定义属性。该值设置为以下三种类型之一

  • 空字符串或null

  • 模板字符串

  • 字典

注意

虽然单个属性只能设置为这些类型之一,但可以对不同的属性使用不同的值类型。

也可以使用compose清单选项来使用清单插件提供的内置compose模板,但必须首先通过attributes选项请求LDAP属性,并在compose模板中通过attributes在其上设置的主机事实进行引用。

空字符串或null

attributes:
  comment:
  objectSid: ''
  ms-Mcs-AdmPwd:

在这种情况下,每个属性值都将设置为主机事实,因为它们是由LDAP模式强制转换的,请参见值类型和模板。每个事实的名称将基于属性名称,其中-将替换为_。在上面的示例中,主机事实commentobjectSidms_Mcs_AdmPwd将设置为强制转换的值。

# ansible-inventory -i microsoft.ad.ldap.yml --host MYHOST --vars --yaml

ansible_host: MYHOST.domain.com
comment: test comment
ms_Mcs_AdmPwd: Password123!
objectSid: S-1-5-21-1234-1108
microsoft_ad_distinguished_name: CN=MYHOST,CN=Computers,DC=domain,DC=com

模板字符串

attributes:
  comment: this
  objectSid: raw | microsoft.ad.as_sid
  ms-Mcs-AdmPwd: raw | first

此格式将根据指定的模板值设置主机事实。每个模板都隐式地用{{ ... }}包装,并通过Jinja2处理以生成结果。这意味着模板字符串可以包含Ansible和其他集合提供的过滤器,以将原始LDAP值转换为更有用的内容。this变量指的是强制转换的LDAP属性值,raw指的是原始LDAP属性值的base64编码字节字符串列表。有关可以在模板内执行的操作的更多信息,请参见值类型和模板。每个主机事实都将以属性名称命名,其中-将替换为_。在上面的示例中,主机事实commandobjectSidms_Mcs_AdmPwd将设置为模板结果。

# ansible-inventory -i microsoft.ad.ldap.yml --host MYHOST --vars --yaml

ansible_host: MYHOST.domain.com
comment: test comment
ms_Mcs_AdmPwd: UGFzc3dvcmQxMjMh
objectSid:
- S-1-5-21-1234-1108
microsoft_ad_distinguished_name: CN=MYHOST,CN=Computers,DC=domain,DC=com

字典

attributes:
  comment:
    # Jinja2 native types will automatically convert this to a dict as
    # the value is a json string.
    my_comment:
    other_var: this | from_json
  objectSid:
    sid: raw | microsoft.ad.as_sid | first
  ms-Mcs-AdmPwd:
    ansible_password: this

可以为每个属性值设置的最终值是一个字典,其中键是要设置的主机事实,值是用于派生最终值的模板。它可以是null或空字符串,以引用该属性的LDAP强制转换值(this),或者是一个模板字符串,以根据手头的要求对新值进行模板化。有关null/空字符串与字符串模板值的更多信息,请参见上述两种格式。在上面的示例中,设置了4个主机事实

  • my_command - comment属性的强制转换值

  • other_var - 如果comment是json字符串,则从中创建的字典

  • sid - 从objectSid派生的计算机SID值(字符串)

  • ansible_password - 从ms-Mcs-AdmPwd派生的LAPS密码强制转换值

# ansible-inventory -i microsoft.ad.ldap.yml --host MYHOST --vars --yaml

ansible_host: MYHOST.domain.com
ansible_password: Password123!
my_comment:
  foo: bar
other_var:
  foo: bar
sid: S-1-5-21-1234-1108
microsoft_ad_distinguished_name: CN=MYHOST,CN=Computers,DC=domain,DC=com

注意

主机事实名称按字面使用,使用此格式时,不会将-转换为_

清单主机名

默认情况下,找到的主机的inventory_hostname 将基于name LDAP 属性值。如果找到的计算机帐户设置了dNSHostName 属性,它将被设置为ansible_host 事实。要定义自定义的inventory_hostnameansible_host,请在该键下的attributescompose 插件选项中设置它。例如,这将inventory_hostname 设置为sAMAccountName 的值,不包含结尾的$,而不是计算机帐户 LDAP name 属性。

attributes:
  sAMAccountName:
  inventory_hostname: sAMAccountName[:-1]
# ansible-inventory -i microsoft.ad.ldap.yml --host MYHOST --vars --yaml

ansible_host: MYHOST.domain.com
microsoft_ad_distinguished_name: CN=OtherName,CN=Computers,DC=domain,DC=com
sAMAccountName: MYHOST$

也可以在compose 键下设置inventory_hostname。以下将产生与上述相同的输出。

attributes:
  sAMAccountName:

compose:
  inventory_hostname: sAMAccountName[:-1]

设置自定义ansible_host 事实(用作连接主机)但保留计算机帐户名称的默认inventory_hostname 的示例如下:

attributes:
  sAMAccountName:
  ansible_host: sAMAccountName[:-1]

值类型和模板

每个 LDAP 属性值都存储为字节列表,但 LDAP 数据库中提供的模式可以描述这些原始字节列表如何表示为正确的类型,例如字符串、整数、布尔值等。目前,强制转换 LDAP 属性值时仅使用这四种类型。

  • 布尔值

  • 整数

  • 字节

  • 字符串

布尔值、整数和字符串被强制转换为这些特定的 Python 类型,但字节被强制转换为这些字节的 base64 字符串编码。

注意

objectGuidobjectSid 属性始终被强制转换为分别表示安全标识符和 GUID 的字符串。这些是唯一具有超出 LDAP 模式语法的特殊强制转换规则的属性。

LDAP 属性值也可以标记为单值或多值属性。单值仅包含强制转换的值,或者如果未设置则为None/null,而多值属性将设置为强制转换值的列表。例如,comment 是单值字符串,而servicePrincipalName 是多值字符串。使用此请求commentservicePrincipalName 的清单配置,我们将获得以下清单主机定义。

plugin: microsoft.ad.ldap

attributes:
  comment:
  servicePrincipalName:
# ansible-inventory -i microsoft.ad.ldap.yml --host MYHOST --vars --yaml

ansible_host: MYHOST.domain.com
comment: test comment
servicePrincipalName:
- WSMAN/MYHOST
- WSMAN/MYHOST.domain.com
- TERMSRV/MYHOST
- TERMSRV/MYHOST.domain.com
- RestrictedKrbHost/MYHOST
- HOST/MYHOST
- RestrictedKrbHost/MYHOST.domain.com
- HOST/MYHOST.domain.com
microsoft_ad_distinguished_name: CN=MYHOST,CN=Computers,DC=domain,DC=com

某些属性(如pwdLastSet)通常表示为日期时间值,但在内部存储为整数。由于 LDAP 模式中没有元数据将这些整数值表示为日期时间对象,因此默认情况下它们将仅被强制转换为整数值。

以下过滤器可用作一种简单的方法,可将强制转换的值进一步转换为更易读的内容。

下面显示了在attributes 选项中使用这些过滤器的示例。

plugin: microsoft.ad.ldap

attributes:
  pwdLastSet:
    password_last_set_int: this
    password_last_set_datetime: this | microsoft.ad.as_datetime
# ansible-inventory -i microsoft.ad.ldap.yml --host MYHOST --vars --yaml

ansible_host: MYHOST.domain.com
password_last_set_datetime: 2023-02-06T07:39:09.195321+0000
password_last_set_int: 133201427491953218
microsoft_ad_distinguished_name: CN=MYHOST,CN=Computers,DC=domain,DC=com

模板还可以引用集合之外的其他过滤器,例如 Ansible 内置的from_json 等等。该值只是在正常的模板操作期间将放置在{{ ... }} 内的内容。

注意

属性值模板中不能使用查找,只能使用过滤器。

attributes 清单选项中使用的每个模板都可以引用以下变量。

  • this

  • raw

  • 任何先前定义的属性

this 变量指的是强制转换的 LDAP 属性值,而raw 变量指的是表示未强制转换的原始 LDAP 值的 base64 编码字符串列表。在处理每个属性主机事实时,它也可以在后续模板中以该主机事实名称的形式使用。这是一个更复杂的属性集的示例。

plugin: microsoft.ad.ldap

attributes:
  objectSid:
    sid: this
    sid_raw: raw
    sid_raw_filtered: raw | microsoft.ad.as_sid | first
  objectGuid:
  sAMAccountName:
    computer_name:
  comment:
    comment: this
    # Can refer to previously set attributes above
    description: computer_name ~ " - " ~ sid ~ " - " ~ objectGuid ~ " - " ~ this

# Can also be used as a template and refer to the vars retrieved above
compose:
  comment2: comment
# ansible-inventory -i microsoft.ad.ldap.yml --host MYHOST --vars --yaml

ansible_host: MYHOST.domain.com
comment: test comment
comment2: test comment
computer_name: MYHOST$
description: MYHOST$ - S-1-5-21-1234-1108 - 51cc490f-1de0-41ae-98ad-dc065d5b33e2 - test comment
objectGuid: 51cc490f-1de0-41ae-98ad-dc065d5b33e2
sid: S-1-5-21-1234-1108
sid_raw:
- AQMAAAAAAAUVAAAA0gQAAFQEAAA=
sid_raw_filtered: S-1-5-21-1234-1108
microsoft_ad_distinguished_name: CN=MYHOST,CN=Computers,DC=domain,DC=com

LAPS

本地管理员密码解决方案 (LAPS) 可用于自动更改已加入域的主机上的本地管理员帐户的密码。LDAP 连接插件可以检索 LAPS 管理的值并将其分配为目标主机的连接密码。

LAPS 可以使用三种不同的属性来存储密码信息。

  • ms-Mcs-AdmPwd - 包含密码的旧版 LAPS 属性

  • msLAPS-Password - 包含用户名和密码的 Windows LAPS 属性

  • msLAPS-EncryptedPassword - 包含加密的用户名和密码的 Windows LAPS 属性

如果使用旧版 LAPS 设置,则以下内容将检索并将连接用户名和密码分配给 LAPS 管理的值。

plugin: microsoft.ad.ldap

attributes:
  ms-Mcs-AdmPwd:
    ansible_user: '"Administrator"'
    ansible_password: this
# ansible-inventory -i microsoft.ad.ldap.yml --host MYHOST --vars --yaml

ansible_host: MYHOST.domain.com
ansible_password: aR$lmrqK1l622H
ansible_user: Administrator
microsoft_ad_distinguished_name: CN=MYHOST,CN=Computers,DC=domain,DC=com

注意

旧版 LAPS 不存储用户名,以上示例硬编码了用户名Administrator

如果使用未加密的 Windows LAPS,则以下内容将连接用户名和密码分配给 LAPS 管理的值。

plugin: microsoft.ad.ldap

attributes:
  msLAPS-Password:
    ansible_user: (this | from_json).n
    ansible_password: (this | from_json).p
    raw_example: raw
    this_example: this
# ansible-inventory -i microsoft.ad.ldap.yml --host MYHOST --vars --yaml

ansible_host: MYHOST.domain.com
ansible_password: AWznso@ZJ+J6p9
ansible_user: Administrator
microsoft_ad_distinguished_name: CN=MYHOST,CN=Computers,DC=domain,DC=com
raw_example:
- eyJuIjoiQWRtaW5pc3RyYXRvciIsInQiOiIxZDk4MmI0MzdiN2E1YzYiLCJwIjoiQVd6bnNvQFpKK0o2cDkifQ==
this_example:
  n: Administrator
  p: AWznso@ZJ+J6p9
  t: 1d982b437b7a5c6

与旧版 LAPS 不同,属性值是一个包含以下键的 json 字符串:

  • n - 为其加密密码的帐户名

  • p - 帐户的密码

  • t - 以 base16 编码的 FILETIME 设置密码的时间

注意

建议对this 值使用from_json 过滤器(如上例所示),以确保在存在或不存在 Jinja2 本机类型支持的情况下保持一致的行为。

获取加密的 Windows LAPS 值需要安装dpapi-ng Python 库。有关此可选包以及如何调试其是否已安装的更多信息,请参见LDAP 连接要求

注意

使用 Windows LAPS 加密密码目前是一项实验性功能。

安装了dpapi-ng 包后,授权的 LDAP 用户可以解密并将 LAPS 管理的用户名和密码分配给目标主机的连接,如下所示:

plugin: microsoft.ad.ldap

attributes:
  msLAPS-EncryptedPassword:
    ansible_user: (this.value | from_json).n
    ansible_password: (this.value | from_json).p
    raw_example: raw
    this_example: this
# ansible-inventory -i microsoft.ad.ldap.yml --host MYHOST --vars --yaml

ansible_host: MYHOST.domain.com
ansible_password: 6jr&}yK++{0Q}&
ansible_user: Administrator
microsoft_ad_distinguished_name: CN=MYHOST,CN=Computers,DC=domain,DC=com
raw_example:
- toLZAWR7rgfk...
this_example:
  encrypted_value: MIIETgYJKoZI...
  flags: 0
  info: ''
  update_timestamp: 133281382308674404
  value: '{"n":"Administrator","t":"1d982b607ae7b64","p":"6jr&}yK++{0Q}&"}'

raw 值包含在 AD 中存储的原始 base64 编码值。this 值包含一个包含以下键的字典:

  • encrypted_value:作为 base64 字符串的加密密码块

  • flags:设置为按位整数值的标志,目前这些标志未被 Microsoft 记录

  • update_timestamp: 的 FILETIME 值

  • value:包含用户名和密码的解密值(作为 JSON 字符串)

  • debug:指示解密失败原因的调试信息

只有在解密过程成功时,value 键才会出现。如果失败,则debug 键将出现,并包含失败原因。

如果未安装dpapi-ng 库,则输出如下所示:

# ansible-inventory -i microsoft.ad.ldap.yml --host MYHOST --vars --yaml

ansible_host: MYHOST.domain.com
microsoft_ad_distinguished_name: CN=MYHOST,CN=Computers,DC=domain,DC=com
raw_example:
- toLZAWR7rgfk...
this_example:
  debug: Cannot decrypt value as the Python library dpapi-ng is not installed
  encrypted_value: MIIETgYJKoZI...
  flags: 0
  update_timestamp: 133281382308674404

value 键不再存在,debug 包含dpapi-ng 未安装的消息。

如果安装了dpapi-ng 库,但连接用户无权解密该值,则输出如下所示:

# ansible-inventory -i microsoft.ad.ldap.yml --host MYHOST --vars --yaml

ansible_host: MYHOST.domain.com
microsoft_ad_distinguished_name: CN=MYHOST,CN=Computers,DC=domain,DC=com
raw_example:
- toLZAWR7rgfk...
this_example:
  debug: Failed to decrypt value due to error - ValueError GetKey failed 0x80070005
  encrypted_value: MIIETgYJKoZI...
  flags: 0
  update_timestamp: 133281382308674404

测试连接用户是否能够解密密码的一种简单方法是在 Windows 主机上以该用户身份运行Get-LapsADPassword -Identity MYHOST