-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathNew-DomainJoinPrep-Groups.ps1
247 lines (198 loc) · 7.67 KB
/
New-DomainJoinPrep-Groups.ps1
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
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
[CmdletBinding()]
param (
[Parameter(Mandatory)]
[String] $Domain,
[Parameter(Mandatory)]
[String] $Room,
[Parameter(Mandatory)]
[Int] $Hosts,
[Parameter()]
[String] $Suffix = "03",
[Parameter()]
[Switch] $Defaults
)
$default_groups = @("ACL_RD-RAP", "ACL_User", "GG_User", "GG")
# actual name is not important, this triggers creation of computer accounts
$computer_accounts = "Hosts"
# add members to groups
# when adding multiple members do so in an array
$members_list = @(
[PSCustomObject]@{
group = "ACL_RD-RAP";
members = @("GG")
}
[PSCustomObject]@{
group = "ACL_User";
members = @("GG_User")
}
[PSCustomObject]@{
group = "GG";
members = @($computer_accounts)
}
)
$ou_list = @(
[PSCustomObject]@{
group = "ACL_RD-RAP";
ou = @("OU_R$Room", "OU_ACL-Groups", "OU_Groups")
}
[PSCustomObject]@{
group = "ACL_User";
ou = @("OU_R$Room", "OU_ACL-Groups", "OU_Groups")
}
[PSCustomObject]@{
group = "GG_User";
ou = @("OU_R$Room", "OU_Global-Groups", "OU_Groups")
}
[PSCustomObject]@{
group = "GG";
ou = @("OU_R$Room", "OU_Global-Groups", "OU_Groups")
}
[PSCustomObject]@{
group = $computer_accounts;
ou = @("OU_HV-Server_R$Room", "OU_Classrooms")
}
)
# suffix was passed as empty
if ($Suffix.Trim()) { $Suffix = "_$Suffix" }
# prompt for prefixes
$default_groups_str = $default_groups -join ", "
if (!$Defaults) {
$groups = (Read-Host -Prompt "`n[>] Please provide desired group prefixes.`n [Default]: $default_groups_str`n Accept defaults with [ENTER] or write names.`n Separate with comma and space").Split(",").Trim()
}
# defaults were accepted
if (!$groups) {
$groups = $default_groups
$groups_note = "`n Defaults were accepted."
}
# user feedback
Write-Output ($groups_note, "`n ", ($groups.Count * $Hosts), "groups with", $groups.Count, "different prefixes will be created." -join " ")
# sort to create GG_ before ACL_
$groups = $groups | Sort-Object -Descending
# these will not create groups but accounts instead
if ($ou_list.group.Contains($computer_accounts)) {
$groups = ,$computer_accounts + $groups
}
# pre-construct dc path for group creation
$dc_path = (",DC=", ($Domain.Split('.') -join ",DC=") -join "")
# filter errors for log file
filter stamp {"$(Get-Date -Format G): $_"}
# error counter for user feedback
$error_counter = 0
foreach ($prefix in $groups) {
# Dieses Präfix hat eine default OU vordefiniert
if ($ou_list.group.Contains($prefix)) {
$ou = $ou_list | Where-Object {$_.group -eq $prefix} | Select-Object -ExpandProperty ou
$ou_note = "`n [Default] organizational units found for prefix [$prefix]: $ou`n Accept with [ENTER] or write new ones."
}
# prompt for ou path
if (!$Defaults) {
$ou_prompt = (Read-Host -Prompt "`n[>] Please provide the OU path for groups with prefix [$prefix].$ou_note`n Write from child (left) to parent (right).`n Only provide names, the script will add keys.`n Separate with comma and space").Split(",").Trim()
}
# user did provide input
if ($ou_prompt) { $ou = $ou_prompt }
# pre-construct ou path for group creation
$ou_path = (",OU=", ($ou.Split(',').Trim() -join ",OU=") -join "")
$path = ($ou_path, $dc_path -join "")
# need to create parents first
[Array]::Reverse($ou)
$ou_queue = $dc_path
# if necessary create the OUs by iterating over the path
for ($i = 0; $i -lt $ou.Count; $i++) {
# construct distinguishedName and parent path
$separator = if ($i -gt 0) { "," }
if ($i -le 0) {
$ou_parents = $ou_queue.substring(1)
$ou_queue = ("OU=", $ou[$i], $separator, $ou_queue -join "")
} else {
$ou_parents = ("OU=", $ou[$i-1], $separator, $ou_parents -join "")
$ou_queue = ("OU=", $ou[$i], $separator, $ou_queue -join "")
}
# verify existance
$ou_exists = Get-ADOrganizationalUnit -Filter { DistinguishedName -eq $ou_queue }
if (!$ou_exists) {
try {
# create ou
New-ADOrganizationalUnit -Name $ou[$i] -Path $ou_parents -ProtectedFromAccidentalDeletion 0
}
catch {
$message = $_
Write-Warning ($message, " [", $ou[$i], "]: " -join "")
$message | stamp >> script_error.log
$error_counter++
}
}
}
# reset ou order
[Array]::Reverse($ou)
# create an account and a group for each workstation and if necessary add members
for ($i = 0; $i -lt $Hosts * 10; $i += 10) {
$client = ([string]($i + 10)).PadLeft(3, '0')
$host_name = "R$Room`_PC$client$Suffix"
$common_name = "$prefix`_$host_name"
$scope = if ($common_name.Substring(0, 4) -eq "ACL_") { "DomainLocal" } else { "Global" }
$member_name = ($members_list | Where-Object {$_.group -eq $prefix}).members
$member_group = "$member_name`_$host_name"
try {
if ($prefix -eq $computer_accounts) {
# create computers
New-ADComputer -Name $host_name -SAMAccountName $host_name -Path $path.substring(1)
} else {
# create group
New-ADGroup -Name $common_name -Path $path.substring(1) -GroupScope $scope -GroupCategory Security -ErrorAction Stop
}
}
catch {
$message = $_
if ($message -inotmatch "group already exists") {
Write-Warning ($message, " [", $common_name, "]: " -join "")
$message | stamp >> script_error.log
$error_counter++
}
}
# add members
$member_is_group = Get-ADGroup -Filter { SamAccountName -eq $member_group }
try {
if ($member_name -And $member_is_group) {
Add-ADGroupMember -Identity $common_name -Members $member_group -ErrorAction Stop
} elseif ($member_name) {
if ($member_name -eq $computer_accounts) {
$member_name = "$host_name`$"
}
Add-ADGroupMember -Identity $common_name -Members $member_name -ErrorAction Stop
}
}
catch {
$message = $_
Write-Warning ($message, " [", $common_name, "]: " -join "")
$message | stamp >> script_error.log
$error_counter++
}
}
}
Write-Output "`nScript finished with $error_counter errors.`n"
<#
.SYNOPSIS
Creates domain local and global AD groups for preparation of workstations
in educative scenarios. Especially for preparing upcoming domain joins.
.DESCRIPTION
Takes a prefix and creates as many groups for this prefix as there were [Hosts].
The resulting group will be called <Prefix>_R<Room>_PC<Host>_<Suffix>
Prefixes must begin with either "ACL_" or "GG_". Universal groups are not supported.
Group members can be added in the script file.
.PARAMETER Domain
Fully qualified domain name of the domain where the groups are to be created.
.PARAMETER Room
The room number of the physical workstations.
.PARAMETER Hosts
Amount of necessary workstations including teacher and unrelated servers that
should take part in the scenario.
.PARAMETER Suffix
Gets appended to groupname. Can be omitted by passing an empty string.
.PARAMETER Defaults
Uses predefined group names, paths and memberships.
Defaults can be changed in the script file.
.EXAMPLE
New-DomainJoinPrep-Groups -Domain contoso.com -Room 110 -Hosts 20 -Suffix "" -Defaults
.LINK
http://github.com/marianarlt
#>