Active Directory is based on Lightweight Directory Access Protocol (LDAP) and supports the LDAP version 3 specification defined in RFC 2251. And while many of the AD tools and interfaces, such as ADSI, abstract and streamline LDAP operations to make things easier, any good AD administrator or developer must have a thorough understanding of LDAP to fully utilize Active Directory. This chapter will cover some of the LDAP-related tasks you may need to perform when working with Active Directory, along with other tasks related to searching and manipulating objects within the directory.
The Active Directory schema is composed of a hierarchy of classes
that define the types of objects that can be created within Active
Directory, as well as the different attributes they can possess. These
classes support inheritance, which enables
developers to reuse existing class definitions for more than one type of
object; for example, the description
attribute is available with every type of AD object, but the attribute
itself is defined only once within the schema. At
the top of the inheritance tree is the top
class, from which every class in the
schema is derived. Table 4-1
contains a list of some of the attributes that are available from the
top
class, and subsequently are
defined on every object that is created in Active Directory.
Table 4-1. Common attributes of objects
Attribute | Description |
---|---|
| RDN attribute for most object classes, also referred to as the common name. |
| Timestamp when the object was created. See Viewing the Created and Last-Modified Timestamp of an Object for more information. |
| Multivalued attribute that can be used as a generic field for storing a description of the object. Although this attribute is multivalued, objects such as users and groups can have only one value populated due to legacy support requirements. |
| Name of the object displayed in administrative interfaces. |
| Distinguished name of the object. |
| Timestamp when the object was last changed by the local server. See Viewing the Created and Last-Modified Timestamp of an Object for more information. |
| RDN of the object. The
value of this attribute will mirror the naming attribute (e.g.,
|
| Security descriptor assigned to the object. |
| Used as a grouping
mechanism for objects with a similar purpose (e.g., |
| List of classes from which the object’s class was derived. |
| Globally unique identifier for the object. |
| Update sequence number (USN) assigned by the local server after the last change to the object (can include creation). |
| USN assigned by the local server when the object was created. |
You want to view attributes of the RootDSE, which can be useful for discovering basic information about a forest, domain, or domain controller without hardcoding the name of a particular naming context into a query.
To display the RootDSE of a domain controller using AdFind, use the following syntax:
> adfind -rootdse
Get-ADRootDSE
You’ll see results similar to the following (truncated for readability):
configurationNamingContext: cn=Configuration,dc= adatum,dc=com currentTime: 10/9/2012 9:27:38 AM defaultNamingContext: dc=adatum,dc=com dnsHostName: dc1.adatum.com domainControllerFunctionality: Windows2012 domainFunctionality: Windows2012Domain dsServiceName: cn=NTDS Settings,cn=DC1,cn=Servers,cn=Default-First-Site-Name,↵ cn=Sites,cn=Configuration,dc=adatum,dc=com forestFunctionality: Windows2012Forest highestCommittedUSN: 28013 isGlobalCatalogReady: {TRUE} isSynchronized: {TRUE} ldapServiceName: adatum.com:dc1$@ADATUM.COM namingContexts: {dc=adatum,dc=com, cn=Configuration,dc=adatum,dc=com, cn=Schema,cn=Configuration,dc=adatum,dc=com,dc=DomainDnsZones,dc=adatum,↵ dc=com...} rootDomainNamingContext: dc=adatum,dc=com schemaNamingContext: cn=Schema,cn=Configuration,dc=adatum,dc=com serverName: cn=dc1,cn=Servers,cn=Default-First-Site-Name,cn=Sites,↵ cn=Configuration,dc=adatum,dc=com subschemaSubentry: cn=Aggregate,cn=Schema,cn=Configuration,dc=adatum,dc=com supportedCapabilities: {1.2.840.113556.1.4.800 (LDAP_CAP_ACTIVE_DIRECTORY_OID),;1.2.840.113556.1.4.1670(LDAP_CAP_ACTIVE_DIRECTORY_V51_OID),;1.2.840.113556.1.4.1791(LDAP_CAP_ACTIVE_DIRECTORY_LDAP_INTEG_OID),;1.2.840.113556.1.4.1935(LDAP_CAP_ACTIVE_DIRECTORY_V61_OID)...} supportedControl: {1.2.840.113556.1.4.319(LDAP_PAGED_RESULT_OID_STRING),;1.2.840.113556.1.4.801(LDAP_SERVER_SD_FLAGS_OID),;1.2.840.113556.1.4.473(LDAP_SERVER_SORT_OID),;1.2.840.113556.1.4.528(LDAP_SERVER_NOTIFICATION_OID)...} supportedLDAPPolicies: {MaxPoolThreads, MaxDatagramRecv, MaxReceiveBuffer,; InitRecvTimeout...} supportedLDAPVersion: {3, 2} supportedSASLMechanisms: {GSSAPI, GSS-SPNEGO, EXTERNAL, DIGEST-MD5}
The RootDSE was originally defined in RFC 2251 as part of the LDAPv3 specification. It is not part of the Active Directory namespace per se. It is a synthetic object that is maintained separately by each domain controller.
The RootDSE can be accessed anonymously using LDP; the command-line and PowerShell solutions use the credentials of the currently logged-on user unless you specify an alternate username and password. In the CLI and PowerShell solutions, serverless binds were used against the RootDSE. In that case, the DC Locator process is used to find a domain controller in the domain you authenticate against. This can also be accomplished with LDP by not entering a server name from the Connect dialog box.
The RootDSE is key to writing portable AD-enabled applications. It provides a mechanism to programmatically determine the distinguished names of the various naming contexts (among other things), which means that you do not need to hardcode that information in scripts and programs.
From the menu, select Connection→Connect.
For Server, enter the name or IP address of a domain controller or domain that contains the object.
For Port, enter 389.
Click OK.
From the menu, select Connection→Bind.
Accept the default and bind as the currently logged on user or select the option to bind with credentials and then enter the credentials.
Click OK.
From the menu, select View→Tree.
For BaseDN, type the DN of the object you want to view.
For Scope, select Base.
Click OK.
To obtain a list of attributes for a particular object using DSQuery, use the following syntax:
> dsquery * "<ObjectDN>
" -scope base -attr *
To query for an object using AdFind, use the following syntax:
> adfind -b<Parent Container DN>
-f cn=<Object CN>
-tdcgt
To get the attributes of the built-in Administrator account, run the following PowerShell command:
Get-ADUser -Identity Administrator -Properties *
An example of the output is shown here:
AccountExpirationDate : accountExpires : 0 AccountLockoutTime : AccountNotDelegated : False adminCount : 1 AllowReversiblePasswordEncryption : False BadLogonCount : 0 badPasswordTime : 129934507947486667 badPwdCount : 0 CannotChangePassword : False CanonicalName : adatum.com/Users/Administrator Certificates : {} City : CN : Administrator codePage : 0 Company : CompoundIdentitySupported : {} Country : countryCode : 0 Created : 9/27/2012 11:16:45 AM createTimeStamp : 9/27/2012 11:16:45 AM Deleted : Department : Description : Built-in account for administering the computer/domain DisplayName : DistinguishedName : cn=Administrator,cn=Users,dc=adatum,dc=com Division : DoesNotRequirePreAuth : False dSCorePropagationData : {9/27/2012 11:34:42 AM,↵ 9/27/2012 11:34:42 AM,↵ 9/27/2012 11:19:31 AM,↵ 1/1/1601 10:12:16 AM} EmailAddress : EmployeeID : EmployeeNumber : Enabled : True Fax : GivenName : HomeDirectory : HomedirRequired : False HomeDrive : HomePage : HomePhone : Initials : instanceType : 4 isCriticalSystemObject : True isDeleted : KerberosEncryptionType : {} LastBadPasswordAttempt : 9/29/2012 8:53:14 PM LastKnownParent : lastLogoff : 0 lastLogon : 129942736428265971 LastLogonDate : 10/9/2012 9:27:17 AM lastLogonTimestamp : 129942736379503412 LockedOut : False logonCount : 29 logonHours : {255, 255, 255, 255...} LogonWorkstations : Manager : MemberOf : {cn=Group Policy Creator Owners,cn=Users,dc=adatum,dc=com, cn=Domain Admins,cn=Users,dc=adatum,dc=com, cn=Enterprise Admins,cn=Users,dc=adatum,dc=com, cn=Schema Admins,cn=Users,dc=adatum,dc=com...} MNSLogonAccount : False MobilePhone : Modified : 10/9/2012 9:27:17 AM modifyTimeStamp : 10/9/2012 9:27:17 AM msDS-AuthenticatedAtDC : {cn=2012-DC05,OU=Domain Controllers,dc=adatum,dc=com} msDS-User-Account-Control-Computed : 0 Name : Administrator nTSecurityDescriptor : System.DirectoryServices.↵ ActiveDirectorySecurity ObjectCategory : cn=Person,cn=Schema,cn=Configuration,↵ dc=adatum,dc=com ObjectClass : user ObjectGUID : c897bc0a-b5d4-4025-8c10-b696e45ce780 objectSid : S-1-5-21-3384837461-4027165227-↵ 453512602-500 Office : OfficePhone : Organization : OtherName : PasswordExpired : False PasswordLastSet : 9/27/2012 10:18:17 AM PasswordNeverExpires : False PasswordNotRequired : False POBox : PostalCode : PrimaryGroup : cn=Domain Users,cn=Users,dc=adatum,dc=com primaryGroupID : 513 PrincipalsAllowedToDelegateToAccount : {} ProfilePath : ProtectedFromAccidentalDeletion : False pwdLastSet : 129932398979898472 SamAccountName : Administrator sAMAccountType : 805306368 ScriptPath : sDRightsEffective : 15 ServicePrincipalNames : {} SID : S-1-5-21-3384837461-4027165227-↵ 453512602-500 SIDHistory : {} SmartcardLogonRequired : False State : StreetAddress : Surname : Title : TrustedForDelegation : False TrustedToAuthForDelegation : False UseDESKeyOnly : False userAccountControl : 512 userCertificate : {} UserPrincipalName : uSNChanged : 28008 uSNCreated : 8196 whenChanged : 10/9/2012 9:27:17 AM whenCreated : 9/27/2012 11:16:45 AM
Objects in Active Directory are made up of a collection of attributes. Attributes can be single- or multivalued. Each attribute also has an associated syntax that is defined in the schema. See Adding a New Attribute for a complete list of syntaxes.
You can customize the list of attributes returned from a search
with LDP by modifying the Attributes: field under Options→Search. To
include all attributes, enter an asterisk (*
). To modify the default subset of
attributes that are returned, enter a semicolon-separated list of attributes.
You can also use the numeric attribute ID instead of the attribute
name, such as using 1.1
in place of
distinguishedName
.
The -attr
option for the
dsquery
command accepts a
whitespace-separated list of attributes to display. Using an asterisk
(*
) will return all default
attributes.
When using AdFind, you have several shortcut switches to reduce
the amount of typing you need to do. If you are searching for an
object in the default container, you can use the –default
switch rather than something like
–b dc=contoso,dc=com
. Likewise, if
you are querying the Configuration NC, you can use the –config
switch, -root
for the root partition, or –schema
for the Schema partition. If you
want to query a subcontainer of one of these partitions, you can add
the –rb
switch, which stands for
Relative Base.
Adding a New Attribute; MSDN: IADsPropertyEntry; MSDN: IADsPropertyList; MSDN: ADSTYPEENUM; MSDN: IADs::GetInfo; Active Directory, Fifth Edition, by Brian Desmond et al. (O’Reilly)
From the menu, select Connection→Connect.
For Server, enter the name or IP address of a domain controller or the domain that contains the object.
For Port, enter 389.
Click OK.
From the menu, select Connection→Bind.
Accept the default and bind as the currently logged on user or select the option to bind with credentials and then enter the credentials.
Click OK.
From the menu, select Browse→Search.
Enter the base DN, scope, and LDAP filter of the objects that you’re looking for.
Click Options and remove the checkmark next to Display Results. This will display the number of objects returned by the query without displaying the details of the items that are returned.
Click OK and then click Run to perform the query.
To retrieve a count of objects that match a particular query, use the following syntax:
> adfind -b<Search Base>
-s<Scope>
-f<Search Filter>
-c
For example, retrieving the number of user objects in the adatum.com domain would use the following syntax:
> adfind -default -f "(&(objectclass=user)(objectcategory=person))" -c > > AdFind V01.46.00cpp Joe Richards (joe@joeware.net) March 2012 > > Using server: dc1.adatum.com:389 > Directory: Windows Server 8 > Base DN: dc=adatum,dc=com > > 5 Objects returned
The following example will query Active Directory for a list of user objects in the current domain and return the count:
Get-ADObject -Filter {(objectClass -eq "user") -and (objectCategory -eq "person")} | Measure-Object | FL Count
To retrieve a count of all of the computer objects in the current domain, run the following command:
Get-ADObject -Filter {(objectClass -eq "user") -and (objectCategory -eq "computer")} | Measure-Object | FL Count
The PowerShell commands can target a specific container or OU, as follows:
Get-ADObject -SearchBase "OU=Branches,dc=adatum,dc=com" -Filter {(objectClass -eq "user") -and (objectCategory -eq "person")} | Measure-Object | FL Count
Be careful with the filtering. The class and category of the object must be combined to accurately target user objects.
There are other ways to filter, too. In this recipe, we’ve used an efficient filtering method while keeping the commands easy to use. However, in large environments, using LDAP filtering can be a bit faster than standard filtering. The following command counts all of the user objects in the current domain and uses LDAP filtering:
Get-ADObject -LDAPFilter "(&(objectCategory=Person)(objectClass=User)) " | Measure-Object | FL Count
From the menu, select Options→Controls.
Under Load Predefined, select the control you want to use. The control should automatically be added to the list of Active Controls.
Under Value, enter the value for the control.
Under Control Type, select whether the control is server-side or client-side.
Check the box beside Critical if the control is critical.
Click OK.
At this point, you will need to invoke the LDAP operation (such as Search) that will use the control. In the dialog box for any operation, click Options and ensure that the Extended option is checked before initiating the operation.
LDAP controls were defined in the LDAPv3 specification as a way to extend LDAP and its operations without breaking the protocol. Many controls have been implemented, some of which are used when searching the directory (e.g., paged searching, Virtual List View [VLV], finding deleted objects, and attribute scoped query), and some are needed to do certain modifications to the directory (e.g., cross-domain object moves, tree delete, and permissive modify). Controls can be marked as critical, which means they must be processed with the request or an error is returned. If an unsupported control is not flagged as critical, the server can continue to process the request and ignore the control.
The complete list of controls supported by Active Directory is included in Table 4-2.
Table 4-2. LDAP controls supported by Active Directory
Name | OID | Description |
---|---|---|
Permit No-Opt Modify | 1.2.840.113556.1.4.1413 | Allows duplicate adds of the same value for an attribute or deletion of an attribute that has no values to succeed (normally, it would fail in that situation). |
Return Deleted Objects | 1.2.840.113556.1.4.417 | Used to inform the server to return any deleted objects that matched the search criteria. |
Cross Domain Move | 1.2.840.113556.1.4.521 | Used to move objects between domains. |
Set change notifications | 1.2.840.113556.1.4.528 | Used by clients to register for notification of when changes occur in the directory. |
Delayed Write | 1.2.840.113556.1.4.619 | Used to inform the server to return after directory modifications have been written to memory, but before they have been written to disk. This can speed up processing of a lot of modifications. |
Security Descriptor Flags | 1.2.840.113556.1.4.801 | Used to pass flags to the server to control certain security descriptor options. |
Subtree Delete | 1.2.840.113556.1.4.805 | Used to delete portions of the directory tree, including any child objects. |
Verify Name Existence | 1.2.840.113556.1.4.1338 | Used to target a specific GC server that is used to verify DN-valued attributes that are processed during addition or modification operations. |
No referrals generated | 1.2.840.113556.1.4.1339 | Informs the server not to generate any referrals in a search response. |
Domain or phantom scope | 1.2.840.113556.1.4.1340 | Used to pass flags to the server to control search options. |
Search Stats | 1.2.840.113556.1.4.970 | Used to return statistics about an LDAP query. See Using the STATS Control to View LDAP Query Statistics for an example. |
Attribute Scoped Query | 1.2.840.113556.1.4.1504 | Used to force a query to be based on a specific DN-valued attribute. This control is new to Windows Server 2003. See Searching for Objects in a Domain for an example. |
Extended DN | 1.2.840.113556.1.4.529 | Used to return an object’s GUID and SID (for security principals) as part of its distinguished name. |
Quota SID | 1.2.840.113566.1.4.1852 | Used to pass the SID of a
security principal in order to query constructed attributes such
as |
Paged Results | 1.2.840.113556.1.4.319 | Instructs the server to return search results in “pages.” |
DIRSYNC | 1.2.840.113556.1.4.841 | Used to find objects that have changed over a period of time. |
Server-side Sort Request | 1.2.840.113556.1.4.473 | Used to inform the server to sort the results of a search. |
Server-side Sort Response | 1.2.840.113556.1.4.474 | Returned by the server in response to a sort request. |
Show deactivated links | 1.2.840.113556.1.4.2065 | Used to request deactivated links to be included in a search. |
Show deleted objects | 1.2.840.113556.1.4.417 | Used to request deleted objects to be included in a search. |
VLV Request | 2.16.840.1.113730.3.4.9 | Used to request a virtual list view of results from a search. This control is new to Windows Server 2003. |
VLV Response | 2.16.840.1.113730.3.4.10 | Response from a server returning a virtual list view of results from a search. This control is new to Windows Server 2003. |
Searching for Objects in a Domain; Using the STATS Control to View LDAP Query Statistics; RFC 2251 (Lightweight Directory Access Protocol [v3]) for a description of LDAP controls; 3.1.1.3.4.1 LDAP Extended Controls; MSDN: Using Controls
You want to perform an LDAP bind using a concurrent bind, also known as a fast bind. Concurrent binds are typically used in situations where you need to authenticate a lot of users, and either those users do not need to directly access the directory or the directory access is done with another account.
From the menu, select Connection→Connect.
For Server, enter the name of a DC.
For Port, enter 389.
Click OK.
From the menu, select Options→Connection Options.
Under Option Name:, select LDAP_OPT_FAST_CONCURRENT_BIND.
Click the Set button. Then click the Close button.
From the menu, select Connection→Bind.
Accept the default and bind as the currently logged on user or select the option to bind with credentials and then enter the credentials.
Click OK.
Unlike simple binding, concurrent binding does not generate a security token or determine a user’s group memberships during the authentication process. It determines only whether the authenticating user has a valid enabled account and password, which makes it much faster than a typical bind. This is usually used programmatically for AD-enabled applications to improve the speed of AD authentication; it’s not something that you’ll typically do on the fly. Concurrent binding is implemented as a session option that is set after you establish a connection to a domain controller, but before any bind attempts are made. After the option has been set, any bind attempt made with the connection will be a concurrent bind.
There are a couple of caveats when using concurrent binds. First,
you cannot enable signing or encryption, which means that all data for
concurrent binds will be sent over the network in clear text. Second,
because the user’s security token is not generated, access to the
directory is done anonymously and access restrictions are based on the
ANONYMOUS LOGON
principal.
It is worth mentioning that there is another type of fast bind
that is completely different from the procedure just described. This
fast bind is implemented within ADSI, and it simply means that when you
fast-bind to an object, the objectClass
attribute for the object is not
retrieved; therefore, the object-specific IADs
class interfaces are not available. For example, if you bind to a
user object using an ADSI fast bind, then only the basic IADs
interfaces will be available, not the
IADsUser
interfaces.
This is the complete list of interfaces that are available for objects retrieved with fast binds:
IADs
IADsContainer
IDirectoryObject
IDirectorySearch
IADsPropertyList
IADsObjectOptions
ISupportErrorInfo
IADsDeleteOps
You must use the IADsOpenDSObject::OpenDSObject
interface to
enable fast binds. If you call IADsContainer::GetObject
on a child object of
a parent you used a fast bind with, the same fast bind behavior applies.
Unlike concurrent binds, ADSI fast binds do not impose any restrictions
on the authenticating user. This means that the object-specific IADs
interfaces will not be available. Also,
no check is done to verify the object exists when you call OpenDSObject
.
ADSI fast binds are useful when you need to make a lot of updates
to objects that you know exist (perhaps from an ADO query that returned
a list of DNs) and you do not need any IADs
-specific interfaces. Instead of two trips
over the network per object binding, there would be only one.
From the menu, select Connection→Connect.
For Server, enter the name of a domain controller (or leave it blank to do a serverless bind).
For Port, enter 389.
Click OK.
From the menu, select Connection→Bind.
Accept the default and bind as the currently logged on user or select the option to bind with credentials and then enter the credentials.
Click OK.
From the menu, select Browse→Search.
For BaseDN, enter the GUID of the object that you’re searching for in the following format:
<GUID=758A39F4A44A0C48A16016457C1AE9E9>
For Scope, select the appropriate scope.
For Filter, enter an LDAP filter.
Each object in Active Directory has a GUID associated with it,
stored in the objectGUID
attribute.
The GUID is, for most purposes, a unique identifier that retains its
value even if an object is updated, renamed, or moved. This makes the
GUID the preferable means of binding to an object, rather than
hardcoding a reference to an object name that might change or by using a
potentially complex LDAP query.
“‘GUIDs’ or
‘Having unique in the name doesn’t make it so...’” for a more
in-depth discussion of the objectGUID
attribute; MSDN: IADs.GUID; MSDN: Using objectGUID to Bind to an Object;
Connecting to a Well-Known GUID
From the menu, select Connection→Connect.
For Server, enter the name of a domain controller (or leave it blank to do a serverless bind).
For Port, enter 389.
Click OK.
From the menu, select Connection→Bind.
Accept the default and bind as the currently logged on user or select the option to bind with credentials and then enter the credentials.
Click OK.
From the menu, select View→Tree.
For the DN, enter:
<WKGUID=
<WKGUID>,<DomainDN>
>where
<WKGUID>
is the well-known GUID that you want to connect to, and<DomainDN>
is the distinguished name of a domain.Click OK. In the lefthand menu, you can now browse the container corresponding to the well-known GUID that you specified.
To enumerate the well-known GUIDs in the Domain NC, use the following syntax:
> adfind -default -s base wellknownObjects
To display the WKGUIDs in the Configuration NC, replace –default
with –config
in the previous syntax.
To connect to a well-known GUID in the Domain NC using AdFind, use the following syntax:
> adfind -b "<WKGUID=<WKGUID>,<DomainDN>
>" -s base -dn
Note
Because of additional security settings attached to the
Deleted
Objects
container, if you specify
the GUID you must also use the –showdel
switch in AdFind.
The Domain NC in Active Directory contains a number of well-known
GUIDs that correspond to containers that exist in every AD
implementation. These GUIDs are stored as wellKnownObjects
attributes within the
<DomainDN>
object, and they allow
administrators and developers to consistently connect to critical
containers even if they are moved or renamed. The
<DomainDN>
container possesses the
following objects that correspond to well-known GUIDs:
cn=NTDS Quotas,
<DomainDN>
cn=Microsoft,cn=Program Data,
<DomainDN>
cn=Program Data,
<DomainDN>
cn=ForeignSecurityPrincipals,
<DomainDN>
cn=Deleted Objects,
<DomainDN>
cn=Infrastructure,
<DomainDN>
cn=LostAndFound,
<DomainDN>
cn=System,
<DomainDN>
OU=Domain Controllers,
<DomainDN>
cn=Computers,
<DomainDN>
cn=Users,
<DomainDN>
The Configuration NC adds these additional WKGUIDs:
cn=NTDS Quotas,cn=Configuration,
<ForestRootDN>
cn=LostAndFoundConfig,cn=Configuration,
<ForestRootDN>
cn=Deleted Objects,cn=Configuration,
<ForestRootDN>
From the menu, select Connection→Connect.
For Server, enter the name of a domain controller (or leave it blank to do a serverless bind).
For Port, enter 389.
Click OK.
From the menu, select Connection→Bind.
Accept the default and bind as the currently logged on user or select the option to bind with credentials and then enter the credentials.
Click OK.
From the menu, select Browse→Search.
For BaseDN, type the base distinguished name where the search will start. (You can leave this blank if you wish to connect to the Domain NC as the base DN.)
For Scope, select the appropriate scope.
For Filter, enter an LDAP filter.
Click Run.
To run a query using the built-in DSQuery tool, use the following syntax:
> dsquery *<BaseDN>
-scope<Scope>
-filter "<Filter>
" -attr "<AttrList>
"
To retrieve the SAM account name for all user objects within the adatum.com domain, for example, use the following syntax:
> dsquery * dc=adatum,dc=com -filter "(&(objectclass=user)(objectcategory=person))" -attr sAMAccountName
To run a query using adfind
,
use the following syntax:
> adfind -b<BaseDN>
-s<Scope>
-f<Filter> <Attributes>
Querying for SAM account names of user objects with adfind
takes the following syntax:
> adfind -b dc=adatum,dc=com -f "(&(objectclass=user)(objectcategory=person))" sAMAccountName
Note
Both DSQuery and AdFind assume a default search scope of subtrees; you need only to specify the search scope if you want to use a different one.
Most tools that can be used to search Active Directory require a basic understanding of how to perform LDAP searches using a base DN, search scope, and search filter, as described in RFC 2251 and RFC 2254. The base DN is where the search begins in the directory tree. The search scope defines how far down in the tree to search from the base DN. The search filter is a prefix notation string that contains equality comparisons of attribute and value pairs.
The scope can be base
, onelevel
(or one
), or subtree
(or sub
). A base
scope will match only the base DN,
onelevel
will match only objects that
are contained directly under the base DN, and subtree
will match everything from the base DN
and any objects beneath it.
Note
There are no LDAP query scopes that will walk backward “up” the tree.
The search filter syntax is a powerful way to represent simple and
complex queries. For example, a filter that matches all of the user
objects would be (&(objectclass=user)(objectcategory=Person))
.
For more information on filters, see RFC 2254.
To customize the list of attributes returned for each matching object, look at the GUI discussion in Viewing the Attributes of an Object.
Viewing the Attributes of an Object for viewing attributes of objects; Searching the Global Catalog for setting advanced ADO options; RFC 2251 (Lightweight Directory Access Protocol [v3]); RFC 2254 (Lightweight Directory Access Protocol [v3]); “LDAP Query Basics”
From the menu, select Connection→Connect.
For Server, enter the name of a global catalog server.
For Port, enter 3268.
Click OK.
From the menu, select Connection→Bind.
Accept the default and bind as the currently logged on user or select the option to bind with credentials and then enter the credentials.
Click OK.
From the menu, select Browse→Search.
For BaseDN, type the base distinguished name of where to start the search.
For Scope, select the appropriate scope.
For Filter, enter an LDAP filter.
Click Run.
The global catalog facilitates forest-wide searches. When you perform a normal LDAP search over port 389, you are searching against a particular partition within Active Directory, whether that is the Domain naming context, Configuration naming context, Schema naming context, or an application partition. If you have multiple domains in your forest, this type of search will not search against all domains; it will search only the domain that you specify.
The global catalog, by contrast, contains a subset of the attributes for all objects in the forest (excluding objects in application partitions). Think of it as a subset of all the naming contexts combined. Every object in the directory will be contained in the global catalog (except for objects contained within application partitions), but only some of the attributes of those objects will be available. For that reason, if you perform a global catalog search and do not get values for attributes you were expecting to, make sure those attributes are included in the global catalog, also known as the partial attribute set (PAS). See Modifying the Set of Attributes Stored on a Global Catalog for more information on adding information to the PAS. As an alternative, you can query a DC within the domain containing the object to return a list of all attributes configured for that object. Note that the Active Directory Administrative Center provides a method to easily change the scope of a search to be a global catalog search.
The only difference between this solution and the one in Searching for Objects in a Domain is that the port has changed to 3268, which is the standard GC port.
The only difference between this solution and the one in Searching for Objects in a Domain, both for DSQuery and
AdFind, is the addition of the -gc
flag.
Searching for Objects in a Domain for searching for objects; Modifying the Set of Attributes Stored on a Global Catalog
Your search is returning exactly 1,000 objects, which is only a subset of the objects you expected, and you want it to return all matching objects.
You might notice, when using some tools, that searches with large numbers of matches stop displaying after 1,000. By default, domain controllers return a maximum of 1,000 entries from a search unless paging is enabled. This is done to prevent queries from consuming excessive resources on domain controllers by retrieving the results all at once instead of in pages or batches. The following examples are variations of Searching for Objects in a Domain, which will show how to enable paging and return all matching entries.
From the menu, select Connection→Connect.
For Server, enter the name of a domain controller (or leave it blank to do a serverless bind).
For Port, enter 389.
Click OK.
From the menu, select Connection→Bind.
Accept the default and bind as the currently logged on user or select the option to bind with credentials and then enter the credentials.
Click OK.
From the menu, select Browse→Search.
For BaseDN, type the base distinguished name of where the search will start. (You can leave this blank if you wish to connect to the domain NC as the base DN.)
For Scope, select the appropriate scope.
For Filter, enter an LDAP filter.
Click Options to customize the options for this query.
For “Time limit,” enter a value such as 120.
For “Size limit,” enter the number of objects to be returned with each page (e.g., 1,000).
Under Search Call Type, select Paged.
Click OK and then Run to perform the query. A page of results (i.e., 1,000 entries) will be displayed each time you click Run until all results have been returned.
Paged searching support is implemented via an LDAP control. LDAP controls were defined in RFC 2251 and the Paged control in RFC 2696. Controls are extensions to LDAP that were not built into the protocol, so not all directory vendors support the same ones.
Note
In Active Directory, you can change the default maximum page size of 1,000 by modifying the LDAP query policy. See Modifying the Default LDAP Query Policy for more information.
Active Directory will return a maximum of 256 KB of data even when paged searching is enabled. This value is defined in the LDAP query policy and can be modified like the maximum page size (see Modifying the Default LDAP Query Policy).
A word of caution when using LDP to display a large number of entries: by default, only 2,048 lines will be displayed in the right pane. To change that value, go to Options→General and change the number of lines under Buffer Size to a larger number. Note that newer tools aren’t as limited as some of the tools that have been around a long time. For example, the Active Directory Administrative Center displays up to 20,000 objects in a search by default.
The only difference between this solution and the one in Searching for Objects in a Domain is the addition of the
-limit 0
flag. With -limit
set to 0
, paging will be enabled according to the
default LDAP query policy; matching objects will be returned within
those parameters. If -limit
is not specified, a maximum
of 100 entries will be returned.
Note
AdFind enables paged searches by default; it will return any number of objects from a query without any modification.
Searching for Objects in a Domain for searching for objects; Modifying the Default LDAP Query Policy for viewing the default LDAP policy; RFC 2251 (Lightweight Directory Access Protocol [v3]); RFC 2696 (LDAP Control Extension for Simple Paged Results Manipulation)
You want to perform a search using an individual value within a multivalued attribute as part of the search criteria. An attribute-scoped query can do this in a single query, instead of the previous method, which required multiple queries.
Follow the steps in Using LDAP Controls to enable an LDAP control.
Select the Attribute Scoped Query control.
For Value, enter the multivalued attribute name (e.g.,
member
).Click the “Check in” button.
Click OK.
From the menu, select Browse→Search.
For BaseDN, type the DN of the object that contains the multivalued attributes.
For Scope, select Base.
For Filter, enter an LDAP filter to match against the objects that are part of the multivalued DN attribute.
Click Run.
Warning
Attribute-scoped queries can only be performed using a Base scope.
When dealing with group
objects, you may have encountered the problem where you wanted to search
against the members of a group to find a subset or to retrieve certain
attributes about each member. This normally involved performing a query
to retrieve all of the members, and additional queries to retrieve
whatever attributes you needed for each member. This was less than
ideal, so an alternative was developed.
With an attribute-scoped query, you can perform a single query
against the group
object and return
whatever properties you need from the member’s object, or return only a
subset of the members based on certain criteria. Let’s look at the LDAP
search parameters for an attribute-scoped query:
- Attribute-scoped query control value
The value to set for this control should be the DN attribute that you want to iterate over (for example,
member
).- Base DN
This must be the DN of the object that contains the DN attribute (e.g.,
cn=Domain Admins,cn=users,dc=adatum,dc=com
).- Scope
This must be set to
Base
to query only thegroup
object itself.- Filter
The filter will match against objects defined in the Control Value. For example, a filter of
(objectClass=computer)
would matchcomputer
objects only. You can also use any other attributes that are available with those objects. The following filter would match allcomputer
objects that have aDescription
attribute equal to “Sales”:(&(objectclass=computer)(Description=Sales))
- Attributes
This should contain the list of attributes to return for the objects matched in the DN attribute.
When performing an attribute-scoped query against a member attribute, it’s important to remember that primary group membership is handled as a special case; as such you may experience unpredictable results in this situation.
Using LDAP Controls; MSDN: Performing an Attribute Scoped Query
You want to search against an attribute that contains a bit flag, which requires you to use a bitwise filter to perform the search.
From the menu, select Connection→Connect.
For Server, enter the name of a domain controller (or leave it blank to do a serverless bind).
For Port, enter 389.
Click OK.
From the menu, select Connection→Bind.
Accept the default and bind as the currently logged on user or select the option to bind with credentials and then enter the credentials.
Click OK.
From the menu, select Browse→Search.
For Base DN, type the base distinguished name of where the search will start. (You can leave this blank if you wish to connect to the domain NC as the base DN.)
For Scope, select the appropriate scope.
For the Filter, enter the bitwise expression, such as the following, which will find all universal groups:
(&(objectCategory=group)(groupType:1.2.840.113556.1.4.804:=8))
Click Run.
The following query finds universal groups in the adatum.com domain by using a bitwise AND filter:
> dsquery * dc=adatum,dc=com -scope subtree -attr "name" -filter"(&(objectclass=group)(objectCategory=group)(groupType:1.2.840.113556.1.4.804:=8) )"
The following query finds disabled user accounts in the adatum.com domain by using a bitwise AND filter:
> dsquery * dc=adatum,dc=com -attr name -scope subtree -filter "(&(objectclass=user)(objectcategory=person)(useraccountcontrol:1.2.840.113556.1.4. 803:=2))"
You can also perform queries that use bitwise filters using AdFind. The following will find all disabled user accounts in the adatum.com domain:
> adfind -default -bit -f useraccountcontrol:AND:=2
Similarly, the following will return all universal groups in the adatum.com domain using a bitwise filter:
> adfind -default -bit -f groupType:AND:=8
Many attributes in Active Directory are composed of bit flags. A
bit flag is often used to encode properties about an object into a
single attribute. For example, the groupType
attribute on group
objects is a bit flag that is used to
determine the group scope and type.
The userAccountControl
attribute on user
and computer
objects is used to describe a whole
series of properties, including account status (i.e., enabled or
disabled), account lockout, password not required, smartcard
authentication required, and so on.
The searchFlags
and systemFlags
attributes on attributeSchema
objects define, among other
things, whether an attribute is constructed, indexed, and included as
part of Ambiguous Name Resolution (ANR).
To search against these types of attributes, you need to use bitwise search filters. There are two types of bitwise search filters you can use, one that represents a logical OR and one that represents a logical AND. This is implemented within a search filter as a matching rule. A matching rule is simply a way to inform the LDAP server (in this case, a domain controller) to treat part of the filter differently. Here is an example of what a matching rule looks like:
(userAccountControl:1.2.840.113556.1.4.803:=514)
The format is
(attributename:MatchingRuleOID:=value
),
though AdFind allows you to use an easier syntax for bitwise queries. As
mentioned, there are two bitwise matching rules, which are defined by
OIDs. The logical AND matching rule OID is 1.2.840.113556.1.4.803, and
the logical OR matching rule OID is 1.2.840.113556.1.4.804. These OIDs
instruct the server to perform special processing on the filter. A
logical OR filter will return success if any bit specified by
value
is stored in
attributename
. Alternatively, the logical AND
filter will return success if all bits specified by
value
match the value of
attributename
. Perhaps an example will help
clarify this.
To create a normal user account, you have to set userAccountControl
to 514. The number 514 was
calculated by adding the normal user account flag of 512 together with
the disabled account flag of 2 (512 + 2 = 514). If you use the following
logical OR matching rule against the 514 value, as shown here:
(useraccountcontrol:1.2.840.113556.1.4.804:=514)
then all normal user accounts (flag 512) OR disabled accounts
(flag 2) would be returned. This would include enabled user accounts
(from flag 512), disabled computer accounts (from flag 2), and disabled
user accounts (from flag 2). In the case of userAccountControl
, flag 2 can apply to both
user and computer accounts, which is why both would be included in the
returned entries.
One of the benefits of bitwise matching rules is that they allow you to combine a bunch of comparisons into a single filter. In fact, it may help to think that the OR filter could also be written using two expressions:
(|(useraccountcontrol:1.2.840.113556.1.4.804:=2) (useraccountcontrol:1.2.840.113556.1.4.804:=512))
Just as before, this will match userAccountControl
attributes that contain
either the 2 or 512 flag; we’re performing two OR operations against the
same value, first ORing the value against 2, then against 512.
For the logical AND operator, similar principles apply. Instead of
any of the bits in the flag being a possible match,
all of the bits in the flag must match for it to
return a success. If the userAccountControl
example was changed to use
logical AND, it would look like this:
(useraccountcontrol:1.2.840.113556.1.4.803:=514)
In this case, only normal user accounts that are also disabled
would be returned. The same filter could be rewritten using the &
operator instead of |
as in the following:
(&(useraccountcontrol:1.2.840.113556.1.4.803:=2) (useraccountcontrol:1.2.840.113556.1.4.803:=512))
An important subtlety to note is that when you are comparing only a single bit-flag value, the logical OR and logical AND matching rules would return the same result. So, if you wanted to find any normal user accounts, you could search on the single bit flag of 512 using either of the following:
(useraccountcontrol:1.2.840.113556.1.4.803:=512) (useraccountcontrol:1.2.840.113556.1.4.804:=512)
Searching on a bitwise operator in PowerShell is done using the
appropriate LDAP filter, as you can see. In other chapters we will
look at individual AD cmdlets that mask the bitwise search into a more
human-readable operation, such as the Enable-ADAccount
and Disable-ADAccount
cmdlets.
In each solution in this recipe, an example of adding a user object is shown. Modify the examples as needed to include whatever class and attributes you need to create.
If an entry for the naming context you want to browse is not already displayed, do the following:
Right-click on ADSI Edit in the right pane and click “Connect to.”
Fill in the information for the naming context, container, or OU you want to add an object to. Click on the Advanced button if you need to enter alternate credentials.
In the left pane, browse to the container or OU you want to add the object to. Once you’ve found the parent container, right-click on it and select New→Object.
Under Select a Class, select user.
For the
cn
, enterjsmith
and click Next.For
sAMAccountName
, enterjsmith
and click Next.Click the More Attributes button to enter additional attributes.
Click Finish.
Create an LDAP Data Interchange Format (LDIF) file called create_object.ldf with the following contents:
dn: cn=jsmith,cn=users,dc=adatum,dc=com changetype: add objectClass: user samaccountname: jsmith
Then run the following command:
> ldifde -v -i -f create_object.ldf
It is also worth noting that you can add a limited number of
object types with the dsadd
command. Run dsadd /?
from a
command line for more details.
You can also create objects using AdMod; to create a new user object in the adatum.com domain use the following syntax:
> admod -b "cn=Joe Smith,cn=users,dc=adatum,dc=com" objectclass::user samaccountname::jsmith -add
To create an object in Active Directory, you have to specify the
objectClass
, RDN value, and any other
mandatory attributes that are not automatically set by Active Directory.
Some of the automatically generated attributes include objectGUID
, instanceType
, and objectCategory
.
In the jsmith
example, the
object class was user
, the RDN value
was jsmith
, and the only other
attribute set was sAMAccountName
.
Admittedly, this user object is unusable in its current state because it
will be disabled by default and no password was set, but it should give
you an idea of how to create an object. In the case of a user object,
you’ll need to configure a password that meets any existing password
complexity requirements before enabling the user.
Other tools, such as Active Directory Administrative Center and AD Users and Computers, could be used to do the same thing, but ADSI Edit is useful as a generic object editor.
One attribute that you will not be able to set via ADSI Edit is
the password (unicodePwd
attribute). It is stored in binary form and needs to be edited using a
secure connection. If you want to set the password for a user through
a GUI, you can do it with the AD Users and Computers snap-in or Active
Directory Administrative Center.
For more on ldifde, see Exporting Objects to an LDIF File.
With DSAdd, you can set numerous attributes when creating an object. The downside is that you can create only the following object types: computer, contact, group, OU, quota, and user.
Exporting Objects to an LDIF File; Importing Objects Using an LDIF File for importing objects with LDIF; MSDN: IADsContainer::GetObject; MSDN: IADsContainer::Create; MSDN: IADs::Put; MSDN: IADs::SetInfo
The following example sets the employeeID
attribute for a user object.
In the bottom-right pane, enter the search criteria of the desired object and then click the Search button.
In the search results, locate the object, right-click it, and then click Properties.
Scroll down to the Extensions section and then click the Attribute Editor tab.
Scroll down and click the
employeeID
attribute and then click the Edit button.Enter the value and then click OK.
Click OK again to close the object properties.
Create an LDIF file called modify_object.ldf with the following contents:
dn: cn=jsmith,cn=users,dc=adatum,dc=com changetype: modify replace: employeeID employeeID: 17320 -
Then run the following command:
> ldifde -v -i -f modify_object.ldf
To modify an object using AdMod, you’ll use the following general syntax:
> admod -b <ObjectDN> <attribute>:<operation>:<value>
For example, you can add a description to a user object using the following syntax:
> admod -b cn="Joe Smith,cn=Users,dc=adatum,dc=com" description::Consultant
You can modify a limited number of object types with the
dsmod
command. Run dsmod /?
from a command line for more
details.
For more on ldifde, see Exporting Objects to an LDIF File.
As of the publication of this book, the only types of objects you can modify with DSMod are the following: computer, contact, group, OU, server, quota, partition, and user.
As you saw in this recipe, the basic format of the AdMod command when used to modify an attribute is as follows:
> admod -b <ObjectDN> <attribute>:<operation>:<value>
The value used for <operation>
can be any one of the following:
<blank>
Updates the attribute with the new value. (In practical terms, this leads to a syntax of
<attribute>
::
<value>
, with nothing included between the two colons.)+
Adds a value to an attribute.
−
Clears an attribute.
++
Adds multiple values to an attribute.
−−
Removes multiple values from an attribute.
Note
To change a user’s password via AdMod, encrypt the connection
by using the -kerbenc
switch and
then modify the unicodepwd
attribute.
You want to safely modify an attribute that contains a bit flag,
without blindly overwriting its existing contents. The solutions in this
recipe modify a new attribute named adatum-UserProperties
that was previously
added to the schema.
' This code safely modifies a bit flag attribute ' ------ SCRIPT CONFIGURATION ------ strObject = "<ObjectDN>
" ' e.g. cn=jsmith,cn=users,dc=adatum,dc=com strAttr = "<AttrName>
" ' e.g. adatum-UserProperties boolEnableBit =<TRUEorFALSE>
' e.g. FALSE intBit =<BitValue>
' e.g. 16 ' ------ END CONFIGURATION -------- set objObject = GetObject("LDAP://" & strObject) intBitsOrig = objObject.Get(strAttr) intBitsCalc = CalcBit(intBitsOrig, intBit, boolEnableBit) if intBitsOrig <> intBitsCalc then objObject.Put strAttr, intBitsCalc objObject.SetInfo WScript.Echo "Changed " & strAttr & " from " & intBitsOrig &↵ " to " & intBitsCalc else WScript.Echo "Did not need to change " & strAttr & " (" & intBitsOrig & ")" end if Function CalcBit(intValue, intBit, boolEnable) CalcBit = intValue if boolEnable = TRUE then CalcBit = intValue Or intBit else if intValue And intBit then CalcBit = intValue Xor intBit end if end if End Function
To set the adatum-UserProperties
value using
PowerShell, use the following example script:
$user = Get-ADObject "cn=jsmith,cn=users,dc=adatum,dc=com" -Properties adatum-UserProperties if (!$user.adatum-UserProperties) { Set-ADObject $user -Add @{"adatum-UserProperties"=4} Write-Host "Changed from NULL to 4." } else { $value = $user.adatum-UserProperties + 4 Set-ADObject $user -Replace @{"adatum-UserProperties"=$value} Write-Host "Changed value from" $user.adatum-UserProperties "to" $value"." }
Searching with a Bitwise Filter described how
to search against attributes that contain a bit flag, which is used to
encode various settings about an object in a single attribute. As a
quick recap, you need to use a logical OR operation to match any bits
being searched against, and a logical AND to match a specific set of
bits. If you want to set an attribute that is a bit flag, you need to
take special precautions to ensure that you don’t overwrite an existing
bit. Let’s consider an example. Adatum wants to secretly store some
politically incorrect information about their users, such as whether the
user is really old or has big feet. They don’t want to create attributes
such as adatum-UserHasBigFeet
, so
they decide to encode the properties in a single bit-flag attribute.
They decide to call the attribute adatum-UserProperties
with the possible bit
values shown in Table 4-3.
Table 4-3. Sample bit-flag attribute values
Value | Description |
---|---|
1 | User is overweight. |
2 | User is very tall. |
4 | User has big feet. |
8 | User is very old. |
After they extend the schema to include the new attribute, Adatum
needs to initially populate the attribute for all their users. To do so
they can simply logically OR the values together that apply to each
user. So, if settings 4 and 8 apply to the jsmith
user, his adatum-UserProperties
would be set to 12 (4 OR
8). No big deal so far. The issue comes in when they need to modify the
attribute in the future.
Note
You will, however, find that searching for information based on a bit-flag attribute is not terribly efficient. This is because bit flags cannot be indexed; you need to calculate the value for every object populated with the bit-flag attribute in question.
They later find out that jsmith
was a former basketball player and is 6′8″. They need to set the 2 bit
(for being tall) in his adatum-UserProperties
attribute. To set the 2
bit they need to first determine whether it has already been set. If it
has already been set, then there is nothing to do. If the 2 bit hasn’t
been set, they need to logical OR 2 with the existing value of jsmith
’s adatum-UserProperties
attribute. If they
simply set the attribute to 2, it would overwrite the 4 and 8 bits that
had been set previously. In the VBScript solution, they could use the
CalcBit
function to determine the new
value:
intBitsCalc = CalcBit(intBitsOrig, 2, TRUE)
The result would be 14 (12 OR 2).
The same logic applies if they want to remove a bit, except the XOR logical operator is used.
Warning
Active Directory contains numerous bit-flag attributes, most
notably options
(which is used on
several different object classes) and userAccountControl
(which is used on
user
objects). We do not recommend
blindly setting those attributes unless you know what you are doing.
It is preferable to use a script from this recipe so that it
calculates the new value based on the existing value.
You should note that it’s certainly possible to modify bitwise attributes using a GUI tool like ADSI Edit or a command-line tool like DSMod. However, it will require a certain amount of manual effort, as you’ll first need to make note of the existing attribute value and then calculate the new value using a calculator or some other method. The VBScript solution presented here simply automates that process by performing the lookup and calculations for you.
Searching with a Bitwise Filter for searching with a bitwise filter
In each solution in this recipe, an example of adding the custom
adatum-SalesUser
auxiliary class to
the jsmith
user object will be
described.
If an entry for the naming context you want to browse is not already displayed, do the following:
Right-click on ADSI Edit in the right pane and click “Connect to.”
Fill in the information for the naming context, container, or OU you want to add an object to. Click the Advanced button if you need to enter alternate credentials.
In the left pane, browse to the container or OU that contains the object you want to modify. Once you’ve found the object, right-click on it and select Properties.
Edit the values for the
objectClass
attribute.For “Value to add,” enter
adatum-SalesUser
.Click Add.
Click OK twice.
Create an LDIF file called dynamically_link_class.ldf with the following contents:
dn: cn=jsmith,cn=users,dc=adatum,dc=com changetype: modify add: objectClass objectClass: adatum-SalesUser -
Then run the following command:
> ldifde -v -i -f dynamically_link_class.ldf
Alternatively, you can use AdMod as follows:
> admod -b<ObjectDN>
objectClass:+:<Dynamic Object Class>
Dynamically linking an auxiliary class to an object is an easy way to use new attributes without modifying the existing object class definition in the schema.
A situation in which it makes more sense to dynamically link
auxiliary classes than to link them statically is when several
organizations or divisions within a company maintain their own user
objects and want to add new attributes to
the user
class.
It is also worth mentioning that extensive use of dynamically
linked auxiliary classes can lead to problems. If several groups are
using different auxiliary classes, it might become hard to determine
what attributes you can expect on your user
objects. Essentially, you could end up
with many variations of a user class that each group has implemented
through the use of dynamic auxiliary classes. For this reason, use of
dynamic auxiliary classes should be closely monitored. In addition, some
tools that access Active Directory may not work properly with auxiliary
classes.
Modifying an Object for modifying an object
You want to create an object that is automatically expired and removed from the directory after a period of time.
Click Connection→Connect and click OK.
Click Connection→Bind.
Accept the default and bind as the currently logged on user or select the option to bind with credentials and then enter the credentials.
Click View→Tree. Enter the DN of the parent container of the object you want to create and then click OK.
Click Browse→Add Child. The Add window will appear.
In the DN text box, enter the DN of the new object.
In the Attribute text box, enter
objectClass
. In the Values text box, enter the object class of the object you are creating, such as'user'
. Click Enter. In the Values text box, type
and click Enter.dynamicObject
In the Attribute text box, type
. In the Values text box, enter the time to live (TTL) of the object you are creating, such asentryTTL
'3600'
. Click Enter.Enter any other attributes and values that you wish to populate in the Attribute and Values text boxes.
Click Run.
The ability to create dynamic objects allows you to create objects
that have a limited lifespan before they are automatically removed from
the directory. To create a dynamic object, you simply need to specify
the objectClass
to have a value of
dynamicObject
in addition to its
structural objectClass
(e.g.,
user
) value when instantiating the
object. The entryTTL
attribute can
also be set to the number of seconds before the object is automatically
deleted. If entryTTL
is not set, the
object will use the dynamicObjectDefaultTTL
attribute specified in
the domain. The entryTTL
cannot be
lower than the dynamicObjectMinTTL
for the domain. See Modifying the Default TTL Settings for Dynamic Objects for more information
on how to view and modify these default values.
Dynamic objects have a few special properties worth noting:
A static object cannot be turned into a dynamic object. The object must be marked as dynamic when it is created.
Dynamic objects cannot be created in the Configuration NC and Schema NC.
Dynamic objects do not leave behind tombstone objects.
Dynamic objects that are containers cannot have static child objects.
A dynamic container will not expire prior to any child objects contained within it. If the dynamic container has a lower TTL value than any of the children, once the container’s TTL expires it will be reset to the highest TTL value of the children plus one second.
Refreshing a Dynamic Object for refreshing a dynamic object; Modifying the Default TTL Settings for Dynamic Objects for modifying the default dynamic object properties
You want to refresh a dynamic object to keep it from expiring and getting deleted from Active Directory.
In each solution in this recipe, an example of adding a user
object is used. Modify the examples as
needed to refresh whatever object is needed.
From the menu, select Connection→Connect.
For Server, enter the name of a domain controller (or leave it blank to do a serverless bind).
For Port, enter 389.
Click OK.
From the menu, select Connection→Bind.
Accept the default and bind as the currently logged on user or select the option to bind with credentials and then enter the credentials.
Click OK.
Select Browse→Modify.
For DN, enter the DN of the dynamic object you want to refresh.
For Attribute, enter
entryTTL
.For Values, enter the new time to live (TTL) for the object in seconds.
Under Operation, select Replace.
Click Enter.
Click Run.
Create an LDIF file called refresh_dynamic_object.ldf with the following contents:
dn: cn=jsmith,cn=users,dc=adatum,dc=com changetype: modify replace: entryTTL entryTTL: 1800 -
Then run the following command:
> ldifde -v -i -f refresh_dynamic_object.ldf
You can also use AdMod with the following syntax:
> admod -b<ObjectDN>
entryTTL::<TTL in Seconds>
Dynamic objects expire after their TTL becomes 0
. You can determine when a dynamic object
will expire by looking at the current value of an object’s entryTTL
attribute or by querying msDS-Entry-Time-To-Die
, which contains the
seconds remaining until expiration. If you’ve created a dynamic object
and need to refresh it so that it will not get deleted, you must reset
the entryTTL
attribute to a new
value. There is no limit to the number of times you can refresh a
dynamic object. As long as the entryTTL
value does not reach 0
, the object will remain in Active
Directory.
Modifying an Object for modifying an object; “Dynamic Objects (Windows)”; Creating a Dynamic Object for creating a dynamic object
In each solution in this recipe, we’ll show how to set the
DynamicObjectDefaultTTL
setting to
172800
. Modifying the DynamicObjectMinTTL
can be done in the same
manner.
If an entry for the Configuration naming context is not already displayed, do the following:
Right-click on ADSI Edit in the right pane and click “Connect to.”
Fill in the information for the naming context for your forest. Click on the Advanced button if you need to enter alternate credentials.
In the left pane, browse to the following path under the Configuration naming context: Services→Windows NT→Directory Service.
Right-click
cn=Directory Service
and select Properties.Edit the
msDS-Other-Settings
attribute.Click on
DynamicObjectDefaultTTL=
<xxxxx>
and click Remove.The attribute/value pair should have been populated in the “Value to add” field.
Edit the number part of the value to be
172800
.Click Add.
Click OK twice.
The following ntdsutil
command connects to
<DomainControllerName>
, displays the
current values for the dynamic object TTL settings, sets the DynamicObjectDefaultTTL
to 172800
, commits the change, and displays the
results:
> ntdsutil "config settings" connections "connect to server <DomainControllerName>
" q "show values" "set DynamicObjectDefaultTTL to 172800""commit changes"
"show values" q q
Two configuration settings apply to dynamic objects:
dynamicObjectDefaultTTL
Defines the default TTL that is set for a dynamic object at creation time unless another one is set via
entryTTL
dynamicObjectMinTTL
Defines the smallest TTL that can be configured for a dynamic object
Unfortunately, these two settings are not stored as discrete
attributes. Instead, they are stored as attribute value assertions
(AVAs) in the msDS-Other-Settings
attribute on the cn=DirectoryServices,cn=WindowsNT,cn=Configuration,
<ForestRootDN>
object. AVAs are used occasionally in Active Directory on multivalued
attributes, in which the values take the form of
Setting1=Value1,Setting2=Value2
, and so
on.
For this reason, you cannot simply manipulate AVA attributes as you would another attribute. You have to be sure to add or replace values with the same format, as they existed previously.
You can use ntdsutil in interactive mode or in single-command mode. In this solution, we’ve included all the necessary commands on a single line. You can, of course, step through each command by simply running ntdsutil in interactive mode and entering each command one by one.
Modifying an Object for modifying an object; MSDN: Regular Expression (RegExp) Object
In the bottom-right pane, enter the search criteria of the desired object and then click the Search button.
In the search results, locate the object, right-click it, and then click Move.
In the dialog box, browse to the destination container, click to highlight it, and then click OK to move the object.
Note
You can also move objects by using the ADSI Edit tool or the Active Directory Users and Computers snap-in.
The DSMove utility can work against any type of object (it has
no limitations, as with DSAdd and DSMod). The first parameter is the
DN of the object to be moved. The second parameter is the new parent
container of the object. The -s
parameter can additionally be used to designate a specific server to
work against.
Note
Regardless of the method you use to move objects, you need to ensure that the user who is performing the move has the appropriate permissions to create objects in the destination container and delete objects from the source container.
Renaming an Object; MSDN: IADsContainer::MoveHere
To migrate a computer
object
between domains in the same forest, use the following steps:
Open the ADMT MMC snap-in.
Right-click on the Active Directory Migration Tool folder and select the Computer Migration Wizard.
On the Welcome screen, click Next.
On the Domain Selection page, enter the DNS or NetBIOS name of the source and target domains. Click Next.
On the Computer Selection Option screen, select the option to select computer from the domain and then click Next.
On the Computer Selection screen, click Add and use the object picker to select a computer object. Click OK to return to the Computer Selection screen and then click Next.
On the Organizational Unit Selection screen, enter the destination OU in the new domain and then click Next.
On the Translate Objects screen, specify which objects should have new ACLs applied in the new domain. Select any, none, or all of the following, and then click Next to continue:
Files and folders
Local groups
Printers
Registry
Shares
User profiles
User rights
On the Computer Options screen, click Next to maintain the default reboot time of 5 minutes.
On the Object Property Exclusion screen, select any object properties that you do not want to migrate and then click Next.
On the Conflict Management screen, click Next to accept the default that will not migrate the computer if there is a conflict.
On the Completing the Computer Migration Wizard screen, review the migration settings and then click Finish to complete the move.
In the following example, the cn=jsmith
object in the
amer.adatum.com domain will be moved to the
emea.adatum.com domain:
Move-ADObject -Identity "cn=jsmith,cn=users,dc=amer,dc=adatum,dc=com" -TargetPath "ou=MigratedUsers,dc=emea,dc=adatum,dc=com" -TargetServer dc-emea1.emea.adatum.com -Credential "emea\Administrator"
At the time of this writing, the current version of ADMT, version 3.2, is not supported on Windows Server 2012. Therefore, you should install it on a previous version of Windows Server as part of the migration to Windows Server 2012. You can move objects between domains assuming you follow a few guidelines:
The user performing the move operation must have permission to modify objects in the parent container of both domains.
You need to explicitly specify the target DC (serverless binds usually do not work). This is necessary because the “Cross Domain Move” LDAP control is being used behind the scenes. For more information on controls, see Using LDAP Controls.
The move operation must be performed against the RID master for both domains.
When you move a
user
object to a different domain, itsobjectSID
is replaced with a new SID (based on the new domain), and the old SID is optionally added to thesIDHistory
attribute.
Using LDAP Controls for more information on LDAP controls; MS KB 238394 (How to Use the MoveTree Utility to Move Objects Between Domains in a Single Forest); MSDN: IADsContainer::MoveHere; “ADMT Guide: Migrating and Restructuring Active Directory Domains”
If an entry for the naming context you want to browse is not already displayed, do the following:
Right-click on ADSI Edit in the right pane and click “Connect to.”
Fill in the information for the naming context, container, or OU you want to add an object to. Click on the Advanced button if you need to enter alternate credentials.
Right-click on the top-level node and open a connection to the Configuration NC.
Right-click on the
Partitions
container and select New→Object. Click Next.For the
cn
attribute, enter the FQDN of the external domain—othercorp.com, for example. Click Next.For the
nCName
attribute, enter the DN of the external domain, such asdc=othercorp,dc=com
. Click Next.For the
dnsRoot
attribute, enter the DNS name of a server that can respond to LDAP queries about the domain in question, such as dc1.othercorp.com.Click Next and then Finish to create the
crossRef
object.
Create an LDIF file called create_crossref.ldf with the following contents:
dn: cn=othercorp.com,cn=partitions,cn=configuration,dc=adatum,dc=com changetype: add objectClass: crossRef cn: othercorp.com nCName: dc=othercorp,dc=com dnsRoot: dc1.othercorp.com
Then run the following command:
> ldifde -v -i -f create_crossref.ldf
You can also create a crossRef
using AdMod as follows:
> admod -config -rb cn=othercorp.com,cn=partitions↵ objectClass::crossRef cn::othercorp.com nCName::dc=othercorp,dc=com↵ dnsRoot::dc1.othercorp.com -add
Similar to the way in which DNS servers use iterative queries to
resolve hostnames that can be resolved only by remote servers, LDAP uses
referrals to resolve queries for objects contained
in naming contexts that are not hosted by the local DC. When a DC
receives any query, it will search the Partitions
container for a crossRef
object containing the DN that’s being
used as the Base DN of the query. If the DC locates a crossRef
that matches the search base of the
query, and that crossRef
indicates a
naming context that’s hosted by the domain controller itself, then the
DC will perform the search locally. If the crossRef
refers to an NC that’s hosted on a
remote server, the DC generates a referral to the
server that is pointed to by the crossRef
object. If the DC can’t locate a
relevant crossRef
object, it will use
DNS to attempt to generate an additional location to refer the client
to.
In most cases, Active Directory will generate LDAP referrals
automatically. However, you should manually create a crossRef
object to generate LDAP referrals for
an external domain, such as referrals to
othercorp.com that are generated by the
adatum.com domain.
MS KB 241737 (How to Create a Cross-Reference to an External Domain in Active Directory); MS KB 817872 (How to Create crossRef Objects for a DNS Namespace Subordinate of an Existing Active Directory Forest); MSDN: Referrals [Active Directory]; MSDN: When Referrals Are Generated [Active Directory]
If an entry for the naming context you want to browse is not already displayed, do the following:
Right-click on ADSI Edit in the right pane and click “Connect to.”
Fill in the information for the naming context, container, or OU that contains the object you want to rename. Click on the Advanced button if you need to enter alternate credentials.
In the left pane, browse to the container or OU that contains the object you want to modify. Once you’ve found the object, right-click on it and select Rename.
Enter the new name and click OK.
You can also rename a leaf
object by using LDP as follows:
Open LDP.
From the menu, select Connection→Connect.
For Server, enter the name of a domain controller (or leave it blank for a serverless bind).
For Port, enter 389.
Click OK.
From the menu, select Connection→Bind.
Accept the default and bind as the currently logged on user or select the option to bind with credentials and then enter the credentials.
Click OK.
Click Browse→Modify RDN. For Old DN, enter the Distinguished Name of the object that you want to rename. For New DN, enter the object’s new name.
Click Run to rename the object.
Before you rename an object, you should ensure that no applications reference it by name. You can make objects rename-safe by requiring all applications that must store a reference to an object to use the GUID of the object, rather than the name.
The GUID (stored in the objectGUID
attribute) is effectively unique
and does not change when an object is renamed.
Note
Keep in mind that you may wish to perform other cleanup tasks
when renaming an object. In the case of a user who is changing her
name, you may wish to update her Display Name and sn
attributes to match the new CN.
If the parent container of the object you want to rename has a lot of objects in it, you may want to add a new connection entry for the DN of the object you want to rename. This may save you time searching through the list of objects in the container. You can do this by right-clicking ADSI Edit and selecting “Connect to” under Connection Point; select Distinguished Name and enter the DN of the object you want to rename.
You can also rename most objects within the Active Directory Users and Computers MMC snap-in (dsa.msc) by navigating to the object in question, right-clicking on it, and selecting Rename.
If an entry for the naming context you want to browse is not already displayed, do the following:
Right-click on ADSI Edit in the right pane and click “Connect to.”
Fill in the information for the naming context, container, or OU that contains the object you want to delete. Click on the Advanced button if you need to enter alternate credentials.
In the left pane, browse to the object you want to delete.
Right-click on the object and select Delete.
Click Yes to confirm.
You can also delete an object using LDP, as follows:
Open LDP.
From the menu, select Connection→Connect.
For Server, enter the name of a domain controller (or leave it blank for a serverless bind).
For Port, enter 389.
Click OK.
From the menu, select Connection→Bind.
Accept the default and bind as the currently logged on user or select the option to bind with credentials and then enter the credentials.
Click OK.
Click Browse→Delete. For DN, enter the Distinguished Name of the object that you want to delete.
Click Run to delete the object.
This recipe covers deleting individual objects. If you want to delete a container or OU and all the objects in it, take a look at Deleting a Container That Has Child Objects.
If the parent container of the object you want to delete has a lot of objects in it, you may want to add a new connection entry for the DN of the object you want to delete. This can save you time searching through the list of objects in the container and could help avoid accidental deletions. You can do this by right-clicking ADSI Edit and selecting “Connect to.” Under Connection Point, select Distinguished Name and enter the DN of the object you want to delete.
You can also delete most objects within the Active Directory Users and Computers MMC snap-in (dsa.msc) by navigating to the object in question, right-clicking on it, and selecting Delete.
The dsrm utility can be used to delete any
type of object (there are no limitations based on object type, as with
dsadd
and dsmod
). The only required parameter is the
DN of the object to delete. You can also specify -noprompt
to keep it from asking for
confirmation before deleting. The -s
parameter can be used as well to
designate a specific server to target. AdMod will not prompt you in
this manner.
Deleting a Container That Has Child Objects for deleting a container; MS KB 258310 (Viewing Deleted Objects in Active Directory); MSDN: IADsContainer::Delete; MSDN: IADsDeleteOps:: DeleteObject
Open ADSI Edit and follow the same steps as in Deleting an Object. The only difference is that you’ll be prompted to confirm twice instead of once before the deletion occurs.
As you can see from the solutions, there is not much difference between deleting a leaf node and deleting a container that has child objects. However, there is a distinction in what is happening in the background.
Deleting an object that has no children can be done with a simple LDAP delete operation. On the other hand, to delete a container and its children, the tree-delete LDAP control has to be used. If you were to do the deletion from an LDAP-based tool like LDP (the Active Directory Administration Tool), you would first need to enable the Subtree Delete control, which has an OID of 1.2.840.113556.1.4.805. LDP provides another option to do a Recursive Delete from the client side. That will essentially iterate through all the objects in the container, deleting them one by one. The Subtree Delete is much more efficient, especially when dealing with large containers.
As with the other operations we’ve discussed in this chapter (create, rename, move, and so on), the user performing the delete operation needs to have the necessary permissions to delete the object or objects in question. Active Directory permissions are discussed more extensively in Chapter 14.
Deleting an Object for information about deleting objects; Protecting a Computer Against Accidental Deletion; Protecting a User Against Accidental Deletion; MSDN: IADsDeleteOps::DeleteObject
Follow the steps in Viewing the Attributes of an Object.
Ensure that
createTimestamp
andmodifyTimestamp
are included in the list of attributes to be returned by looking at Attributes under Options→Search.
You can view the created and modified timestamps using the built-in DSQuery utility, as well as AdFind. For DSQuery, use the following syntax:
> dsquery * "<ObjectDN>
" -attr name createTimestamp modifyTimestamp
For AdFind, use the following:
> adfind -default -rb cn=Users -f "cn=Joe Smith"↵ createTimestamp modifyTimestamp
When an object is created or modified in Active Directory, the
createTimestamp
and modifyTimestamp
attributes get set with the
current time. The createTimestamp
attribute is replicated between domain controllers, so assuming the
latest modification of the object in question has replicated to all
domain controllers, they will all contain the timestamp when the object
was created. whenChanged
and modifyTimestamp
are not replicated, which
means that their values will be local to an individual domain
controller. Additionally, modifyTimestamp
is a constructed
attribute.
Viewing the Attributes of an Object for viewing the attributes of an object; Chapter 12 for a more detailed description of the Active Directory replication process
You want to view or modify the default LDAP query policy of a forest. The query policy contains settings that restrict search behavior, such as the maximum number of entries that can be returned from a search.
In the Configuration partition, browse to Services→Windows NT→Directory Service→Query Policies.
In the left pane, click on the
Query Policies
container, then right-click on the Default Query Policy object in the right pane and select Properties.Click on the attribute you want to modify and click Remove.
Modify the value in the “Value to add” box and click Add.
Click OK twice.
To view the current settings, use the following command:
> ntdsutil "ldap pol" conn "con to server <DomainControllerName>
" q "show values"
To change the MaxPageSize
value to 2,000, you can do the following:
> ntdsutil "ldap pol" conn "con to server <DomainControllerName>
" q
ldap policy: set MaxPageSize to 2000
ldap policy: Commit Changes
The LDAP query policy contains several settings that control how domain controllers handle searches. By default, one query policy is defined for all domain controllers in a forest, but you can create additional ones and apply them to a specific domain controller or even at the site level (so that all domain controllers in the site use that policy).
Query policies are stored in the Configuration NC as queryPolicy
objects. The default query policy is located at cn=Default Query
Policy,cn=Query-Policies,
cn=Directory Service,cn=Windows
NT,cn=Services
,
<ConfigurationPartitionDN>
. The
attribute lDAPAdminLimits
of a
queryPolicy
object is multivalued and
contains each setting for the policy in name/value pairs. Table 4-4 contains the available
settings.
Table 4-4. LDAP query policy settings
Name | Default value | Description |
---|---|---|
| 4 per proc | Maximum number of threads that are created by the DC for query execution. |
| 4096 | Maximum number of datagrams that can be simultaneously processed by the DC. |
| 10485760 | Maximum size in bytes for an LDAP request that the server will attempt to process. If the server receives a request that is larger than this value, it will close the connection. |
| 120 secs | Initial receive timeout. |
| 5000 | Maximum number of open connections. |
| 900 secs | Maximum amount of time a connection can be idle. |
| 1000 | Maximum number of records that will be returned by LDAP responses. |
| 120 secs | Maximum length of time the domain controller can execute a query. |
| 10000 | Maximum size of temporary storage that is allocated to execute queries. |
| 262144 | Controls the total amount of data that the domain controller stores for this kind of search. When this limit is reached, the domain controller discards the oldest of these intermediate results to make room to store new intermediate results. |
| 5 | Maximum number of notifications that a client can request for a given connection. |
Instead of modifying the default LDAP query policy, you can create
a new one from scratch. In the Query
Policies
container (where the default query policy object is
located), create a new queryPolicy
object and set the lDAPAdminLimits
attribute as just described based on the settings you want configured.
Then modify the attribute queryPolicyObject
on the nTDSDSA
object of a domain controller you want
to apply the new policy to. This can be done via the Active Directory
Sites and Services snap-in by browsing to the nTDSDSA
object of a domain controller
(cn=NTDS Settings
), right-clicking on it, and selecting
Properties. You can then select the new policy from a drop-down menu
beside Query Policy. Click OK to apply the new policy.
Warning
You should not change the default query policy in production unless you’ve done plenty of testing. Changing some of the settings may result in unexpected application or domain controller behavior, such as a significant failure of your Active Directory domain controllers.
Modifying the Default TTL Settings for Dynamic Objects; MS KB 315071 (How to View and Set LDAP Policy in Active Directory by Using Ntdsutil.exe)
The LDIF specification defined in RFC 2849 describes a well-defined file-based format for representing directory entries. The format is intended to be both human- and machine-parseable, which adds to its usefulness. LDIF is the de facto standard for importing and exporting a large number of objects in a directory and is supported by virtually every directory vendor, including Microsoft.
The -f
switch specifies the
name of the file to use to save the entries to, -s
is the DC to query, -l
is the comma-separated list of attributes
to include, -p
is the search scope,
-r
is the search filter, and
-d
is the base DN. If you encounter
any problems using ldifde
, the
-v
switch enables verbose mode and
can help identify problems.
Importing Objects Using an LDIF File for importing objects using LDIF; RFC 2849 (The LDAP Data Interchange Format [LDIF]—Technical Specification); MS KB 237677 (Using LDIFDE to Import and Export Directory Objects to Active Directory)
You want to import objects into Active Directory using an LDIF file. The file could contain object additions, modifications, and deletions.
To import objects using the ldifde utility, you must first create an LDIF file with the objects to add, modify, or delete. Here is an example LDIF file that adds a user:
dn: cn=jsmith,cn=users,dc=adatum,dc=com changetype: add objectClass: user samaccountname: jsmith sn: JSmith
Once you’ve created the LDIF file, you just need to run the
ldifde
command to import the new
objects:
> ldifde -i -f input.ldf
For more information on the LDIF format, check RFC 2849.
To import with ldifde, simply specify the
-i
switch to turn on import mode
and -f
<filename>
for the file. It can also
be beneficial to use the -v
switch
to turn on verbose mode to get more information in case of errors. The
Windows Server 2003 version of ldifde also
includes the –j
switch that will
create a logfile for troubleshooting purposes. The LDIF file can
specify a deletion or a modification instead of an addition. To modify
a user, set the changetype
to
modify
. To delete a user, set the
changetype
to delete
.
Exporting Objects to an LDIF File for information on LDIF; RFC 2849 (The LDAP Data Interchange Format [LDIF]—Technical Specification); MS KB 237677 (Using LDIFDE to Import and Export Directory Objects to Active Directory)
You want to export objects to a comma-separated values (CSV) file. The CSV file can then be opened and manipulated from a spreadsheet application or with a text editor.
You can export objects to a CSV file using Active Directory Users and Computers, as follows:
Open Active Directory Users and Computers.
Browse to the desired container or OU.
Right-click on the container or OU and click Export List.
Choose the CSV file type, name the file, and then click Save to save the file.
You can export objects to a CSV file using the built-in csvde utility, as well as AdFind. For csvde, use the following syntax:
> csvde -f output.csv -l<AttrList>
-p<Scope>
-r "<Filter>
" -d "<BaseDN>
"
You can also export information to a CSV file using adfind
:
> adfind -b<SearchBase>
-f<Filter>
-csv<Attr1> <Attr2> <Attr3>
You can also export objects to a CSV file by using PowerShell. In the following command, all user objects in the Users OU in the adatum.com domain will be exported to c:\temp\users.csv:
Get-ADUser -SearchBase "cn=users,dc=adatum,dc=com" -Filter * | Select Name,UserPrincipalName,samAccountName | Export-Csv c:\temp\users.csv
Once you have a CSV file containing entries, you can use a spreadsheet application such as Excel to view, sort, and manipulate the data.
Before performing the export, add any needed columns to the view in Active Directory Users and Computers. To add columns, click on View and then click Add/Remove Columns.
The parameters used by csvde are nearly
identical to those used by ldifde. The -f
switch specifies the name of the file to
use to save the entries to, -s
is
the DC to query, -l
is the
comma-separated list of attributes to include, -p
is the search scope (base
, onelevel
, or subtree
), -r
is the search filter, and -d
is the base DN. If you encounter any
issues, the -v
switch enables
verbose mode and can help identify problems.
AdFind offers a number of additional switches to customize the behavior of CSV file output, including the following:
-csv xxx
CSV output.
xxx
is an optional string that specifies the value to use for empty attributes.-csvdelim x
Delimiter to use for separating attributes in CSV output. The default is (
,
).-csvmvdelim x
Delimiter to use for separating multiple values in output. The default is (
;
).-csvq x
Character to use for quoting attributes. The default is (
"
).
Importing Objects Using PowerShell and a CSV File for importing objects using a CSV file
You must first create a CSV file containing the objects to add.
The first line of the file should contain a comma-separated list of
attributes you want to set, with DN
being the first attribute. Here is an example:
DN,objectClass,cn,sn,userAccountControl,sAMAccountName,userPrincipalName
The rest of the lines should contain entries to add. If you want to leave one of the attributes unset, then leave the value blank (followed by a comma). Here is a sample CSV file that would add two user objects:
DN,objectClass,sn,userAccountControl,sAMAccountName,userPrincipalName "cn=jim,cn=users,dc=adatum,dc=com",user,Smith,512,jim,jim@adatum.com "cn=john,cn=users,dc=adatum,dc=com",user,,512,john,john@adatum.com
Once you’ve created the CSV file, you just need to import the new objects by using PowerShell:
> -Import-CSV c:\temp\input.csv | New-ADUser
Prior to the New-ADUser
cmdlet,
CSVDE
was often used to import
objects from a CSV file. However, starting with Windows Server 2008, it
became much more difficult to use CSVDE
due to the inability to meet password
complexity requirements of a domain. CSVDE
creates users with a blank password,
which usually doesn’t meet password complexity requirements of a domain.
With the New-ADUser
cmdlet, new
disabled users can be created without a password, even if there is a
password complexity requirement.
Exporting Objects to a CSV File for exporting objects in CSV format; Creating a User; Creating a Large Number of Users
Get Active Directory Cookbook, 4th Edition now with the O’Reilly learning platform.
O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.