-
Notifications
You must be signed in to change notification settings - Fork 2
/
file.psm1
361 lines (333 loc) · 12.7 KB
/
file.psm1
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
function Disable-Access {
<#
.SYNOPSIS
Deny student group permission to a file.
.DESCRIPTION
Add an NTFS Deny ACL to a given file for students to block their access.
A deny rule supercedes any allow rule.
.EXAMPLE
PS C:\> \\<server\<share>\<Path> | Disable-Access | Convertto-html | Out-File "Report.html"
Generate a report that lists the files students have been blocked from using.
#>
[CmdletBinding()]
Param(
[Parameter(ValueFromPipeline,
ValueFromPipelineByPropertyName,
Position = 0)]
[String[]]
$Path
, # AD identity
[Parameter(ValueFromPipelineByPropertyName,
Position = 1)]
[string]
$Identity = 'AllStudents'
)
Begin {
$Deny = New-Object -TypeName System.Security.AccessControl.FileSystemAccessRule -ArgumentList $Identity, 'FullControl', 'Deny'
}
Process {
$Path | Get-Acl | foreach-object {
$psitem.SetAccessRule($Deny)
try { $psitem | Set-acl }
catch {
Throw "Failed to set permission: $($psitem.path)"
}
Get-Item $psitem.Path | Write-Output
}
}
}
function Enable-Access {
<#
.SYNOPSIS
Remove "Deny" permission added by "Deny-Access"
.DESCRIPTION
Remove the NTFS Deny ACL for a given item for students access.
Does not test that users get access permission. See Add-Access
.EXAMPLE
PS C:\> \\<server\<share>\<Path> | Enable-Access | Convertto-html | Out-File "Report.html"
Generate a report that lists the item students have been blocked from using.
#>
[CmdletBinding()]
Param(
[Parameter(ValueFromPipeline,
ValueFromPipelineByPropertyName,
Position = 0)]
[String[]]
$Path
, # AD identity
[Parameter(ValueFromPipelineByPropertyName,
Position = 1)]
[string]
$Identity = 'AllStudents'
)
Begin {
$Rule = New-Object -TypeName System.Security.AccessControl.FileSystemAccessRule -ArgumentList $Identity, 'FullControl', 'Deny'
}
Process {
$Path | Get-Acl | foreach-object {
$psitem.RemoveAccessRule($Rule) > $null
try { $psitem | Set-acl }
catch {
Throw "Failed remove Deny permission: $($psitem.path)"
}
Get-Item $psitem.Path | Write-Output
}
}
End {
Write-Warning "Enable-StudentAccess will remove 'Deny' permission set by Disable-StudentAccess. See Add-Access"
}
}
function Add-Access {
<#
.SYNOPSIS
Add "Allow" permission to target path.
.DESCRIPTION
Add the NTFS Allow ACL for a given item for students access.
Any deny rule will supercede this. See Enable-Access.
.PARAMETER Inherit
Choose to edit a folder ACL or all files within the folder
Set the "Applies to" contition for child items when All files
.EXAMPLE
Add-Access .\en-US\
By default allow students to read permission to the folder, subfolder and files.
.EXAMPLE
Add-Access .\en-US\ -Inherit ThisFolder
Allow students to read permission to this folder folder only.
Useful to only allow the account to check further permission,
this way you can add-access to files below this tree and access-based-enumeration will
hide them from the user.
.EXAMPLE
Add-Access .\en-US\ -Identity '2016 Students'
Specify the Active Directory identiy name to set access for;
Directory: N:\Documents\src\ps-helper
Mode LastWriteTime Length Name
---- ------------- ------ ----
d----- 19/10/2016 15:33 en-US
.EXAMPLE
PS C:\> \\<server\<share>\<Path> | Add-Access | Convertto-html | Out-File "Report.html"
Generate a report that lists the items students have been allowed to aceess.
#>
[CmdletBinding()]
Param(
[Parameter(ValueFromPipeline,
ValueFromPipelineByPropertyName,
Position = 0
)]
[String[]]
$Path
, # AD identity to grant access
[Parameter(ValueFromPipelineByPropertyName,
Position = 1)]
[string[]]
$Identity = 'AllStudents'
, # keyword access permission levels
[System.Security.AccessControl.FileSystemRights]
$Access = 'ReadAndExecute'
, #
[ValidateSet('All','ThisFolder')]
[string]
$Inherit = 'All'
)
Begin {
switch ($inherit) {
'ThisFolder' { $Inherritance = @('None') }
Default { $Inherritance = @('ContainerInherit', 'ObjectInherit') }
}
$FolderRule = New-Object System.Collections.ArrayList
$FileRule = New-Object System.Collections.ArrayList
if($Access -eq 'Write'){
$Access = 'Write', 'ReadAndExecute'
}
foreach($id in $Identity){
$FolderRule.Add( (New-Object -TypeName System.Security.AccessControl.FileSystemAccessRule -ArgumentList $id, $Access, $Inherritance, 'None', 'Allow') ) > $null
$FileRule.Add( (New-Object -TypeName System.Security.AccessControl.FileSystemAccessRule -ArgumentList $id, $Access, 'Allow') ) > $null
}
}
Process {
$Path | Get-Acl | foreach-object {
$acl = $PSItem
$item = Get-Item $PSItem.path
try {
if ( $item -is [System.IO.DirectoryInfo] ){
foreach($rule in $FolderRule){
$acl.SetAccessRule($rule)
}
} else {
foreach($rule in $FileRule){
$acl.SetAccessRule($rule)
}
}
$acl | Set-acl
}
catch {
Throw "Failed to add permission: $($acl.path)"
}
Write-Output $item
}
}
}
function Remove-Access {
<#
.SYNOPSIS
Remove "Allow" permission added by "Add-StudentAccess"
.DESCRIPTION
Remove the NTFS Allow ACL for a given item for students access.
.EXAMPLE
PS C:\> \\<server\<share>\<Path> | Remove-StudentAccess | Convertto-html | Out-File "Report.html"
Generate a report that lists the items students have been blocked from using.
#>
[CmdletBinding(SupportsShouldProcess=$true)]
Param(
[Parameter(ValueFromPipeline,ValueFromPipelineByPropertyName,
Position = 0)]
[String[]]
$Path
, # AD identity to remove access
[Parameter(ValueFromPipelineByPropertyName,
Position = 1)]
[string]
$Identity = 'AllStudents'
)
Begin {
}
Process {
$Path | Get-Acl | foreach-object {
$Rule = $psitem.Access | Where-Object { ($_.IdentityReference -like "*$Identity") -and ($_.AccessControlType -eq 'Allow') -and ($_.IsInherited -eq $false)}
$psitem.RemoveAccessRule($Rule) > $null
try {
if($PSCmdlet.ShouldProcess($psitem.path, "Remove ACL: $($Rule.IdentityReference)")){
$psitem | Set-acl
} else {
return
}
}
catch {
Throw "Failed to remove permission: $($psitem.path)"
}
Get-Item $psitem.Path | Write-Output
}
}
}
function Show-Access {
<#
.SYNOPSIS
Display the ACL information for given files or folders.
.DESCRIPTION
Wraps Get-ACL to select the access list while retaining the file path being inspected.
Useful for Group-Object inspecting access controls.
This function is intended for interactive use inspecting a network share, as such it breaks best practice of avoiding the use of format-* commands.
.EXAMPLE
Show-Access '.\INFO.lnk'
Path IdentityReference IsInherited AccessControlType FileSystemRights
---- ----------------- ----------- ----------------- ----------------
\\ORG\Desktop\Start Menu\INFO.lnk ORG\Office False Allow ReadAndExecute, Synchronize
\\ORG\Desktop\Start Menu\INFO.lnk ORG\Support True Allow FullControl
\\ORG\Desktop\Start Menu\INFO.lnk NT AUTHORITY\SYSTEM True Allow FullControl
\\ORG\Desktop\Start Menu\INFO.lnk NT AUTHORITY\NETWORK SERVICE True Allow FullControl
\\ORG\Desktop\Start Menu\INFO.lnk BUILTIN\Administrator True Allow FullControl
\\ORG\Desktop\Start Menu\INFO.lnk ORG\Domain Admin True Allow FullControl
\\ORG\Desktop\Start Menu\INFO.lnk ORG\Share Administrator True Allow FullControl
Internal use of Format-Table to ease reading at the console.
.EXAMPLE
'.\.gitignore','.\asset.psm1' | show-access -NoFormat
Path : N:\Documents\helper\.gitignore
IdentityReference : ORG\jbennett
IsInherited : True
AccessControlType : Allow
FileSystemRights : FullControl
Path : N:\Documents\helper\.gitignore
IdentityReference : BUILTIN\Administrator
IsInherited : True
AccessControlType : Allow
FileSystemRights : FullControl
Use the NoFormat switch to bypass internal use of Format-Table for piping objects to further functions.
.NOTES
Should refactor the format switch into a custom native cmdlet format document.
#>
[CmdletBinding()]
Param(
[Parameter(Position = 0,Mandatory,ValueFromPipeline,ValueFromPipelineByPropertyName)]
[string]
$Path
, # Do not automatically pipe output to Format-Table
[switch]$NoFormat = $false
)
Process {
$output = $path |
get-acl |
Foreach {
$item = $psItem | select-Object -Expandproperty Access
$item | Add-Member -MemberType NoteProperty -Name Path -Value $psItem.path
Write-Output $Item
} |
select @{
name='Path'
expression = { $_.path.replace('Microsoft.PowerShell.Core\FileSystem::','') }
},
'IdentityReference',
'IsInherited',
'AccessControlType',
'FileSystemRights'
if($NoFormat){
Write-Output $output
} else{
$output | Format-Table | Write-Output
}
}
}
function Move-Work {
[cmdletBinding(SupportsShouldProcess)]
Param(
[Parameter(ValueFromPipeline,ValueFromPipelineByPropertyName)]
[String]
$Path = '.'
,
[Parameter(Mandatory)]
[string]
$Destination
,
[string]
$Filter = '*.docx'
,
[switch]
$Recurse
)
$source = Get-ChildItem -Recurse:$Recurse -Filter $Filter -Path $Path
if($PSCmdlet.ShouldProcess( $Destination, "Create New Directory" )){
New-Item -type Directory -Path $Destination -ErrorAction SilentlyContinue > $null
}
if($PSCmdlet.ShouldProcess( $source.length, "Move files to $Destination" )){
$source | Move-Item -Destination $Destination -PassThru -OutVariable target
}
Write-Output ([PSCustomObject]@{
Source = $source
Target = $target
Count = $source.length
})
}
Register-ArgumentCompleter -CommandName 'Add-Access','Remove-Access','Enable-Access','Disable-Access' -ParameterName 'Identity' -ScriptBlock {
param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameter)
[System.Collections.ArrayList]$preset = @(
'AllStudents'
'AllCAStudents'
'AllStaff'
'Office'
"'Site Management'"
"'Student Teachers'"
"'Teaching Staff'"
'Govenors'
"'Exam Candidate'"
)
[int]$year = (get-date).year
for( $i = $year; $i -ge ($year -6); $i -= 1){
$preset.add("'$i Students'") > $null
}
$preset |
Where-Object {
$psitem -match $wordToComplete
} |
ForEach-Object {
Write-Output ([System.Management.Automation.CompletionResult]::new($psitem, $psitem, 'ParameterValue', ("AD Name: " + $psitem)))
}
}
Export-ModuleMember -Function "*"