属性指南

此集合中模块的一个常见用例是管理各种 Active Directory 对象,例如用户、组、计算机等等。其中一些选项作为直接模块选项公开,但其他属性可能需要通过此集合中大多数模块通用的 attributes 选项进行设置。

LDAP 属性

Microsoft 的 Active Directory (AD) 的一个核心组件是轻型目录访问协议 (LDAP) 数据库。此数据库包含与 AD 环境相关的所有信息,例如用户、计算机、组织单位等等。每个对象都包含一组动态属性,用于描述对象并符合架构。例如,用户包含 firstNamecountrysAMAccountName 等属性来描述对象本身。Microsoft 在其AD 属性架构中记录了 AD 中的所有内置属性。例如,SAM-Account-Name 属性包含有关此属性的元数据。它包括以下字段:

  • Ldap-Display-Name - LDAP 显示名称

  • Syntax - 属性存储的底层值类型

  • System-Only - 属性是否由系统设置,实际上使其为只读

  • Is-Single-Value - 属性值是单个值还是值数组/列表

Ldap-Display-Name 是 Ansible 模块引用的属性名称/键。例如,要管理 SAM-Account-Name 属性,它将由键 sAMAccountName 引用。每个属性至少关联 1 个值,但某些属性可以有多个值。例如,sAMAccountName 是一个 Is-Single-Value 属性,因此只有一个值,但 userCert 可以包含多个值。可以使用 Active Directory Users and Computers 管理单元(或 dsa.msc)在高级模式下查看这些 LDAP 属性。这对于查看现有值以及可以在对象上设置哪些属性非常有用。

还可以扩展 AD 中的 LDAP 架构,为组织添加自定义属性。此集合中的模块也支持这些自定义属性。要获取属性的 LDAP 架构信息,可以在 PowerShell 中运行以下命令:

Function Get-AttributeMetadata {
    [CmdletBinding()]
    param ([Parameter(ValueFromPipeline)][string[]]$Name)

    begin {
        $schema = (Get-ADRootDSE -Properties subschemaSubentry).subschemaSubentry
        $getParams = @{
            SearchBase = $schema
            LDAPFilter = '(objectClass=*)'
            Properties = 'attributeTypes'
        }
        $attributes = (Get-ADObject @getParams).attributeTypes
        $queried = $false
    }

    process {
        foreach ($n in $Name) {
            $queried = $true
            $attributes | Where-Object {
                $_ -like "*Name '$n'*"
            }
        }
    }

    end {
        if (-not $queried) {
            $attributes
        }
    }
}

# Display all attributes
Get-AttributeMetadata

# Get specific attributes
Get-AttributeMetadata -Name sAMAccountName, o, objectGuid

输出格式为:

( $ATTRIBUTE_OID NAME '$ATTRIBUTE_NAME' SYNTAX '$TYPE_OID' [SINGLE-VALUE|NO-USER-MODIFICATION] )

$TYPE_OID 指定可用于此属性的值类型。在线搜索 OID 以获取更多信息。SINGLE-VALUE 指定属性是否只能存储 1 个值。NO-USER-MODIFICATION 指定属性是否为只读且不能设置。

最后一个示例输出:

( 1.2.840.113556.1.4.221 NAME 'sAMAccountName' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE )
( 2.5.4.10 NAME 'o' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' )
( 1.2.840.113556.1.4.2 NAME 'objectGUID' SYNTAX '1.3.6.1.4.1.1466.115.121.1.40' SINGLE-VALUE NO-USER-MODIFICATION )

这表明 sAMAccountName 是一个只能有 1 个值的字符串。o 属性也是一个字符串,但可以存储多个值。objectGUID 是一个只能有 1 个值的字节数组值,并且也是只读的。

设置属性

每个管理 Active Directory 对象的模块都将具有 attributes 选项,该选项用于直接配置 LDAP 属性。字典接受三个键:

  • add - 如果不存在,则添加属性值

  • remove - 如果存在,则删除属性值

  • set - 将现有属性值替换为指定的值。

这些键中的每一个都包含一个字典值,其中键是 ldapDisplayName 的 LDAP 属性名称,以及要设置的值。由于 LDAP 属性可以包含多个值,因此指定的值可以是单个值或值列表,例如:

- microsoft.ad.user:
    name: MyUser
    state: present
    attributes:
      set:
        comment: My Comment
        extensionName:
        - Extension Value 1
        - Extension Value 2
        - Extension Value 3

上面的示例会将 MyUser 对象的 comment LDAP 属性设置为指定的值。它还将确保 extensionName 属性设置为这三个值,如果存在则删除任何其他值。

可以使用 add 键来确保将指定的 LDAP 属性值添加到属性值列表中。对于 remove 键下的属性,则相反。如果这些属性在问题属性中存在,则将删除指定的值。例如:

- microsoft.ad.user:
    name: MyUser
    state: present
    attributes:
      add:
        extensionName:
        - Extension Value 1
        - Extension Value 3
      remove:
        extensionName:
        - Extension Value 2

上面的示例将确保 extensionName 具有值 Extension Value 1Extension Value 3,并删除 Extension Value 2(如果已设置)。因为未使用 set,所以除非它们在 remove 条目中,否则任何现有值都不会被触及。

注意

仅使用可以使用 addremove 添加或删除多个值的 LDAP 属性。使用 Is-Single-Value 属性会导致未定义的行为。

要清除属性值,请在 set 下定义属性,并将值设置为 null(~)或空列表。例如:

- microsoft.ad.user:
    name: MyUser
    state: present
    attributes:
      set:
        # Null can either be represented by no value
        # or with tilde (~)
        comment: ~
        company:
        extensionName: []

此任务将确保清除 commentcompanyextensionName 属性的所有值。

属性类型

属性中可以存储几种不同的值类型。常见的类型有:

  • 字符串

  • 整数

  • 布尔值

  • 字节数组

  • 日期

  • 安全描述符

通过 Ansible 任务设置字符串、整数或布尔值只需使用 YAML 语法即可,例如:

string: This is a string
integer: 1
boolean: true

注意

字符串比较区分大小写,即 "String" != "string"

这些简单类型也可以用带有键 typevalue 的字典表示。类型键可以设置为以下值之一:

  • bool - 值被转换为布尔值

  • bytes - 值被解码为 base64 字符串

  • date_time - 值被解码为 ISO 8601 日期时间字符串

  • int - 值被解码为整数

  • security_descriptor - 值被解码为 SDDL 字符串

  • string - 值被转换为字符串

  • raw - 值按原样使用 - 这是使用的默认类型

如下所示:

- microsoft.ad.user:
    name: MyUser
    state: present
    attributes:
      set:
        # comment: A raw value that is a string
        comment:
          type: raw
          value: A string

        # userAccountControl: 1234
        userAccountControl:
          type: int
          value: 1234

        # extensionName: ['Value 1', 'Value 2']
        extensionName:
        - type: raw
          value: Value 1
        - type: raw
          value: Value 2

带有 typevalue 结构的复杂字典值仅在处理下面列出的更复杂类型时才真正需要。如果省略,则该值被视为 type: raw

字节数组

由于原始字节无法在 YAML 中表示,要设置具有字节数组值的属性,请使用以下格式:

- microsoft.ad.user:
    name: MyUser
    state: present
    attributes:
      set:
        # Attribute with single value
        dsaSignature:
          type: bytes
          value: YmluYXJ5
        # Attribute with multiple values
        userCertificate:
        - type: bytes
          value: Zm9vYmFy
        - type: bytes
          value: YmFyZm9v

此处指定的值是编码为 base64 字符串的字节。

可以使用 ansible.builtin.b64encode 过滤器 动态编码字符串,可以使用 ansible.builtin.file 查找 从文件中读取数据。

- vars:
    sig_data: "{{ lookup('ansible.builtin.file', '/path/to/my/sig') }}"
  microsoft.ad.user:
    name: MyUser
    state: present
    attributes:
      set:
        # Attribute with single value
        dsaSignature:
          type: bytes
          value: "{{ sig_data | ansible.builtin.b64encode }}"

日期

具有日期时间值的属性在技术上是整数值,但表示时间点。为了便于使用,这些条目可以表示为 ISO 8601 扩展格式的日期时间,并且将在内部用整数值表示。要以日期时间格式指定属性值,请使用与上述相同的字典值结构,但将 type 设置为 date_time。例如:

- microsoft.ad.user:
    name: MyUser
    state: present
    attributes:
      set:
        dateAttributeSingleValue:
          type: date_time
          value: '2019-09-07T15:50:00+00:00'
        dateAttributeMultipleValue:
        - type: date_time
          value: '2019-09-07T15:50:00Z'
        - type: date_time
          value: '2019-09-07T11:50:00-04:00'

在内部,日期时间被转换为 UTC 时间,并转换为自 1601-01-01 以来的 100 纳秒增量的数量。此 PowerShell 代码片段显示了内部发生的情况,以获取整数值:

$dt = '2019-09-07T15:50:00Z'
$dtVal = [DateTimeOffset]::ParseExact(
    $dt,
    [string[]]@("yyyy-MM-dd'T'HH:mm:ss.FFFFFFFK"),
    [System.Globalization.CultureInfo]::InvariantCulture,
    [System.Globalization.DateTimeStyles]::AssumeUniversal)
$dtVal.UtcDateTime.ToFileTimeUtc()

注意

如果未指定时区,则假定为 UTC。

安全描述符

安全描述符作为字节数组存储在属性中,但可以使用 security_descriptor 类型在 playbook 中更方便地表示此值。指定的值是 安全描述符定义语言 (SDDL)。此字符串在内部转换为设置 SDDL 所需的字节数组。设置此类型属性的示例如下:

- microsoft.ad.user:
    name: MyUser
    state: present
    attributes:
      set:
        nTSecurityDescriptor:
          type: security_descriptor
          value: O:DAG:DAD:PAI(A;CI;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;WD)

SDDL 字符串可能非常复杂,因此不建议手动构建它们。建议在 Active Directory Users and Computers 管理单元(或 dsa.msc)中构建一个测试对象,并在 Security 选项卡中根据需要设置安全性。然后可以通过执行以下操作检索 SDDL 字符串:

$dn = 'CN=ObjectName,DC=domain,DC=test'
$obj = Get-ADObject -Identity $dn -Properties nTSecurityDescriptor
$obj.nTSecurityDescriptor.GetSecurityDescriptorSddlForm('All')

DN 查找属性

Active Directory 中的某些属性存储为引用另一个 AD 对象的专有名称 (DN) 值。某些模块提供了一种使用更人性化的值(如 managed_by)来查找 DN 的方法。这些选项值必须是字符串或带有键 name 和可选键 server 的字典。字符串值或 name 的值是要查找的标识,而 server 是要在其上查找标识的域服务器。查找标识值可以指定为 distinguishedNameobjectGUIDobjectSidsAMAccountNameuserPrincipalName。以下示例说明如何使用字符串值或字典形式使用 sAMAccountName 查找 DN:

- name: Find managed_by using string value
  microsoft.ad.group:
    name: My Group
    scope: global
    managed_by: Domain Admins

- name: Find managed_by using dictionary value with a server
  microsoft.ad.group:
    name: My Group
    scope: global
    managed_by:
      name: Domain Admins
      server: OtherDC

还有一些模块选项可以为属性设置 DN 值列表。这些选项的列表值与单个值属性相同,其中每个 DN 查找都设置为字符串或带有 name 和可选的 server 键的字典。

- name: Specify a list of DNs to set
  microsoft.ad.computer:
    identity: TheComputer
    delegates:
      set:
      - FileShare
      - name: ServerA
        server: OtherDC

对于带有 add/remove/set 子键选项的列表属性,还可以将 lookup_failure_action 选项设置为 fail(默认)、ignorewarnfail 选项会在任何查找失败时导致任务失败,ignore 将忽略任何无效的查找,而 warn 将发出警告,但在查找失败时仍继续。

- name: Specify a list of DNs to set - ignoring lookup failures
  microsoft.ad.computer:
    identity: TheComputer
    delegates:
      lookup_failure_action: ignore
      set:
      - FileShare
      - MissingUser

如果提供了 server 键,则将使用指定的服务器值完成查找。还可以使用 domain_credentials 选项为此服务器提供显式凭据。

- name: Set member with lookup on different server
  microsoft.ad.group:
    name: MyGroup
    state: present
    members:
      add:
      - GroupOnDefaultDC
      - name: GroupOnDefaultDC2
      - name: GroupOnOtherDC
        server: OtherDC
    domain_credentials:
    - username: UserForDefaultDC
      password: PasswordForDefaultDC
    - name: OtherDC
      username: UserForOtherDC
      password: PasswordForOtherDC

在上面,GroupOnOtherDC 将使用 OtherDC 和用户名 UserForOtherDC 完成。

模块选项的文档将标识该选项是否支持查找行为,或者是否必须显式提供 DN 值。