PowerShell 2.0 实践(八)管理活动目录(中)
上一次我们对活动目录的用户和组进行了简单的管理操作,使用了.NET框架中的System.DirectoryServices
System.DirectoryServices.AccountManagement等类。以及微软与Quest公司的PowerShell扩展,在实际应用中,推荐使用上述两种扩展,其语法更加简洁,便于维护。本次我们将尝试批量编辑域用户的信息,以及通过LDAP查询我们感兴趣的信息。
本系列所有脚本均在Windows Server 2008 R2 DataCenter (PowerShell 2.0) + PowerGUI Script Editor Free Edition x64中测试通过。
- 使用 Microsoft Active Directory Cmdlets 批量创建域用户。
首先准备一个csv文件,将待创建的域用户名写入:
其中第一行的"UserName"作为列名。CSV = Comma Separated Values,即"逗号分隔值"文件。这里使用的是一种广义的csv文件,可以看到并没有逗号,其实用其他分隔符也可以,只要能区分各个用户就可以了。
csv文件可以使用Excel打开:
循环遍历csv文件,提取UserName:
Clear-Host
Import-Csv -Path E:\PSTest\Users.csv | foreach {
New-ADUser -Name $_.UserName `
-SamAccountName $_.UserName -GivenName $_.UserName `
-Surname $_.UserName -Path "ou=Domain Controllers,dc=Lucifer,dc=com" `
-DisplayName $_.UserName -AccountPassword $null `
-CannotChangePassword $false `
-ChangePasswordAtLogon $true `
-UserPrincipalName "$_.UserName@manticore.org" `
}
运行结果:
可以看到用户默认是禁用的,稍后将学习怎么启用、禁用用户。
2、使用 Quest Active Directory Cmdlets 批量创建域用户。
Clear-Host
Import-Csv -Path E:\PSTest\Users.csv | foreach {
New-QADUser -Name $_.UserName `
-DisplayName $_.UserName `
-SamAccountName $_.UserName `
-ParentContainer "OU=Domain Controllers,DC=Lucifer,DC=com" `
}
还是使用刚才的csv文件,运行结果类似:
其实不一定非要使用csv文件,使用txt、xml等文件也可以,文件只是存储用户信息的容器,只要能获取文件中存储的用户信息即可。PowerShell对csv提供了内置支持,即Import-Csv、Export-Csv命令等,所以如果没有特殊需求,建议使用csv文件。
3、修改用户信息。
要修改用户信息,首先要知道用户有哪些信息:
Get-ADUser -Identity "User1" -Properties *
运行结果:
今天偶然看到AD PowerShell的官方博客,还是很不错的。
如上图所示,查询出了用户"User1"的所有信息,可以看到还是很多的。-Identity参数用于唯一标识用户,微软的Cmdlets支持如下四种Identity:
其中比较常用的是sAMAccountName。
可以用一些PowerShell或LDAP表达式来进行查询:
Logical Operator | Description | Equivalent LDAP operator/expression |
-eq | Equal to. This will not support wild card search. | = |
-ne | Not equal to. This will not support wild card search. | ! x = y |
-like | Similar to -eq and supports wildcard comparison. The only wildcard character supported is: * | = |
-notlike | Not like. Supports wild card comparison. | ! x = y |
-approx | Approximately equal to | ~= |
-le | Lexicographically less than or equal to | <= |
-lt | Lexicographically less than | ! x >= y |
-ge | Lexicographically greater than or equal to | >= |
-gt | Lexicographically greater than | ! x <= y |
-and | AND | & |
-or | OR | | |
-not | NOT | ! |
-bor | Bitwise OR | :1.2.840.113556.1.4.804:= |
-band | Bitwise AND | :1.2.840.113556.1.4.803:= |
-recursivematch | Uses LDAP_MATCHING_RULE_IN_CHAIN (Win2k3 SP2 and above) | :1.2.840.113556.1.4.1941:= |
如:
Get-ADObject -Filter { CN -like "*bro*" }
Get-ADObject -LDAPFilter "(cn=*bro*)"
查询CN like bro的活动目录信息:
我对LDAP语法很不熟悉,临时查了些资料:
LDAP的存储规则
区分名(DN,Distinguished Name)
和自然界中的树不同,文件系统/LDAP/电话号码簿目录的每一片枝叶都至少有一个独一无二的属性,这一属性可以帮助我们来区别这些枝叶。
在文件系统中, 这些独一无二的属性就是带有完整路径的文件名。比如/etc/passwd,该文件名在该路径下是独一无二的。当然我们可以有/usr/passwd, /opt/passwd,但是根据它们的完整路径,它们仍然是唯一的。
在LDAP中,一个条目的区分名称叫做"dn"或者叫做区分名。在一个目录中这个名称总是唯一的。比如,我的dn是"uid=aghaffar, ou=People, o=developer.ch"。不可能有相同的dn,但是我们可以有诸如"uid=aghaffar, ou=Administrators, o=developer.ch"的dn。这同上面文件系统中/etc/passwd 和 /usr/passwd的例子很类似。
我们有独一无二的属性,在"ou=Administrators, o=developer.ch" 中uid和在"ou=People, o=developer.ch"中的uid。这并不矛盾。
CN=Common Name 为用户名或服务器名,最长可以到80个字符,可以为中文;
OU=Organization Unit为组织单元,最多可以有四级,每级最长32个字符,可以为中文;
O=Organization 为组织名,可以3—64个字符长
C=Country为国家名,可选,为2个字符长
LDAP目录以一系列"属性对"的形式来存储记录项,每一个记录项包括属性类型和属性值(这与关系型数据库用行和列来存取数据有根本的不同)。
4、将用户"User1"的部门修改为"开发部",并启用该用户:
Get-ADUser -Identity "User1" | Set-ADUser -Department "Develop" -Enabled $true
运行结果:
注意,在PowerShell中,使用$true、$false表示布尔值:true/false。
此外,凡是脚本中包含Q的,如Get-QADUser 均是Quest公司的Cmdlets,否则是微软的Cmdlets,请注意区分。
5、查询禁用的用户:
Clear-Host
Get-QADUser -Disabled
Search-ADAccount -AccountDisabled –UsersOnly
运行结果:
Quest Cmdlets给出了禁用用户的列表,Microsoft Cmdlets则给出了更为详细的信息。
6、使用.NET框架中的类进行查询:
Clear-Host
$user = "User1"
$dc = [System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain()
$root = $dc.GetDirectoryEntry()
$search = [System.DirectoryServices.DirectorySearcher]$root
$search.Filter = "cn=$user"
$result = $search.FindOne()
if($result -ne $null)
{
Write-Host "Find One!"
}
else
{
Write-Host "$user does not exists!"
}
查询cn=User1的结果,显然能找到该用户:
FindOne()方法返回查询结果中的第一个,FindAll()则会返回所有查询到的结果。
7、禁用、启用用户:
Clear-Host
Disable-ADAccount -Identity "User1"
Enable-ADAccount -Identity "User1" -PassThru
Disable-QADUser -Identity "User1"
Enable-QADUser -Identity "User1"
8、查询登录并锁定的用户:
Clear-Host
Get-QADUser -Locked
Search-ADAccount –LockedOut
9、移动用户。为了便于看到效果,我们先新建一个OU:Temp。
注意,取消保护勾选可以方便的删除该OU:
下面把User1移动到Temp中去。
Move-ADObject -Identity "CN=User1,OU=Domain Controllers,DC=Lucifer,DC=com" -TargetPath "OU=Temp,DC=Lucifer,DC=com"
运行结果:
注意表达式是有顺序的,CN要在OU之前,这块语法我也在慢慢摸索。
再使用Quest Cmdlets将User1移动回去:
Move-QADObject -Identity "CN=User1,OU=Temp,DC=Lucifer,DC=com" -NewParentContainer "OU=Domain Controllers,DC=Lucifer,DC=com"
运行结果:
小结:
本次我们继续练习了活动目录的相关操作,主要涉及域用户的编辑、搜索,其中掌握LDAP的查询语法非常重要。熟练以后可以快捷高效的对活动目录对象(不仅仅局限于用户、组)进行管理。下一次将练习域组的管理操作,以及管理OU、组策略等高级话题。