发布于 

PowerShell 批量创建 AD 域的 OU、组、用户,并创建对应的共享文件夹

准备

假设人事部给了你一份 Excel 表,记录了工号、姓名、部门、职位、公司,要按这表在 AD 域控上面创建对应的用户。

你稍加处理过后另存成了 csv,内容格式如下:

工号 姓名 部门 员工类型 公司
1001 赵一 管理层 老板 广州番禺加班有限公司
1002 钱二 管理层 总监 广州番禺加班有限公司
1003 孙三 管理层 经理 广州番禺加班有限公司
1004 李四 管理层 经理 广州番禺加班有限公司
1005 周五 管理层 经理 广州番禺加班有限公司
1006 吴六 行政部 主管 广州番禺加班有限公司
1007 郑七 行政部 员工 广州番禺加班有限公司
1008 王七加加 行政部 员工 广州番禺加班有限公司
1009 冯九 行政部 员工 广州番禺加班有限公司
1010 陈十 行政部 员工 广州番禺加班有限公司
1011 褚十一 账务部 主管 广州番禺加班有限公司
1012 卫十二 账务部 员工 广州番禺加班有限公司
1013 蒋十三 账务部 员工 广州番禺加班有限公司
1014 沈十四 账务部 员工 广州番禺加班有限公司
1015 韩十五 账务部 员工 广州番禺加班有限公司
1016 杨十六 销售部 主管 广州番禺加班有限公司
1017 朱十七 销售部 员工 广州番禺加班有限公司
1018 秦十八 销售部 员工 广州番禺加班有限公司
1019 尤十九 销售部 员工 广州番禺加班有限公司
1020 许二十 销售部 员工 广州番禺加班有限公司
1021 何二一 后勤部 主管 广州番禺加班有限公司
1022 吕二二 后勤部 员工 广州番禺加班有限公司
1023 施二三 后勤部 员工 广州番禺加班有限公司
1024 张二四 后勤部 员工 广州番禺加班有限公司
1025 孔二五 后勤部 员工 广州番禺加班有限公司
1026 曹二六 技术部 主管 广州番禺加班有限公司
1027 严二七 技术部 员工 广州番禺加班有限公司
1028 华二八 技术部 员工 广州番禺加班有限公司
1029 金二九 技术部 员工 广州番禺加班有限公司
1030 魏三十 技术部 员工 广州番禺加班有限公司

需求

域账号需求:

域控的层级结构为:公司 > 部门 > 员工

以工号来当登陆名,初始密码和工号一样,首次后登陆后必须更改密码。

共享文件夹需求:

文件结构为: \\ 服务器 \ 公司 $\ 部门 \ 员工

权限要求为:

老板、总监可以查看所有部门

部门之间不可互相查看

员工之间不可互相查看

员工对自己的文件夹可以读写

部门内有一个 “部门共享” 文件夹,部门内所有员工都可以读写

主管可以查看自己的整个部门所有员工的文件夹

所需命令

简单说明一下要用的命令

操作 AD 域要用的 Get-ADxxxSet-ADxxx 这一类的命令要添加 Windows PowerShell 的 Active Directory 模块 才能使用。

添加了 Active Directory 域服务 的服务器,会自动加上去的,没有的话也能手动添加上去,没加域和没用对应的域权限运行是用不了的。

脚本里面的具体每条命令我就不解释了,自己去官网查一下吧,比我说得详细,用法实例结合参考我这里贴出来的命令。

服务器在 添加角色和功能向导 里面

Windows Server 2019 添加角色和功能向导 界面

Windows10 就是在设置里面可选功能里面找

Windows10 设置 添加可靠功能 界面

批量创建 OU、组、用户

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
# 根目录路径,批量在此路径下添加OU和用户,我这里直接用了域的根目录
$OuRoot = Get-ADDomain | Select-Object -ExpandProperty "DistinguishedName"

# 域名
$DomainName = (Get-ADDomain).DNSRoot

# 导入整理好的csv
$UserList = Import-Csv "C:\Users\Administrator\Desktop\工号部门信息表.csv" -Encoding UTF8

foreach ( $User in $UserList ) {

# 没有公司就创建公司
# 获取根目录OU下面的公司OU的DistinguishedName,拿不到就是没有
$OuRoot_Company = Get-ADOrganizationalUnit -Filter "Name -eq '$($User.公司)'" -SearchBase $OuRoot -SearchScope OneLevel | Select-Object -ExpandProperty "DistinguishedName"

if ( -Not $OuRoot_Company ) {
# 创建公司OU
New-ADOrganizationalUnit -Name $User.公司 -Path $OuRoot # -ProtectedFromAccidentalDeletion $False
# 获取公司OU 的DistinguishedName
$OuRoot_Company = Get-ADOrganizationalUnit -Filter "Name -eq '$($User.公司)'" -SearchBase $OuRoot -SearchScope OneLevel | Select-Object -ExpandProperty "DistinguishedName"
# 创建公司OU 的组
New-ADGroup -Name $User.公司 -Path $OuRoot_Company -GroupScope Global
}


# 公司下面没有部门就创建部门
# 获取公司下面的部门OU的DistinguishedName,拿不到就是没有
$OuRoot_Company_Department = Get-ADOrganizationalUnit -Filter "Name -eq '$($User.部门)'" -SearchBase $OuRoot_Company -SearchScope OneLevel | Select-Object -ExpandProperty "DistinguishedName"

if ( -Not $OuRoot_Company_Department ) {
# 创建公司下的部门OU
New-ADOrganizationalUnit -Name $User.部门 -Path $OuRoot_Company # -ProtectedFromAccidentalDeletion $False
# 获取公司下的部门OU 的DistinguishedName
$OuRoot_Company_Department = Get-ADOrganizationalUnit -Filter "Name -eq '$($User.部门)'" -SearchBase $OuRoot_Company -SearchScope OneLevel | Select-Object -ExpandProperty "DistinguishedName"
# 创建公司下的部门OU 的组,为什么这里要用“公司_部门”?因为可能有两个子公司,两个子公司都有财务部,只有一个公司可以去掉公司前缀
New-ADGroup -Name $($($User.公司) + "_" + $($User.部门) ) -Path $OuRoot_Company_Department -GroupScope Global
}


# 创建用户,相关属性自行增减,这里为了登陆的时候直接使用工号当账号密码,域服务器的本地组策略的密码复杂度是关掉的了。
New-ADUser `
-Name $User.姓名 `
-DisplayName $User.姓名 `
-EmployeeNumber $User.工号 `
-SamAccountName $User.工号 `
-UserPrincipalName "$($User.工号)@$DomainName" `
-Department $User.部门 `
-OtherAttributes @{EmployeeType=$($User.员工类型)} `
-AccountPassword $(ConvertTo-SecureString $User.工号 -AsPlainText -Force) `
-ChangePasswordAtLogon $True `
-Enabled $True `
-Path $OuRoot_Company_Department

# 获取用户的 DistinguishedName
$User_DN = Get-ADUser -identity $User.工号 | Select-Object -ExpandProperty "DistinguishedName"

# 把用户添加进公司_部门的组
$Company_Department_Group_DN = Get-ADGroup -identity $($($User.公司) + "_" + $($User.部门) ) | Select-Object -ExpandProperty "DistinguishedName"
Add-ADGroupMember -Identity $Company_Department_Group_DN -Members $User_DN

# 把部门添加进公司的组
$Company_Group_DN = Get-ADGroup -identity $User.公司 | Select-Object -ExpandProperty "DistinguishedName"
Add-ADGroupMember -Identity $Company_Group_DN -Members $Company_Department_Group_DN

}

批量创建共享文件夹

因为要拿 AD 域里面的信息,又懒得在文件共享服务器那边装模块(模拟可能的实际场景),所以这里用的是远程 PowerShell 命令

关于 PowerShell 设置文件权限的信息,可以看我的另一篇文章:

PowerShell 修改文件夹及文件权限 - tjxwork (tjxblog.com)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
# 要远程的共享文件服务器的名字(已加域)
$InvokeServerName = "SHARING-SERVER"

# 要在共享服务器上面的创建的共享文件夹的路径
$SharedFolderPath = "D:\Shares\广州番禺加班有限公司"

# 获取域
$Domain = (Get-ADDomain).Name

# 获取公司 OU
$Company_OU = Get-ADOrganizationalUnit -Filter "Name -eq '广州番禺加班有限公司'"

# 获取公司 组
$Company_Group = Get-ADGroup -Filter * -SearchBase $Company_OU -SearchScope OneLevel

# 获取公司下面的所有部门
$Department_OU_List = Get-ADOrganizationalUnit -Filter * -SearchBase $Company_OU | Where-Object {$_.Name -ne "广州番禺加班有限公司"}

# 获取公司下所有员工属性为老板和总监的员工
$Boss_User_List = Get-ADUser -Filter "(employeeType -eq '老板') -or ( employeeType -eq '总监')" -SearchBase $Company_OU


# 创建最顶层共享文件夹
$InvokeScriptBlock1 = {
# 新建公司共享文件夹路径
New-Item -Path "$Using:SharedFolderPath" -ItemType Directory

# 设置公司共享文件夹,隐藏共享,共享路径是 \\服务器\GZ$
New-SmbShare -Name "GZ$" -Path "$Using:SharedFolderPath" -FullAccess "$Using:Domain\$($Using:Company_Group.Name)"

# 准备修改文件夹权限
$FolderPath = $Using:SharedFolderPath
$FolderAcl = Get-Acl -Path $FolderPath

# 设置 域 Administrator 的权限
$AccessRule = New-Object -TypeName System.Security.AccessControl.FileSystemAccessRule("$Using:Domain\administrator", "FullControl", "ContainerInherit,ObjectInherit", "None", "Allow")
$FolderAcl.SetAccessRule($AccessRule)

# 设置 公司 组的权限
$AccessRule = New-Object -TypeName System.Security.AccessControl.FileSystemAccessRule("$Using:Domain\$($Using:Company_Group.Name)", "ListDirectory", "None", "None", "Allow")
$FolderAcl.SetAccessRule($AccessRule)

# 设置 老板、总监的权限
if( ($Using:Boss_User_List.SamAccountName).Count -gt 0 ){
foreach ($Boss_User in $Using:Boss_User_List){
$AccessRule = New-Object -TypeName System.Security.AccessControl.FileSystemAccessRule("$Using:Domain\$($Boss_User.SamAccountName)", "Read", "ContainerInherit,ObjectInherit", "None", "Allow")
$FolderAcl.SetAccessRule($AccessRule)
}
}

# 禁用继承权限
$FolderAcl.SetAccessRuleProtection($true,$false)

# 应用到文件夹
Set-Acl -Path $FolderPath -AclObject $FolderAcl
}

Invoke-Command -ComputerName $InvokeServerName -ScriptBlock $InvokeScriptBlock1



# 以部门进行循环
foreach ($Department_OU in $Department_OU_List) {

# 获取部门下的所有用户
$Department_User_List = Get-ADUser -Filter * -SearchBase $Department_OU

# 获取部门下所有员工属性为主管的员工
$Director_User_List = Get-ADUser -Filter "employeeType -eq '主管'" -SearchBase $Department_OU

# 远程执行的代码块2
$InvokeScriptBlock2 = {

# 新建部门文件夹
New-Item -Path "$Using:SharedFolderPath\$($Using:Department_OU.Name)" -ItemType Directory

# 准备修改文件夹权限
$FolderPath1 = "$Using:SharedFolderPath\$($Using:Department_OU.Name)"
$FolderAcl = Get-Acl -Path $FolderPath1

# 设置 部门 组的权限
$AccessRule = New-Object -TypeName System.Security.AccessControl.FileSystemAccessRule("$Using:Domain\$($Using:Company_OU.Name)_$($Using:Department_OU.Name)", "ListDirectory", "None", "None", "Allow")
$FolderAcl.SetAccessRule($AccessRule)

if( ($Using:Director_User_List.SamAccountName).Count -gt 0 ){
# 设置 主管的权限
foreach ($Director_User in $Using:Director_User_List){
$AccessRule = New-Object -TypeName System.Security.AccessControl.FileSystemAccessRule("$Using:Domain\$($Director_User.SamAccountName)", "Read", "ContainerInherit,ObjectInherit", "None", "Allow")
$FolderAcl.SetAccessRule($AccessRule)
}
}

# 应用到文件夹
Set-Acl -Path $FolderPath1 -AclObject $FolderAcl

# 新建部门内“部门共享”文件夹
New-Item -Path "$Using:SharedFolderPath\$($Using:Department_OU.Name)\部门共享" -ItemType Directory

# 准备修改文件夹权限
$FolderPath2 = "$Using:SharedFolderPath\$($Using:Department_OU.Name)\部门共享"
$FolderAcl = Get-Acl -Path $FolderPath2

# 设置 部门\部门共享 组的权限
$AccessRule = New-Object -TypeName System.Security.AccessControl.FileSystemAccessRule("$Using:Domain\$($Using:Company_OU.Name)_$($Using:Department_OU.Name)", "Modify,ReadAndExecute,Write", "ContainerInherit,ObjectInherit", "None", "Allow")
$FolderAcl.SetAccessRule($AccessRule)

# 应用到文件夹
Set-Acl -Path $FolderPath2 -AclObject $FolderAcl

# 循环创建用户文件夹
foreach ($Department_User in $Using:Department_User_List ) {

# 新建用户文件夹
New-Item -Path "$Using:SharedFolderPath\$($Using:Department_OU.Name)\$($Department_User.Name)" -ItemType Directory

# 准备修改文件夹权限
$FolderPath3 = "$Using:SharedFolderPath\$($Using:Department_OU.Name)\$($Department_User.Name)"
$FolderAcl = Get-Acl -Path $FolderPath3

# 设置用户权限
$AccessRule = New-Object -TypeName System.Security.AccessControl.FileSystemAccessRule("$Using:Domain\$($Department_User.SamAccountName)", "Modify,ReadAndExecute,Write", "ContainerInherit,ObjectInherit", "None", "Allow")
$FolderAcl.SetAccessRule($AccessRule)

# 应用到文件夹
Set-Acl -Path $FolderPath3 -AclObject $FolderAcl

}
}

Invoke-Command -ComputerName $InvokeServerName -ScriptBlock $InvokeScriptBlock2

}

个人不太建议写长脚本的,测试修改起来挺麻烦的,宁愿拆分开多操作几次。


原文作者:tjxwork
原文链接:https://www.tjxblog.com/blog/2023-0006
发布时间:2023-02-16