From 609e54dab1848e22d58e8b2d01ede4199dc7cb33 Mon Sep 17 00:00:00 2001 From: Martin Vokurek Date: Tue, 5 Jun 2018 09:58:00 +0200 Subject: [PATCH] Fix for Issues #10 and #11 (#17) - Fixed issue which caused xBLAutoBitlocker to incorrectly detect Fixed vs Removable volumes (issue #11). - Fixed issue which made xBLAutoBitlocker unable to encrypt volumes with drive letters assigned (issue #10). --- .../MSFT_xBLAutoBitlocker.psm1 | 38 +- README.md | 5 +- Tests/Unit/MSFT_xBLAutoBitlocker.tests.ps1 | 365 ++++++++++++++++++ 3 files changed, 401 insertions(+), 7 deletions(-) create mode 100644 Tests/Unit/MSFT_xBLAutoBitlocker.tests.ps1 diff --git a/DSCResources/MSFT_xBLAutoBitlocker/MSFT_xBLAutoBitlocker.psm1 b/DSCResources/MSFT_xBLAutoBitlocker/MSFT_xBLAutoBitlocker.psm1 index 74a1d6b..45d773f 100644 --- a/DSCResources/MSFT_xBLAutoBitlocker/MSFT_xBLAutoBitlocker.psm1 +++ b/DSCResources/MSFT_xBLAutoBitlocker/MSFT_xBLAutoBitlocker.psm1 @@ -70,7 +70,8 @@ function Get-TargetResource $UsedSpaceOnly ) - #Load helper module Import-Module "$((Get-Item -LiteralPath "$($PSScriptRoot)").Parent.Parent.FullName)\Misc\xBitlockerCommon.psm1" -Verbose:0 + #Load helper module + Import-Module "$((Get-Item -LiteralPath "$($PSScriptRoot)").Parent.Parent.FullName)\Misc\xBitlockerCommon.psm1" -Verbose:0 CheckForPreReqs @@ -151,8 +152,9 @@ function Set-TargetResource [System.Boolean] $UsedSpaceOnly ) - - #Load helper module Import-Module "$((Get-Item -LiteralPath "$($PSScriptRoot)").Parent.Parent.FullName)\Misc\xBitlockerCommon.psm1" -Verbose:0 + + #Load helper module + Import-Module "$((Get-Item -LiteralPath "$($PSScriptRoot)").Parent.Parent.FullName)\Misc\xBitlockerCommon.psm1" -Verbose:0 CheckForPreReqs @@ -254,7 +256,8 @@ function Test-TargetResource $UsedSpaceOnly ) - #Load helper module Import-Module "$((Get-Item -LiteralPath "$($PSScriptRoot)").Parent.Parent.FullName)\Misc\xBitlockerCommon.psm1" -Verbose:0 + #Load helper module + Import-Module "$((Get-Item -LiteralPath "$($PSScriptRoot)").Parent.Parent.FullName)\Misc\xBitlockerCommon.psm1" -Verbose:0 CheckForPreReqs @@ -372,10 +375,35 @@ function GetAutoBitlockerStatus { [Hashtable]$returnValue = @{} + # Convert DriveType into values returned by Win32_EncryptableVolume.VolumeType + switch ($DriveType) + { + 'Fixed' + { + $driveTypeValue = 1 + } + 'Removable' + { + $driveTypeValue = 2 + } + } + foreach ($blv in $allBlvs) { $vol = $null - $vol = Get-Volume -Path $blv.MountPoint -ErrorAction SilentlyContinue | where {$_.DriveType -like $DriveType} + + $encryptableVolumes = Get-CimInstance -Namespace 'root\cimv2\security\microsoftvolumeencryption' -Class Win32_Encryptablevolume -ErrorAction SilentlyContinue + + if (Split-Path -Path $blv.MountPoint -IsAbsolute) + { + # MountPoint is a Drive Letter + $vol = $encryptableVolumes | Where-Object {($_.DriveLetter -eq $blv.Mountpoint) -and ($_.VolumeType -eq $driveTypeValue)} + } + else + { + # MountPoint is a path + $vol = $encryptableVolumes | Where-Object {($_.DeviceID -eq $blv.Mountpoint) -and ($_.VolumeType -eq $driveTypeValue)} + } if ($vol -ne $null) { diff --git a/README.md b/README.md index da64451..ac630ab 100644 --- a/README.md +++ b/README.md @@ -59,7 +59,7 @@ It does not work on Operating System drives. **xBLAutoBitlocker** has the following properties. Where no description is listed, properties correspond directly to [Enable-Bitlocker](http://technet.microsoft.com/en-us/library/jj649837.aspx) parameters. -* *DriveType:The type of volume, as reported by Get-Volume, to auto apply Bitlocker to +* *DriveType:The type of volume to auto apply Bitlocker to. Valid values are "Fixed" or "Removable" * *PrimaryProtector:The primary protector type to be used for AutoBitlocker. Valid values are: "AdAccountOrGroupProtector", "PasswordProtector", "Pin", "RecoveryKeyProtector", "RecoveryPasswordProtector", "StartupKeyProtector", or "TpmProtector" * MinDiskCapacityGB:If specified, only disks this size or greater will auto apply Bitlocker @@ -132,7 +132,8 @@ Defaults to false. * Added `PowerShellVersion = '4.0'`, and updated copyright information, in the module manifest. * Fixed issue which caused Test to incorrectly succeed on fully decrypted volumes when correct Key Protectors were present ([issue #13](https://github.com/PowerShell/xBitlocker/issues/13)) - +* Fixed issue which caused xBLAutoBitlocker to incorrectly detect Fixed vs Removable volumes. ([issue #11](https://github.com/PowerShell/xBitlocker/issues/11)) +* Fixed issue which made xBLAutoBitlocker unable to encrypt volumes with drive letters assigned. ([issue #10](https://github.com/PowerShell/xBitlocker/issues/10)) ### 1.1.0.0 diff --git a/Tests/Unit/MSFT_xBLAutoBitlocker.tests.ps1 b/Tests/Unit/MSFT_xBLAutoBitlocker.tests.ps1 new file mode 100644 index 0000000..a164f3a --- /dev/null +++ b/Tests/Unit/MSFT_xBLAutoBitlocker.tests.ps1 @@ -0,0 +1,365 @@ +#region HEADER + +# Unit Test Template Version: 1.2.1 +$script:moduleRoot = Split-Path -Parent (Split-Path -Parent $PSScriptRoot) +if ( (-not (Test-Path -Path (Join-Path -Path $script:moduleRoot -ChildPath 'DSCResource.Tests'))) -or ` + (-not (Test-Path -Path (Join-Path -Path $script:moduleRoot -ChildPath 'DSCResource.Tests\TestHelper.psm1'))) ) +{ + & git @('clone','https://github.com/PowerShell/DscResource.Tests.git',(Join-Path -Path $script:moduleRoot -ChildPath 'DSCResource.Tests')) +} + +Import-Module -Name (Join-Path -Path $script:moduleRoot -ChildPath (Join-Path -Path 'DSCResource.Tests' -ChildPath 'TestHelper.psm1')) -Force + +$TestEnvironment = Initialize-TestEnvironment ` + -DSCModuleName 'xBitlocker' ` + -DSCResourceName 'MSFT_xBLAutoBitlocker' ` + -TestType Unit + +#endregion HEADER + +function Invoke-TestCleanup { + Restore-TestEnvironment -TestEnvironment $TestEnvironment +} + +# Begin Testing +try +{ + InModuleScope 'MSFT_xBLAutoBitlocker' { + + function Get-BitLockerVolume { + param + ( + [Parameter()] + [System.String[]] + $MountPoint + ) + } + + # Get-BitlockerVolume is used to obtain list of volumes in the system and their current encryption status + Mock ` + -CommandName Get-BitlockerVolume ` + -ModuleName 'MSFT_xBLAutoBitlocker' ` + -MockWith { + # Returns a collection of OS/Fixed/Removable disks with correct/incorrect removable status + return @( + @{ + # C: is OS drive + VolumeType = 'OperatingSystem' + MountPoint = 'C:' + CapacityGB = 500 + VolumeStatus = 'FullyEncrypted' + EncryptionPercentage = 100 + KeyProtector = @( + @{ + KeyProtectorType = 'Tpm' + }, + @{ + KeyProtectorType = 'RecoveryPassword' + } + ) + AutoUnlockEnabled = $null + ProtectionStatus = 'On' + }, + @{ + # D: is Fixed drive, incorrectly reporting as Removable to Bitlocker + VolumeType = 'Data' + MountPoint = 'D:' + CapacityGB = 500 + VolumeStatus = 'FullyDecrypted' + EncryptionPercentage = 0 + KeyProtector = @( + ) + AutoUnlockEnabled = $null + ProtectionStatus = 'Off' + }, + @{ + # E: is Fixed drive, correctly reporting as Fixed to Bitlocker + VolumeType = 'Data' + MountPoint = 'E:' + CapacityGB = 50 + VolumeStatus = 'FullyDecrypted' + EncryptionPercentage = 0 + KeyProtector = @( + ) + AutoUnlockEnabled = $null + ProtectionStatus = 'Off' + } + @{ + # F: is a Removable drive thumb drive, correctly reporting as Removable to Bitlocker + VolumeType = 'Data' + MountPoint = 'F:' + CapacityGB = 500 + VolumeStatus = 'FullyDecrypted' + EncryptionPercentage = 0 + KeyProtector = @( + ) + AutoUnlockEnabled = $null + ProtectionStatus = 'Off' + }, + @{ + # 1 is Fixed drive, incorrectly reporting as Removable to Bitlocker + VolumeType = 'Data' + MountPoint = '\\?\Volume{00000000-0000-0000-0000-000000000001}\' + CapacityGB = 500 + VolumeStatus = 'FullyDecrypted' + EncryptionPercentage = 0 + KeyProtector = @( + ) + AutoUnlockEnabled = $null + ProtectionStatus = 'Off' + }, + @{ + # 2 is Fixed drive, correctly reporting as Fixed to Bitlocker + VolumeType = 'Data' + MountPoint = '\\?\Volume{00000000-0000-0000-0000-000000000002}\' + CapacityGB = 500 + VolumeStatus = 'FullyDecrypted' + EncryptionPercentage = 0 + KeyProtector = @( + ) + AutoUnlockEnabled = $null + ProtectionStatus = 'Off' + } + @{ + # 3 is a Removable drive thumb drive, correctly reporting as Removable to Bitlocker + VolumeType = 'Data' + MountPoint = '\\?\Volume{00000000-0000-0000-0000-000000000003}\' + CapacityGB = 50 + VolumeStatus = 'FullyDecrypted' + EncryptionPercentage = 0 + KeyProtector = @( + ) + AutoUnlockEnabled = $null + ProtectionStatus = 'Off' + } + ) + } + + # Get-Volume evaluates volume removable status correctly + # This was used in broken version of the module, replaced in Issue #11 by Win32_EncryptableVolume class + Mock ` + -CommandName Get-Volume ` + -ModuleName 'MSFT_xBLAutoBitlocker' ` + -MockWith { + # Returns a collection of OS/Fixed/Removable disks with correct/incorrect removable status + + switch ($Path) + { + '\\?\Volume{00000000-0000-0000-0000-000000000001}\' + { + return @{ + # D: is Fixed drive, incorrectly reporting as Removable to Bitlocker + DriveLetter = '' + Path = '\\?\Volume{00000000-0000-0000-0000-000000000001}\' + DriveType = 'Fixed' + } + } + '\\?\Volume{00000000-0000-0000-0000-000000000002}\' + { + return @{ + # 2 is Fixed drive, correctly reporting as Fixed to Bitlocker + DriveLetter = '' + Path = '\\?\Volume{00000000-0000-0000-0000-000000000002}\' + DriveType = 'Fixed' + } + } + '\\?\Volume{00000000-0000-0000-0000-000000000003}\' + { + return @{ + # 3 is a Removable drive, correctly reporting as Fixed to Bitlocker + DriveLetter = '' + Path = '\\?\Volume{00000000-0000-0000-0000-000000000003}\' + DriveType = 'Removable' + } + } + default + { + throw "No MSFT_Volume objects found with property 'Path' equal to '$Path'. Verify the value of the property and retry." + } + } + } + + Mock ` + -CommandName Get-CimInstance ` + -ModuleName 'MSFT_xBLAutoBitlocker' ` + -MockWith { + # Returns a collection of OS/Fixed/Removable disks with correct/incorrect removable status + return @( + @{ + # C: is OS drive + DriveLetter = 'C:' + VolumeType=0 + DeviceID='\\?\Volume{00000000-0000-0000-0000-000000000000}\' + + }, + @{ + # D: is Fixed drive, incorrectly reporting as Removable to Bitlocker + DriveLetter = 'D:' + VolumeType=2 + DeviceID='\\?\Volume{00000000-0000-0000-0000-000000000004}\' + + }, + @{ + # E: is Fixed drive, correctly reporting as Fixed to Bitlocker + DriveLetter = 'E:' + VolumeType=1 + DeviceID='\\?\Volume{00000000-0000-0000-0000-000000000005}\' + + }, + @{ + # F: is a Removable drive, correctly reporting as Fixed to Bitlocker + DriveLetter = 'F:' + VolumeType=2 + DeviceID='\\?\Volume{00000000-0000-0000-0000-000000000006}\' + }, + @{ + # 1 is Fixed drive, incorrectly reporting as Removable to Bitlocker + DriveLetter = '' + VolumeType=2 + DeviceID='\\?\Volume{00000000-0000-0000-0000-000000000001}\' + }, + @{ + # 2 is Fixed drive, correctly reporting as Fixed to Bitlocker + DriveLetter = '' + VolumeType=1 + DeviceID='\\?\Volume{00000000-0000-0000-0000-000000000002}\' + }, + @{ + # 3 is a Removable drive, correctly reporting as Fixed to Bitlocker + DriveLetter = '' + VolumeType=2 + DeviceID='\\?\Volume{00000000-0000-0000-0000-000000000003}\' + } + + ) + } + + Describe 'MSFT_xBLAutoBitlocker\GetAutoBitlockerStatus' { + + Context 'When Volume C: Reports as OS Volume' { + + It 'Should Not Be In The List of Eligible Fixed Volumes' { + (GetAutoBitlockerStatus -DriveType 'Fixed' -PrimaryProtector TpmProtector|Select-Object -ExpandProperty Keys)|Should -Not -Contain 'C:' + } + + It 'Should Not Be In The List of Eligible Removable Volumes' { + (GetAutoBitlockerStatus -DriveType 'Removable' -PrimaryProtector TpmProtector|Select-Object -ExpandProperty Keys)|Should -Not -Contain 'C:' + } + } + + Context 'When Volume D: Reports Fixed to OS, but Removable to Bitlocker' { + + It 'Should Not Be In The List of Eligible Fixed Volumes' { + (GetAutoBitlockerStatus -DriveType 'Fixed' -PrimaryProtector RecoveryPasswordProtector|Select-Object -ExpandProperty Keys)|Should -Not -Contain 'D:' + } + + It 'Should Be In The List of Eligible Removable Volumes' { + (GetAutoBitlockerStatus -DriveType 'Removable' -PrimaryProtector RecoveryPasswordProtector|Select-Object -ExpandProperty Keys)|Should -Contain 'D:' + } + } + + Context 'When Volume E: Reports Fixed to OS and Bitlocker' { + + It 'Should Be In The List of Eligible Fixed Volumes' { + (GetAutoBitlockerStatus -DriveType 'Fixed' -PrimaryProtector RecoveryPasswordProtector|Select-Object -ExpandProperty Keys)|Should -Contain 'E:' + } + + It 'Should Not Be In The List of Eligible Removable Volumes' { + (GetAutoBitlockerStatus -DriveType 'Removable' -PrimaryProtector RecoveryPasswordProtector|Select-Object -ExpandProperty Keys)|Should -Not -Contain 'E:' + } + } + + Context 'When Volume F: Reports as Removable to OS and Bitlocker' { + + It 'Should Not Be In The List of Eligible Fixed Volumes' { + (GetAutoBitlockerStatus -DriveType 'Fixed' -PrimaryProtector RecoveryPasswordProtector|Select-Object -ExpandProperty Keys)|Should -Not -Contain 'F:' + } + + It 'Should Be In The List of Eligible Removable Volumes' { + (GetAutoBitlockerStatus -DriveType 'Removable' -PrimaryProtector RecoveryPasswordProtector|Select-Object -ExpandProperty Keys)|Should -Contain 'F:' + } + } + + Context 'When Volume \\?\Volume{00000000-0000-0000-0000-000000000001}\ Reports Fixed to OS, but Removable to Bitlocker' { + + It 'Should Not Be In The List of Eligible Fixed Volumes' { + (GetAutoBitlockerStatus -DriveType 'Fixed' -PrimaryProtector RecoveryPasswordProtector|Select-Object -ExpandProperty Keys)|Should -Not -Contain '\\?\Volume{00000000-0000-0000-0000-000000000001}\' + } + + It 'Should Be In The List of Eligible Removable Volumes' { + (GetAutoBitlockerStatus -DriveType 'Removable' -PrimaryProtector RecoveryPasswordProtector|Select-Object -ExpandProperty Keys)|Should -Contain '\\?\Volume{00000000-0000-0000-0000-000000000001}\' + } + } + + Context 'When Volume \\?\Volume{00000000-0000-0000-0000-000000000002}\ Reports Fixed to OS and Bitlocker' { + + It 'Should Be In The List of Eligible Fixed Volumes' { + (GetAutoBitlockerStatus -DriveType 'Fixed' -PrimaryProtector RecoveryPasswordProtector|Select-Object -ExpandProperty Keys)|Should -Contain '\\?\Volume{00000000-0000-0000-0000-000000000002}\' + } + + It 'Should Not Be In The List of Eligible Removable Volumes' { + (GetAutoBitlockerStatus -DriveType 'Removable' -PrimaryProtector RecoveryPasswordProtector|Select-Object -ExpandProperty Keys)|Should -Not -Contain '\\?\Volume{00000000-0000-0000-0000-000000000002}\' + } + } + + Context 'When Volume \\?\Volume{00000000-0000-0000-0000-000000000003}\ Reports as Removable to OS and Bitlocker' { + + It 'Should Not Be In The List of Eligible Fixed Volumes' { + (GetAutoBitlockerStatus -DriveType 'Fixed' -PrimaryProtector RecoveryPasswordProtector|Select-Object -ExpandProperty Keys)|Should -Not -Contain '\\?\Volume{00000000-0000-0000-0000-000000000003}\' + } + + It 'Should Be In The List of Eligible Removable Volumes' { + (GetAutoBitlockerStatus -DriveType 'Removable' -PrimaryProtector RecoveryPasswordProtector|Select-Object -ExpandProperty Keys)|Should -Contain '\\?\Volume{00000000-0000-0000-0000-000000000003}\' + } + } + + Context 'When MinDiskCapacity Parameter is Defined at 100 GB for Fixed Disks' { + + It 'Should Exclude E: from The List of Eligible Fixed Volumes' { + (GetAutoBitlockerStatus -DriveType 'Fixed' -PrimaryProtector RecoveryPasswordProtector -MinDiskCapacityGB 100|Select-Object -ExpandProperty Keys)|Should -Not -Contain 'E:' + } + + It 'Should Include Volume \\?\Volume{00000000-0000-0000-0000-000000000002}\ In The List of Eligible Removable Volumes' { + (GetAutoBitlockerStatus -DriveType 'Fixed' -PrimaryProtector RecoveryPasswordProtector -MinDiskCapacityGB 100|Select-Object -ExpandProperty Keys)|Should -Contain '\\?\Volume{00000000-0000-0000-0000-000000000002}\' + } + } + + Context 'When MinDiskCapacity Parameter is Not Defined for Fixed Disks' { + + It 'Should Include E: In The List of Eligible Fixed Volumes' { + (GetAutoBitlockerStatus -DriveType 'Fixed' -PrimaryProtector RecoveryPasswordProtector|Select-Object -ExpandProperty Keys)|Should -Contain 'E:' + } + + It 'Should Include Volume \\?\Volume{00000000-0000-0000-0000-000000000002}\ In The List of Eligible Removable Volumes' { + (GetAutoBitlockerStatus -DriveType 'Fixed' -PrimaryProtector RecoveryPasswordProtector|Select-Object -ExpandProperty Keys)|Should -Contain '\\?\Volume{00000000-0000-0000-0000-000000000002}\' + } + } + + Context 'When MinDiskCapacity Parameter is Defined at 100 GB for Removable Disks' { + + It 'Should Exclude \\?\Volume{00000000-0000-0000-0000-000000000003}\ from The List of Eligible Fixed Volumes' { + (GetAutoBitlockerStatus -DriveType 'Removable' -PrimaryProtector RecoveryPasswordProtector -MinDiskCapacityGB 100|Select-Object -ExpandProperty Keys)|Should -Not -Contain '\\?\Volume{00000000-0000-0000-0000-000000000003}\' + } + + It 'Should Include F: In The List of Eligible Removable Volumes' { + (GetAutoBitlockerStatus -DriveType 'Removable' -PrimaryProtector RecoveryPasswordProtector -MinDiskCapacityGB 100|Select-Object -ExpandProperty Keys)|Should -Contain 'F:' + } + } + + Context 'When MinDiskCapacity Parameter is Not Defined for Fixed Disks' { + + It 'Should Include \\?\Volume{00000000-0000-0000-0000-000000000003}\ In The List of Eligible Fixed Volumes' { + (GetAutoBitlockerStatus -DriveType 'Removable' -PrimaryProtector RecoveryPasswordProtector|Select-Object -ExpandProperty Keys)|Should -Contain '\\?\Volume{00000000-0000-0000-0000-000000000003}\' + } + + It 'Should Include F: In The List of Eligible Removable Volumes' { + (GetAutoBitlockerStatus -DriveType 'Removable' -PrimaryProtector RecoveryPasswordProtector|Select-Object -ExpandProperty Keys)|Should -Contain 'F:' + } + } + } + } +} +finally +{ + Invoke-TestCleanup +}