This week, while delivering Microsoft course 20411D: Administering Windows Server 2012, I came up with an idea while delivering the chapter on encryption and advanced auditing. One of the issues that we as Network Administrators needs to be aware of when removing a user account or formatting a client is the use of EFS. When a user first encrypts a file or folder using EFS, a certificate is generated for EFS encryption. If you lose this certificate, the data is no longer accessible. One of my best practices has been to check for this certificate on the client prior to removing the account. That way you know to start hunting for those encrypted files.
This cmdlet is going to help me modify this practice. I’m going to do some more development with this code to also issue decrypt the files and folders.
This command was tested using the built in Domain Administrator account. This account is the Disaster Recovery Key for files that were EFS encrypted with a domain user account. Using this account allows you to still access these files. It is not a good practice to leave this account enabled for use. You may want to consider two alternative options.
1) Utilize a Data Recovery Agent
2) Disable EFS encryption in your environment.
For now, here is the Find-EFSEncryptedFiles cmdlet that I came up with last week
This cmdlet is going to help me modify this practice. I’m going to do some more development with this code to also issue decrypt the files and folders.
This command was tested using the built in Domain Administrator account. This account is the Disaster Recovery Key for files that were EFS encrypted with a domain user account. Using this account allows you to still access these files. It is not a good practice to leave this account enabled for use. You may want to consider two alternative options.
1) Utilize a Data Recovery Agent
2) Disable EFS encryption in your environment.
For now, here is the Find-EFSEncryptedFiles cmdlet that I came up with last week
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
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
199
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
|
Function Find-EFSEncryptedFiles
{
<#
.SYNOPSIS
Returns files and folders on clients that have the "encrypted" attribute set
on NTFS formatted partitions.
.DESCRIPTION
Scans a remote clients hard drive for all EFS encrypted files. This is only able
to search for files and folders on NTFS partitioned hard drives where the
Encrypted attribute is set.
.PARAMETER ComputerName
The name of the client to scan.
.PARAMETER SearchRoot
The default searchroot is the root of each fixed hard drive. To accelerate the
search, provide the path to a specific users storage location on the
hard drive.
.PARAMETER ErrorLogPath
The location of where to store the names of all clients that could not be
contacted.
.EXAMPLE
"Client1", "Client2", "Client3" | Find-EFSEncryptedFiles
Scans three different clients for EFS encrypted Files.
.EXAMPLE
"Client1", "Client2", "Client3" | Find-EFSEncryptedFiles -SearchRoot "C:\Users\jyoder\Documents\Restricted2"
Scans three different clients for EFS encrypted files, but with the root of the search at
"C:\Users\jyoder\Documents\Restricted2". This will accelerate the search.
.EXAMPLE
"Client1", "Client2", "Client3" | Find-EFSEncryptedFiles -Verbose -ErrorLogPath H:\temp\EncryptErrors.txt
This example provides the same results as Example 1, but also contains Verbose output and
an error log of all clients that could not be reached.
.EXAMPLE
Get-Content -Path C:\Temp\EncryptErrors.txt | Find-EFSEncryptedFiles
This example reads an error log from a previous run of this command. The error log
contains the names of the clients that could not be contacted the
first time the command was run.
.NOTES
===============================================================================
== Cmdlet: Find-EFSEncryptedFiles ==
== Author: Jason A. Yoder ==
== Company: MCTExpert of Arizona ==
== Date: June 14, 2014 ==
== Copyright: All rights reserved. ==
== Version: 1.0.0.0 ==
== Legal: The user assumes all responsibility and liability for the usage of ==
== this PowerShell code. MCTExpert of Arizona, Its officers, shareholders, ==
== owners, and their relatives are not liable for any damages. As with all ==
== code, review it and understand it prior to usage. It is recommended that ==
== this code be fully tested and validated in a test environment prior to ==
== usage in a production environment. ==
== ==
== Does this code make changes: NO ==
===============================================================================
#>
[cmdletbinding()]
Param(
[Parameter(Mandatory=$True,
ValueFromPipeline=$true)]
[String[]]$ComputerName,
[String]$SearchRoot = "",
[String]$ErrorLogPath
)
BEGIN
{
# If the user requests an Error Log to be generated, first verify
# the path for the file by creating it (or erasing it) and set it
# equal to $null.
#
# If the path is not valid, then display that the path is invalid.
# Terminate the command if the path is invalid.
If ($ErrorLogPath -ne "")
{
$ErrorLogAvailable = $False
Try
{
$null | Out-File -FilePath $ErrorLogPath -ErrorAction Stop
$ErrorLogAvailable = $True
}
Catch
{
$ColorHash = @{'ForegroundColor' = 'DarkRed'
'BackgroundColor' = 'Gray'}
Write-Host "Error: Log Path is invalid " @ColorHash
Write-Host "Find-EFSEncryptedFiles has terminated. " @ColorHash
Write-Host "Correct the Errorlog path. Refer to " @ColorHash
Write-Host "Get-Help Find-EFSEncryptedFile -Examples" @ColorHash
Write-Host "for more information. " @ColorHash
BREAK
}
}
} # END: BEGIN BLOCK
PROCESS{
# Work on each client, one at a time.
ForEach ($C in $Computername)
{
Write-Verbose "Connecting to $C"
Try
{
# Initiate the remote session to the client.
$S = New-PSSession -ComputerName $C -ErrorAction Stop
Invoke-Command -ScriptBlock {
Param($SearchRoot, $IncludeNetworkDrives)
# Collect the drive information
$Q = "Select DeviceID FROM win32_LogicalDisk WHERE DriveType = 3"
$Drives = Get-CimInstance -Query $Q
# This IF..ELSE block is used to determine the root of the search.
If ($SearchRoot -ne "")
{
If (Test-Path -Path $SearchRoot)
{
ForEach ($D in $Drives)
{
Get-ChildItem -Path $SearchRoot -Recurse -Attributes E |
Select-Object -Property FullName, Name
}
}
Else
{
$ColorHash = @{'ForegroundColor' = 'DarkRed'
'BackgroundColor' = 'Yellow'}
Write-Host "The SearchRoot $SearchRoot does not exists on $(Hostname)" @ColorHash
}
}
Else
{
ForEach ($D in $Drives)
{
Get-ChildItem -Path "$($D.DeviceID)\" -Recurse -Attributes E |
Select-Object -Property FullName, Name
}
}
} -Session $S -ArgumentList $SearchRoot, $IncludeNetworkDrives |
Select-Object -Property Name, FullName, PSComputerName
$S | Remove-PSSession
} # END: TRY BLOCK
Catch
{
Write-Host "Computer $C is offline" -ForegroundColor Red -BackgroundColor DarkRed
If (($ErrorLogPath -ne "") -and ($ErrorLogAvailable -eq $true))
{
$C | Out-File -FilePath $ErrorLogPath -Append
}
}
} # END: ForEach ($C in $Computername)
} #End: PROCESS BLOCK
END{}
} # END: Function Find-EFSEncryptedFiles
|
Comments