-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathSet-WEMApplockerRule.ps1
365 lines (318 loc) · 20.9 KB
/
Set-WEMApplockerRule.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
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
<#
.Synopsis
Updates a AppLocker Rule object in the WEM Database.
.Description
Updates a AppLocker Rule object in the WEM Database.
.Link
https://msfreaks.wordpress.com
.Parameter IdRule
..
.Parameter Name
..
.Parameter Description
..
.Parameter Permission
..
.Parameter IdADObjects
..
.Parameter ConditionObject
..
.Parameter ExceptionObjects
..
.Parameter Connection
..
.Example
.Notes
Author: Arjan Mensch
#>
function Set-WEMAppLockerRule {
[CmdletBinding()]
param(
[Parameter(Mandatory=$True, ValueFromPipeline=$True, ValueFromPipelineByPropertyName=$True)]
[int]$IdRule,
[Parameter(Mandatory=$False)]
[string]$Name,
[Parameter(Mandatory=$False)]
[string]$Description = "",
[Parameter(Mandatory=$False)][ValidateSet("Allow", "Deny")]
[string]$Permission,
[Parameter(Mandatory=$False)]
[int[]]$IdADObjects,
[Parameter(Mandatory=$False)]
[pscustomobject]$ConditionObject,
[Parameter(Mandatory=$False)]
[pscustomobject[]]$ExceptionObjects,
[Parameter(Mandatory=$True)]
[System.Data.SqlClient.SqlConnection]$Connection
)
process {
# grab the orginal rule
$origObject = Get-WEMAppLockerRule -Connection $Connection -IdRule $IdRule
$Type = $origObject.CollectionType
# abort if the rule does not exist
if (-not $origObject) {
Write-Error "No rule with id $($IdRule) found in the database"
break
}
# check if the conditionobject parameter is set and has content
if ([bool]($MyInvocation.BoundParameters.Keys -match 'ConditionObject') -and -not $ConditionObject) {
Write-Error "A ConditionObject cannot be removed from a rule"
break
}
# check if the conditionobject is actually that
if ([bool]($MyInvocation.BoundParameters.Keys -match 'ConditionObject') -and -not ($ConditionObject.pstypenames[0] -like "Citrix.WEMSDK.AppLockerRule*Condition")) {
Write-Error "ConditionObject is not the correct type. Please provide a valid AppLockerRuleConditionObject"
break
}
# check if exceptions are valid for the type of condition that is requested
if ([bool]($MyInvocation.BoundParameters.Keys -match 'ExceptionObjects') -and $ExceptionObjects) {
if (([bool]($MyInvocation.BoundParameters.Keys -match 'ConditionObject') -and $ConditionObject.pstypenames[0] -ne "Citrix.WEMSDK.AppLockerRulePathCondition") -or ([bool]($MyInvocation.BoundParameters.Keys -notmatch 'ConditionObject') -and $origObject.RuleType -ne "PathCondition")) {
Write-Error "ExceptionObject(s) are only valid in combination with a PathCondition type"
break
} else {
# check if the exceptionobjects are actually that
foreach($ExceptionObject in $ExceptionObjects) {
if ($ExceptionObject -and -not ($ExceptionObject.pstypenames[0] -like "Citrix.WEMSDK.AppLockerRule*Condition")) {
Write-Error "ExceptionObject is not the correct type. Please provide a valid AppLockerRuleConditionObject"
break
}
}
}
}
# check if requested type matches with conditionobject
if ([bool]($MyInvocation.BoundParameters.Keys -match 'ConditionObject') -and $Type -eq "Executable" -and $ConditionObject.pstypenames[0] -eq "Citrix.WEMSDK.AppLockerRulePathCondition") {
if ($ConditionObject.Path.Substring($ConditionObject.Path.Length -2) -ne "\*" -and (@(".exe",".com") -notcontains [System.IO.Path]::GetExtension($ConditionObject.Path.Substring($ConditionObject.Path.LastIndexOf("\") + 1)))) {
Write-Error "For an Executable rule the Path Condition must be for a .exe or a .com file, or it must be a Path Condition"
break
}
}
if ([bool]($MyInvocation.BoundParameters.Keys -match 'ConditionObject') -and $Type -eq "Executable" -and $ConditionObject.pstypenames[0] -eq "Citrix.WEMSDK.AppLockerRuleHashCondition" -and $ConditionObject.Purpose -ne "Executable") {
Write-Error "For an Executable rule the Hash Condition purpose must be 'Executable'"
break
}
if ([bool]($MyInvocation.BoundParameters.Keys -match 'ConditionObject') -and $Type -eq "Windows Installer" -and $ConditionObject.pstypenames[0] -eq "Citrix.WEMSDK.AppLockerRulePathCondition") {
if ($ConditionObject.Path.Substring($ConditionObject.Path.Length -2) -ne "\*" -and (@(".msi",".msp",".mst") -notcontains [System.IO.Path]::GetExtension($ConditionObject.Path.Substring($ConditionObject.Path.LastIndexOf("\") + 1)))) {
Write-Error "For a Windows Installer rule the Path Condition must be for a .msi, a .msp or a .mst file, or it must be a Path Condition"
break
}
}
if ([bool]($MyInvocation.BoundParameters.Keys -match 'ConditionObject') -and $Type -eq "Windows Installer" -and $ConditionObject.pstypenames[0] -eq "Citrix.WEMSDK.AppLockerRuleHashCondition" -and $ConditionObject.Purpose -ne "Windows Installer") {
Write-Error "For an Windows Installer rule the Hash Condition purpose must be 'Windows Installer'"
break
}
if ([bool]($MyInvocation.BoundParameters.Keys -match 'ConditionObject') -and $Type -eq "Scripts" -and $ConditionObject.pstypenames[0] -eq "Citrix.WEMSDK.AppLockerRulePathCondition") {
if ($ConditionObject.Path.Substring($ConditionObject.Path.Length -2) -ne "\*" -and (@(".ps1",".bat",".cmd",".vbs",".js") -notcontains [System.IO.Path]::GetExtension($ConditionObject.Path.Substring($ConditionObject.Path.LastIndexOf("\") + 1)))) {
Write-Error "For a Scripts rule the Path Condition must be for a .ps1, a .bat, a .cmd, a .vbs or a .js file, or it must be a Path Condition"
break
}
}
if ([bool]($MyInvocation.BoundParameters.Keys -match 'ConditionObject') -and $Type -eq "Scripts" -and $ConditionObject.pstypenames[0] -eq "Citrix.WEMSDK.AppLockerRuleHashCondition" -and $ConditionObject.Purpose -ne "Scripts") {
Write-Error "For a Scripts rule the Hash Condition purpose must be 'Scripts'"
break
}
if ([bool]($MyInvocation.BoundParameters.Keys -match 'ConditionObject') -and $Type -eq "Packaged" -and $ConditionObject.pstypenames[0] -ne "Citrix.WEMSDK.AppLockerRulePublisherCondition") {
Write-Error "For an Packaged rule only a Publisher Condition is valid"
break
}
if ([bool]($MyInvocation.BoundParameters.Keys -match 'ConditionObject') -and $Type -eq "DLL" -and $ConditionObject.pstypenames[0] -eq "Citrix.WEMSDK.AppLockerRulePathCondition") {
if ($ConditionObject.Path.Substring($ConditionObject.Path.Length -2) -ne "\*" -and (@(".dll",".ocx") -notcontains [System.IO.Path]::GetExtension($ConditionObject.Path.Substring($ConditionObject.Path.LastIndexOf("\") + 1)))) {
Write-Error "For a DLL rule the Path Condition must be for a .dll or a .ocx file, or it must be a Path Condition"
break
}
}
if ([bool]($MyInvocation.BoundParameters.Keys -match 'ConditionObject') -and $Type -eq "DLL" -and $ConditionObject.pstypenames[0] -eq "Citrix.WEMSDK.AppLockerRuleHashCondition" -and $ConditionObject.Purpose -ne "DLL") {
Write-Error "For a DLL rule the Hash Condition purpose must be 'DLL'"
break
}
# check if the IdADObjects parameter is set and has content
if ([bool]($MyInvocation.BoundParameters.Keys -match 'idadobjects') -and -not $IdADObjects) {
Write-Error "You cannot remove all assignments from a rule"
break
}
# check if the ADObjects exist in the requested configuration
if ([bool]($MyInvocation.BoundParameters.Keys -match 'idadobjects')) {
foreach($IdADObject in $IdADObjects) {
$adObject = Get-WEMADUserObject -Connection $Connection -IdSite $IdSite -IdADObject $IdADObject
if (-not ($adObject)) {
Write-Error "Could not find an ADUserObject for IdADObject $($IdADObject)"
break
}
}
}
# build the query to update the rule
$updateFields = @()
$SQLQuery = "UPDATE AppLockerRules SET "
if ([bool]($MyInvocation.BoundParameters.Keys -match 'name') -and $origObject.Name -ne (ConvertTo-StringEscaped $Name)) {
$updateFields += "Name = '$(ConvertTo-StringEscaped $Name)'"
}
if ([bool]($MyInvocation.BoundParameters.Keys -match 'description') -and $origObject.Description -ne (ConvertTo-StringEscaped $Description)) {
$updateFields += "Description = '$(ConvertTo-StringEscaped $Description)'"
}
if ([bool]($MyInvocation.BoundParameters.Keys -match 'permission') -and $origObject.Permission -ne $Permission) {
$updateFields += "State = $($tableVUEMApplockerRulePermission[$Permission])"
}
# only update if any of the fields were updated
$isUpdated = $false
if($updateFields) {
$SQLQuery += "{0} " -f ($updateFields -join ", ")
$SQLQuery += "WHERE IdRule = $($IdRule)"
Write-Verbose "Query built: $($SQLQuery)"
$null = Invoke-SQL -Connection $Connection -Query $SQLQuery
# object is updated
$isUpdated = $true
} else {
Write-Verbose "No parameters to update the AppLockerRule were provided, checking ConditionObject, ExceptionObjects, and IdADObjects"
}
# checking ConditionObject
if ([bool]($MyInvocation.BoundParameters.Keys -match 'ConditionObject')) {
Write-Verbose "ConditionObject parameter was found, process ConditionObject"
# since the object is valid (this was checked earlier) delete the ConditionObject from the database and create the new one
# insert condition
switch ($ConditionObject.pstypenames[0]) {
"Citrix.WEMSDK.AppLockerRulePathCondition" {
# delete the old condition
Write-Verbose "Deleting PathCondition"
$SQLQuery = "DELETE FROM AppLockerRulePathConditions WHERE IdRule = $($IdRule) AND IsException = 0"
$null = Invoke-SQL -Connection $db -Query $SQLQuery
# build the query to insert the Object
$SQLQuery = "INSERT INTO AppLockerRulePathConditions (IdRule, Path, IsException, RevisionId, Reserved01) VALUES ($($IdRule),'$($ConditionObject.Path)',0,0,NULL)"
$null = Invoke-SQL -Connection $Connection -Query $SQLQuery
}
"Citrix.WEMSDK.AppLockerRulePublisherCondition" {
# delete the old condition
Write-Verbose "Deleting PpublisherCondition"
$SQLQuery = "DELETE FROM AppLockerRulePublisherConditions WHERE IdRule = $($IdRule) AND IsException = 0"
$null = Invoke-SQL -Connection $db -Query $SQLQuery
# build the query to insert the Object
$SQLQuery = "INSERT INTO AppLockerRulePublisherConditions (IdRule, FilePath, FileName, LowSection, HighSection, Product, Publisher, IsException, RevisionId, Reserved01) VALUES ($($IdRule),'$($ConditionObject.FilePath)','$($ConditionObject.FileName)','$($ConditionObject.LowSection)','$($ConditionObject.HighSection)','$($ConditionObject.Product)','$($ConditionObject.Publisher)',0,0,NULL)"
$null = Invoke-SQL -Connection $Connection -Query $SQLQuery
}
"Citrix.WEMSDK.AppLockerRuleHashCondition" {
# remove hashes from the old condition
$SQLQuery = "SELECT TOP (1) * FROM AppLockerRuleHashConditions WHERE IdRule = $($IdRule) AND IsException = 0 ORDER BY IdCondition DESC"
$result = Invoke-SQL -Connection $Connection -Query $SQLQuery
$vuemAppLockerCondition = $result.Tables.Rows
Write-Verbose "Deleting HashCondition hashes"
$SQLQuery = "DELETE FROM AppLockerRuleFileHashes WHERE IdCondition = $($vuemAppLockerCondition.IdCondition)"
$null = Invoke-SQL -Connection $Connection -Query $SQLQuery
Write-Verbose "Deleting HashCondition"
$SQLQuery = "DELETE FROM AppLockerRuleHashConditions WHERE IdRule = $($IdRule) AND IsException = 0"
$null = Invoke-SQL -Connection $Connection -Query $SQLQuery
# build the query to insert the Object
$SQLQuery = "INSERT INTO AppLockerRuleHashConditions (IdRule, IsException, RevisionId, Reserved01) VALUES ($($IdRule),0,0,NULL)"
$null = Invoke-SQL -Connection $Connection -Query $SQLQuery
# grab the new Object
$SQLQuery = "SELECT TOP (1) * FROM AppLockerRuleHashConditions WHERE IdRule = $($IdRule) ORDER BY IdCondition DESC"
$result = Invoke-SQL -Connection $Connection -Query $SQLQuery
$vuemAppLockerCondition = $result.Tables.Rows
# process hashes
foreach($hash in $ConditionObject.Hashes) {
$SQLQuery = "INSERT INTO AppLockerRuleFileHashes (IdCondition, HashAlgorithm, Hash, FileLength, RevisionId, Reserved01, FileName) VALUES ($($vuemAppLockerCondition.IdCondition),0,$($hash.Hash),$($hash.FileLength),0,NULL,'$($hash.FileName)')"
$null = Invoke-SQL -Connection $Connection -Query $SQLQuery
}
}
Default {}
}
# object is updated
$isUpdated = $true
}
# checking ExceptionObjects
if ([bool]($MyInvocation.BoundParameters.Keys -match 'ExceptionObjects')) {
Write-Verbose "ExceptionObjects parameter was found, process ExceptionObjects"
# delete the existing exceptionobjects (this also takes care of $null value)
Write-Verbose "Deleting PathCondition exceptions and PublisherCondition exceptions"
$SQLQuery = "DELETE FROM AppLockerRulePathConditions WHERE IdRule = $($IdRule) AND IsException = 1;DELETE FROM AppLockerRulePublisherConditions WHERE IdRule = $($IdRule) AND IsException = 1"
$null = Invoke-SQL -Connection $db -Query $SQLQuery
# grab Hash condition exceptions
$SQLQuery = "SELECT * FROM AppLockerRuleHashConditions WHERE IdRule = $($IdRule) AND IsException = 1"
$result = Invoke-SQL -Connection $db -Query $SQLQuery
foreach($row in $result.Tables.rows) {
Write-Verbose "Deleting Hashes for the HashCondition exception in condition $($row.IdCondition)"
$SQLQuery = "DELETE FROM AppLockerRuleFileHashes WHERE IdCondition = $($row.IdCondition)"
Invoke-SQL -Connection $Connection -Query $SQLQuery
}
# delete hash condition exceptions (this is now possible because the hashes are also deleted)
Write-Verbose "Deleting HashCondition exceptions"
$SQLQuery = "DELETE FROM AppLockerRuleHashConditions WHERE IdRule = $($IdRule) AND IsException = 1"
$null = Invoke-SQL -Connection $db -Query $SQLQuery
if ($ExceptionObjects) {
# create any new exceptionobjects
# insert exceptions
foreach($ExceptionObject in $ExceptionObjects) {
switch ($ExceptionObject.pstypenames[0]) {
"Citrix.WEMSDK.AppLockerRulePathCondition" {
# build the query to insert the Object
$SQLQuery = "INSERT INTO AppLockerRulePathConditions (IdRule, Path, IsException, RevisionId, Reserved01) VALUES ($($IdRule),'$($ExceptionObject.Path)',1,0,NULL)"
$null = Invoke-SQL -Connection $Connection -Query $SQLQuery
}
"Citrix.WEMSDK.AppLockerRulePublisherCondition" {
# build the query to insert the Object
$SQLQuery = "INSERT INTO AppLockerRulePublisherConditions (IdRule, FilePath, FileName, LowSection, HighSection, Product, Publisher, IsException, RevisionId, Reserved01) VALUES ($($IdRule),'$($ExceptionObject.FilePath)','$($ExceptionObject.FileName)','$($ExceptionObject.LowSection)','$($ExceptionObject.HighSection)','$($ExceptionObject.Product)','$($ExceptionObject.Publisher)',1,0,NULL)"
$null = Invoke-SQL -Connection $Connection -Query $SQLQuery
}
"Citrix.WEMSDK.AppLockerRuleHashCondition" {
# build the query to insert the Object
$SQLQuery = "INSERT INTO AppLockerRuleHashConditions (IdRule, IsException, RevisionId, Reserved01) VALUES ($($IdRule),1,0,NULL)"
$null = Invoke-SQL -Connection $Connection -Query $SQLQuery
# grab the new Object
$SQLQuery = "SELECT TOP (1) * FROM AppLockerRuleHashConditions WHERE IdRule = $($IdRule) AND IsException = 1 ORDER BY IdCondition DESC"
$result = Invoke-SQL -Connection $Connection -Query $SQLQuery
$vuemAppLockerException = $result.Tables.Rows
# process hashes
foreach($hash in $ExceptionObject.Hashes) {
$SQLQuery = "INSERT INTO AppLockerRuleFileHashes (IdCondition, HashAlgorithm, Hash, FileLength, RevisionId, Reserved01, FileName) VALUES ($($vuemAppLockerException.IdCondition),0,$($hash.Hash),$($hash.FileLength),0,NULL,'$($hash.FileName)')"
$null = Invoke-SQL -Connection $Connection -Query $SQLQuery
}
}
Default {}
}
}
}
# object is updated
$isUpdated = $true
}
# checking Assignments
if ([bool]($MyInvocation.BoundParameters.Keys -match 'idadobjects')) {
Write-Verbose "IdADObjects parameter was found, process Assignments"
# adding new assignments
foreach($IdADObject in $IdADObject) {
$isAssigned = $false
foreach($assignment in $origObject.Assignments) {
if ($assignment.IdADObject -eq $IdADObject) { $isAssigned = $true }
}
if (-not $isAssigned) {
# this is a new assignment: add it to the list in the database
Write-Verbose "New Assignment detected"
$SQLQuery = "INSERT INTO AppLockerRuleAssignments (IdSite, IdAppLockerRule, IdItem, RevisionId, Reserved01) VALUES ($($origObject.IdSite),$($IdRule),$($IdADObject),1,NULL)"
$null = Invoke-SQL -Connection $Connection -Query $SQLQuery
# object is updated
$isUpdated = $true
}
}
# removing redundant assignments
foreach($assignment in $origObject.Assignments) {
$isRedundant = $True
foreach($IdADObject in $IdADObjects) {
if ($IdADObject -eq $assignment.IdADObject) { $isRedundant = $false }
}
if ($isRedundant) {
# this assignment is redundant: remove it from the list in the database
Write-Verbose "Redundant Assignment detected"
$SQLQuery = "DELETE FROM AppLockerRuleAssignments WHERE IdSite = $($origObject.IdSite) AND IdAppLockerRule = $($IdRule) AND IdItem = $($assignment.IdADObject)"
$null = Invoke-SQL -Connection $Connection -Query $SQLQuery
# object is updated
$isUpdated = $true
}
}
}
if ($isUpdated) {
# object was updated so increase its version
$SQLQuery = "UPDATE AppLockerRules SET RevisionId = $($origObject.Version + 1) WHERE IdRule = $($IdRule)"
$null = Invoke-SQL -Connection $Connection -Query $SQLQuery
}
# grab the updated object
$updatedObject = Get-WEMAppLockerRule -Connection $Connection -IdRule $IdRule
# Updating the ChangeLog
New-ChangesLogEntry -Connection $Connection -IdSite $origObject.IdSite -IdElement $IdRule -ChangeType "Update" -ObjectName $updatedObject.Name -ObjectType "AppLocker Rule\$($tableVUEMAppLockerChangeLogType["$($tableVUEMAppLockerCollectionType[$updatedObject.CollectionType]).$($tableVUEMAppLockerRuleType[$updatedObject.RuleType])"])" -NewValue "N/A" -ChangeDescription $null -Reserved01 $null
}
}