en-US/about_OpenADAttributeFormats.help.txt
TOPIC
about_openadattributeformats SHORT DESCRIPTION Setting the attributes/properties of an AD object is a common scenario of this module. This document will go through how to set values for attributes and how values are transformed over the LDAP protocol. LONG DESCRIPTION The New-OpenADObject based on a PowerShell object. It is important to use the correct object type for the value when setting attributes that expect a specific type. This is because the cmdlets will not transform the value based on the attribute specified but rather transform it based on the value provided. For example trying to set a `DateTime` or `DateTimeOffset` value to an LDAP attribute that accepts a string representing the `DateTime` will fail. LDAP Syntaxes Knowing what type to use when setting an LDAP attribute is key and should be the first step done when trying to manage an attribute. As LDAP contains a schema of the data it is possible to see the available attributes as well as the type they expect. The following script can be used to retrieve a specific or multiple attributes and see what their `attributeSyntax` and `oMSyntax` values are. Function Get-AttributeMetadata { [CmdletBinding()] param ([Parameter(ValueFromPipeline)][string[]]$Name) begin { $schema = (Get-OpenADRootDSE -Properties schemaNamingContext).schemaNamingContext $getParams = @{ SearchBase = $schema LDAPFilter = '(objectClass=attributeSchema)' Properties = 'lDAPDisplayName', 'attributeSyntax', 'oMSyntax' } $attributes = Get-OpenADObject @getParams | Select-Object -Property @( @{ N = 'Name'; E = { $_.LDAPDisplayName } }, 'AttributeSyntax', 'OMSyntax' ) $queried = $false } process { foreach ($n in $Name) { $queried = $true $attributes | Where-Object Name -like $n } } end { if (-not $queried) { $attributes } } } By default this outputs all the attributes, their `attributeSyntax` and `oMSyntax`, the cmdlet can be used to filter it by name if desired. Here are some common `attributeSyntax` and `oMSyntax` combinations and what type should be used when setting them in this module. |Name|AttributeSyntax|OMSyntax|Type| |-|-|-|-| | Object(DS-DN) |2.5.5.1|127|LDAP DistinguishedName as a string| | String(Object-Identifier) |2.5.5.2|6|OID dotted notation as a string| | String(Teletex) |2.5.5.4|20|A string with characters restricted to the Teletex character set| | String(IA5) | | String(IA5) | | String(Numeric) |2.5.5.6|18|A string that contains digits only, can also be set from an integer| | Object(DN-Binary) |2.5.5.7|127|A string in the format `B:<char count>:<binary value>:<object DN>`, see `New-ObjectDNBinary` below| | Boolean |2.5.5.8|1|A boolean value; `$true` or `$false`, can also be the string `TRUE` or `FALSE`| | Enumeration |2.5.5.9|2|An integer value with well known constants, see the documentation for each specific attribute for more information| | Enumeration |2.5.5.9|10|See above| | String(Generalized-Time) |2.5.5.11|23|String in the format `YYYYMMDDHHMMSS.0Z` or `YYYYMMDDHHMMSS.0[+/-]HHMM`| | String(Generalized-Time) |2.5.5.11|24|See above| | String(Unicode) |2.5.5.12|64|A string| | String(NT-Sec-Desc) |2.5.5.15|66|A SecurityDescriptor object, see `CommonSecurityDescriptor` below| | Interval |2.5.5.16|65|A `LargeInteger` value, either use an int or `DateTime` object| | String(Sid) |2.5.5.17|4|A SecurityIdentifier object, see `SecurityIdentifier` below| Some helper functions to create some of the more complex values are below: Function New-ObjectDNBinary { [CmdletBinding()] param ( [Parameter(Mandatory)] [byte[]] $Value, [Parameter(Mandatory)] [string] $DN ) $binaryHex = [Convert]::ToHexString($Value) "B:$($binaryHex.Length):${binaryHex}:$DN" } See MS-ADTS LDAP Representations for more information on how AD maps the `attributeSyntax` and `oMSyntax` to a specific type. See Active Directory Attributes for definitions of every builtin class to AD and their syntax inforamtion, note they are keyed by the AD name and not `lDAPDisplayName`. RFC 4517 contains more background information on the various syntaxes and the formats they allow. Type Transformers This module includes some builtin type transformers to convert specific objects into a more friendly LDAP represetnation. The following table demonstrates how each specific type is transformed into the raw LDAP value to set and what LDAP type they are useful for. |Type|Behaviour|For Attribute| |-|-|-| |$null|No values/empty|| |bool|Either `TRUE` or `FALSE`|`Boolean`| |CommonSecurityDescriptor|The raw byte[] representation of the SD|`String(NT-Sec-Desc)`| |Enum|The integer value of the enum|`Enumeration`| |DateTime|The UTC FILETIME integer value and not the string representation of the DateTime|`Interval`| |DateTimeOffset|Will use the UTC FILETIME integer value and not the string representation of the DateTime|`Interval`| |Guid|The raw byte[] representation of the Guid|| |SecurityIdentifier|The raw byte[] representation of the SID|`String(Sid)`| |TimeSpan|The number of ticks (100s of nanoseconds) is used as an integer value|`Interval`| |X509Certificate|The raw byte[] of the certificate in DER form|| If the type is not listed the value is converted to a string and sent as is. For example setting an integer value `100` is the same as setting `'100'` as a string. DateTime values Settings a `DateTime` value is a complex scenario as the value provided to the cmdlet is based on whether the underlying LDAP attribute accepts a `GeneralizedTime` or `FILETIME` value. For a `GeneralizedTime` the `DateTime` needs to be provided as a string in a specific format: $dt = Get-Date $dt.ToString("yyyyMMddhhmmss.fzzz").Replace(':', '') Some LDAP implementations may differ in what format they expect but if it's an LDAP 3 compliant server then the above should work. For a `FILETIME` value or even just a `LargeInteger` attribute the `DateTime` object can be provided as is. The cmdlet will do `$dt.ToFileTimeUtc()` and use that raw integer value as the one to set. |