diff --git a/CHANGELOG.md b/CHANGELOG.md index 0bc6e25..bddb131 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,7 +7,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed -- ActiveDirectoryCSDsc +- `ActiveDirectoryCSDsc` - Automatically publish documentation to GitHub Wiki - Fixes [Issue #122](https://github.com/dsccommunity/ActiveDirectoryCSDsc/issues/122). - Revert Pester to non-prerelease. - Use DscResource.Base pre-release. @@ -22,7 +22,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - `Tests` - Migrate all tests to Pester 5. - Include module file in code coverage. - Add RootModule to Module psd1. -- AdcsAuthorityInformationAccess +- `AdcsAuthorityInformationAccess` - Removed `AllowRestartService` parameter from compared settings, force `Get-CaAiaUriList` to return unmangled `System.String[]` with single values. Fixes [Issue #128](https://github.com/dsccommunity/ActiveDirectoryCSDsc/issues/128) @@ -35,6 +35,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Move to Private function. - `Restart-ServiceIfExists` - Change Write-Verbose to Write-Debug. +- `AdcsOnlineResponder` + - Convert to class-based resource [#155](https://github.com/dsccommunity/ActiveDirectoryCSDsc/issues/155). ### Added diff --git a/RequiredModules.psd1 b/RequiredModules.psd1 index 4dfbf88..2a153c8 100644 --- a/RequiredModules.psd1 +++ b/RequiredModules.psd1 @@ -38,7 +38,12 @@ AllowPrerelease = $true } } - 'DscResource.Common' = 'latest' + 'DscResource.Common' = @{ + Version = 'latest' + Parameters = @{ + AllowPrerelease = $true + } + } # Analyzer rules 'DscResource.AnalyzerRules' = 'latest' diff --git a/source/ActiveDirectoryCSDsc.psd1 b/source/ActiveDirectoryCSDsc.psd1 index 745d0e1..6fbf6c5 100644 --- a/source/ActiveDirectoryCSDsc.psd1 +++ b/source/ActiveDirectoryCSDsc.psd1 @@ -27,7 +27,7 @@ FunctionsToExport = @() # Cmdlets to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no cmdlets to export. - CmdletsToExport = @() + CmdletsToExport = '*' # Variables to export from this module VariablesToExport = @() diff --git a/source/Classes/020.AdcsOnlineResponder.ps1 b/source/Classes/020.AdcsOnlineResponder.ps1 new file mode 100644 index 0000000..3b0fb65 --- /dev/null +++ b/source/Classes/020.AdcsOnlineResponder.ps1 @@ -0,0 +1,135 @@ +<# + .SYNOPSIS + The `AdcsOnlineResponder` DSC resource is used to configure the + ADCS Online Responder after the feature has been installed on the server. + + .DESCRIPTION + This resource can be used to install an ADCS Online Responder after the feature + has been installed on the server. + Using this DSC Resource to configure an ADCS Certificate Authority assumes that + the ```ADCS-Online-Responder``` feature has already been installed. + + .PARAMETER IsSingleInstance + Specifies the resource is a single instance, the value must be 'Yes'. + + .PARAMETER Credential + If the Online Responder service is configured to use Standalone certification authority, + then an account that is a member of the local Administrators on the CA is required. If + the Online Responder service is configured to use an Enterprise CA, then an account that + is a member of Domain Admins is required. + + .PARAMETER Ensure + Specifies whether the Online Responder feature should be installed or uninstalled. + + .PARAMETER Reasons + Returns the reason a property is not in desired state. +#> + +[DscResource(RunAsCredential = 'NotSupported')] +class AdcsOnlineResponder : ResourceBase +{ + [DscProperty(Key)] + [System.String] + $IsSingleInstance = 'Yes' + + [DscProperty(Mandatory)] + [System.Management.Automation.PSCredential] + [System.Management.Automation.Credential()] + $Credential + + [DscProperty()] + [Ensure] + $Ensure = [Ensure]::Present + + [DscProperty(NotConfigurable)] + [AdcsReason[]] + $Reasons + + AdcsOnlineResponder () : base ($PSScriptRoot) + { + # These properties will not be enforced. + $this.ExcludeDscProperties = @( + 'IsSingleInstance' + 'Credential' + ) + } + + [AdcsOnlineResponder] Get() + { + # Call the base method to return the properties. + return ([ResourceBase] $this).Get() + } + + # Base method Get() calls this method to get the current state as a Hashtable. + [System.Collections.Hashtable] GetCurrentState([System.Collections.Hashtable] $properties) + { + try + { + $null = Install-AdcsOnlineResponder -Credential $this.Credential -WhatIf + + return @{} + } + catch + { + if ($_.Exception.GetType().FullName -eq 'Microsoft.CertificateServices.Deployment.Common.OCSP.OnlineResponderSetupException') + { + return @{ + IsSingleInstance = $this.IsSingleInstance + } + } + + return New-InvalidOperationException -Message $this.localizedData.ErrorGetCurrentState -ErrorRecord $_ + } + } + + [void] Set() + { + # Call the base method to enforce the properties. + ([ResourceBase] $this).Set() + } + + <# + Base method Set() call this method with the properties that should be + enforced and that are not in desired state. + #> + hidden [void] Modify([System.Collections.Hashtable] $properties) + { + if ($properties.ContainsKey('Ensure') -and $properties.Ensure -eq [Ensure]::Absent) + { + try + { + $null = Uninstall-AdcsOnlineResponder -Force + } + catch + { + New-InvalidOperationException -Message $_.Exception.Message -ErrorRecord $_ + } + } + else + { + try + { + $null = Install-AdcsOnlineResponder -Credential $this.Credential -Force + } + catch + { + New-InvalidOperationException -Message $_.Exception.Message -ErrorRecord $_ + } + } + } + + [System.Boolean] Test() + { + # Call the base method to test all of the properties that should be enforced. + return ([ResourceBase] $this).Test() + } + + <# + Base method Assert() call this method with the properties that was assigned + a value. + #> + hidden [void] AssertProperties([System.Collections.Hashtable] $properties) + { + Assert-Module -ModuleName 'ADCSDeployment' + } +} diff --git a/source/DSCResources/DSC_AdcsOnlineResponder/DSC_AdcsOnlineResponder.psm1 b/source/DSCResources/DSC_AdcsOnlineResponder/DSC_AdcsOnlineResponder.psm1 deleted file mode 100644 index bae7768..0000000 --- a/source/DSCResources/DSC_AdcsOnlineResponder/DSC_AdcsOnlineResponder.psm1 +++ /dev/null @@ -1,269 +0,0 @@ -$modulePath = Join-Path -Path (Split-Path -Path (Split-Path -Path $PSScriptRoot -Parent) -Parent) -ChildPath 'Modules' - -# Import the ADCS Deployment Resource Common Module. -Import-Module -Name (Join-Path -Path $modulePath ` - -ChildPath (Join-Path -Path 'ActiveDirectoryCSDsc.Common' ` - -ChildPath 'ActiveDirectoryCSDsc.Common.psm1')) - -Import-Module -Name (Join-Path -Path $modulePath -ChildPath 'DscResource.Common') - -# Import Localization Strings. -$script:localizedData = Get-LocalizedData -DefaultUICulture 'en-US' - -<# - .SYNOPSIS - Returns an object containing the current state information for the ADCS Online Responder. - - .PARAMETER IsSingleInstance - Specifies the resource is a single instance, the value must be 'Yes'. - - .PARAMETER Credential - If the Online Responder service is configured to use Standalone certification authority, - then an account that is a member of the local Administrators on the CA is required. If - the Online Responder service is configured to use an Enterprise CA, then an account that - is a member of Domain Admins is required. - - .PARAMETER Ensure - Specifies whether the Online Responder feature should be installed or uninstalled. - - .OUTPUTS - Returns an object containing the ADCS Online Responder state information. -#> -function Get-TargetResource -{ - [CmdletBinding()] - [OutputType([System.Collections.Hashtable])] - param - ( - [Parameter(Mandatory = $true)] - [ValidateSet('Yes')] - [System.String] - $IsSingleInstance, - - [Parameter(Mandatory = $true)] - [System.Management.Automation.PSCredential] - [System.Management.Automation.Credential()] - $Credential, - - [Parameter()] - [ValidateSet('Present', 'Absent')] - [System.String] - $Ensure = 'Present' - ) - - Write-Verbose -Message ( @( - "$($MyInvocation.MyCommand): " - $($script:localizedData.GettingAdcsOnlineResponderStatusMessage) - ) -join '' ) - - $adcsParameters = @{ } + $PSBoundParameters - $null = $adcsParameters.Remove('IsSingleInstance') - $null = $adcsParameters.Remove('Ensure') - $null = $adcsParameters.Remove('Debug') - $null = $adcsParameters.Remove('ErrorAction') - - try - { - $null = Install-AdcsOnlineResponder @adcsParameters -WhatIf - # CA is not installed - $Ensure = 'Absent' - } - catch [Microsoft.CertificateServices.Deployment.Common.OCSP.OnlineResponderSetupException] - { - # CA is already installed - $Ensure = 'Present' - } - catch - { - # Something else went wrong - throw $_ - } - - return @{ - Ensure = $Ensure - Credential = $Credential - } -} # function Get-TargetResource - -<# - .SYNOPSIS - Installs or uinstalls the ADCS Online Responder from the server. - - .PARAMETER IsSingleInstance - Specifies the resource is a single instance, the value must be 'Yes'. - - .PARAMETER Credential - If the Online Responder service is configured to use Standalone certification authority, - then an account that is a member of the local Administrators on the CA is required. If - the Online Responder service is configured to use an Enterprise CA, then an account that - is a member of Domain Admins is required. - - .PARAMETER Ensure - Specifies whether the Online Responder feature should be installed or uninstalled. -#> -function Set-TargetResource -{ - [CmdletBinding()] - param - ( - [Parameter(Mandatory = $true)] - [ValidateSet('Yes')] - [System.String] - $IsSingleInstance, - - [Parameter(Mandatory = $true)] - [System.Management.Automation.PSCredential] - [System.Management.Automation.Credential()] - $Credential, - - [Parameter()] - [ValidateSet('Present', 'Absent')] - [System.String] - $Ensure = 'Present' - ) - - Write-Verbose -Message ( @( - "$($MyInvocation.MyCommand): " - $($script:localizedData.SettingAdcsOnlineResponderStatusMessage) - ) -join '' ) - - $adcsParameters = @{ } + $PSBoundParameters - $null = $adcsParameters.Remove('IsSingleInstance') - $null = $adcsParameters.Remove('Ensure') - $null = $adcsParameters.Remove('Debug') - $null = $adcsParameters.Remove('ErrorAction') - - $errorMessage = '' - - if ($Ensure -eq 'Present') - { - Write-Verbose -Message ( @( - "$($MyInvocation.MyCommand): " - $($script:localizedData.InstallingAdcsOnlineResponderMessage) - ) -join '' ) - - $errorMessage = (Install-AdcsOnlineResponder @adcsParameters -Force).ErrorString - } - else - { - Write-Verbose -Message ( @( - "$($MyInvocation.MyCommand): " - $($script:localizedData.UninstallingAdcsOnlineResponderMessage) - ) -join '' ) - - $errorMessage = (Uninstall-AdcsOnlineResponder -Force).ErrorString - } - - if (-not [System.String]::IsNullOrEmpty($errorMessage)) - { - New-InvalidOperationException -Message $errorMessage - } -} # function Set-TargetResource - -<# - .SYNOPSIS - Tests is the ADCS Online Responder is in the desired state. - - .PARAMETER IsSingleInstance - Specifies the resource is a single instance, the value must be 'Yes'. - - .PARAMETER Credential - If the Online Responder service is configured to use Standalone certification authority, - then an account that is a member of the local Administrators on the CA is required. If - the Online Responder service is configured to use an Enterprise CA, then an account that - is a member of Domain Admins is required. - - .PARAMETER Ensure - Specifies whether the Online Responder feature should be installed or uninstalled. - - .OUTPUTS - Returns true if the ADCS Online Responder is in the desired state. -#> -function Test-TargetResource -{ - [CmdletBinding()] - [OutputType([System.Boolean])] - param - ( - [Parameter(Mandatory = $true)] - [ValidateSet('Yes')] - [System.String] - $IsSingleInstance, - - [Parameter(Mandatory = $true)] - [System.Management.Automation.PSCredential] - [System.Management.Automation.Credential()] - $Credential, - - [Parameter()] - [ValidateSet('Present', 'Absent')] - [System.String] - $Ensure = 'Present' - ) - - Write-Verbose -Message ( @( - "$($MyInvocation.MyCommand): " - $script:localizedData.TestingAdcsOnlineResponderStatusMessage - ) -join '' ) - - $adcsParameters = @{ } + $PSBoundParameters - $null = $adcsParameters.Remove('IsSingleInstance') - $null = $adcsParameters.Remove('Ensure') - $null = $adcsParameters.Remove('Debug') - $null = $adcsParameters.Remove('ErrorAction') - - try - { - $null = Install-AdcsOnlineResponder @adcsParameters -WhatIf - # Online Responder is not installed - if ($Ensure -eq 'Present') - { - # Online Responder is not installed but should be - change required - Write-Verbose -Message ( @( - "$($MyInvocation.MyCommand): " - $($script:localizedData.AdcsOnlineResponderNotInstalledButShouldBeMessage) - ) -join '' ) - - return $false - } - else - { - # Online Responder is not installed and should not be - change not required - Write-Verbose -Message ( @( - "$($MyInvocation.MyCommand): " - $($script:localizedData.AdcsOnlineResponderNotInstalledAndShouldNotBeMessage) - ) -join '' ) - - return $true - } - } - catch [Microsoft.CertificateServices.Deployment.Common.OCSP.OnlineResponderSetupException] - { - # Online Responder is already installed - if ($Ensure -eq 'Present') - { - # Online Responder is installed and should be - change not required - Write-Verbose -Message ( @( - "$($MyInvocation.MyCommand): " - $($script:localizedData.AdcsOnlineResponderInstalledAndShouldBeMessage) - ) -join '' ) - - return $true - } - else - { - # Online Responder is installed and should not be - change required - Write-Verbose -Message ( @( - "$($MyInvocation.MyCommand): " - $($script:localizedData.AdcsOnlineResponderInstalledButShouldNotBeMessage) - ) -join '' ) - - return $false - } - } - catch - { - # Something else went wrong - throw $_ - } # try -} # function Test-TargetResource diff --git a/source/DSCResources/DSC_AdcsOnlineResponder/DSC_AdcsOnlineResponder.schema.mof b/source/DSCResources/DSC_AdcsOnlineResponder/DSC_AdcsOnlineResponder.schema.mof deleted file mode 100644 index fbc89da..0000000 --- a/source/DSCResources/DSC_AdcsOnlineResponder/DSC_AdcsOnlineResponder.schema.mof +++ /dev/null @@ -1,7 +0,0 @@ -[ClassVersion("0.1.0.0"), FriendlyName("AdcsOnlineResponder")] -class DSC_AdcsOnlineResponder : OMI_BaseResource -{ - [Key, Description("Specifies the resource is a single instance, the value must be 'Yes'"), ValueMap{"Yes"}, Values{"Yes"}] String IsSingleInstance; - [Required, Description("If the Online Responder service is configured to use Standalone certification authority, then an account that is a member of the local Administrators on the CA is required. If the Online Responder service is configured to use an Enterprise CA, then an account that is a member of Domain Admins is required."), EmbeddedInstance("MSFT_Credential")] String Credential; - [Write, Description("Specifies whether the Online Responder feature should be installed or uninstalled."), ValueMap{"Present","Absent"}, Values{"Present","Absent"}] String Ensure; -}; diff --git a/source/DSCResources/DSC_AdcsOnlineResponder/README.md b/source/DSCResources/DSC_AdcsOnlineResponder/README.md deleted file mode 100644 index c3b93bb..0000000 --- a/source/DSCResources/DSC_AdcsOnlineResponder/README.md +++ /dev/null @@ -1,7 +0,0 @@ -# Description - -This resource can be used to install an ADCS Online Responder after the feature -has been installed on the server. -Using this DSC Resource to configure an ADCS Certificate Authority assumes that -the ```ADCS-Online-Responder``` feature has already been installed. -For more information on ADCS Online Responders, see [this article on TechNet](https://technet.microsoft.com/en-us/library/cc725958.aspx). diff --git a/source/DSCResources/DSC_AdcsOnlineResponder/en-US/DSC_AdcsOnlineResponder.strings.psd1 b/source/DSCResources/DSC_AdcsOnlineResponder/en-US/DSC_AdcsOnlineResponder.strings.psd1 deleted file mode 100644 index 4fd9406..0000000 --- a/source/DSCResources/DSC_AdcsOnlineResponder/en-US/DSC_AdcsOnlineResponder.strings.psd1 +++ /dev/null @@ -1,13 +0,0 @@ -# Localized resources for DSC_AdcsOnlineResponder - -ConvertFrom-StringData @' - GettingAdcsOnlineResponderStatusMessage = Getting ADCS Online Responder Status. - TestingAdcsOnlineResponderStatusMessage = Testing ADCS Online Responder Status. - AdcsOnlineResponderInstalledButShouldNotBeMessage = ADCS Online Responder is installed but should not be. Change required. - AdcsOnlineResponderInstalledAndShouldBeMessage = ADCS Online Responder is installed and should be. Change not required. - AdcsOnlineResponderNotInstalledButShouldBeMessage = ADCS Online Responder is not installed but should be. Change required. - AdcsOnlineResponderNotInstalledAndShouldNotBeMessage = ADCS Online Responder is not installed and should not be. Change not required. - SettingAdcsOnlineResponderStatusMessage = Setting ADCS Online Responder Status. - InstallingAdcsOnlineResponderMessage = Installing ADCS Online Responder. - UninstallingAdcsOnlineResponderMessage = Uninstalling ADCS Online Responder. -'@ diff --git a/source/en-US/AdcsOnlineResponder.strings.psd1 b/source/en-US/AdcsOnlineResponder.strings.psd1 new file mode 100644 index 0000000..000b069 --- /dev/null +++ b/source/en-US/AdcsOnlineResponder.strings.psd1 @@ -0,0 +1,13 @@ +<# + .SYNOPSIS + The localized resource strings in English (en-US) for the + resource AdcsOnlineResponder. +#> + +ConvertFrom-StringData @' + ## Strings overrides for the ResourceBase's default strings. + # None + + ## Strings directly used by the derived class AdcsOnlineResponder. + ErrorGetCurrentState = GetCurrentState() failed with an unexpected error. (ADCSOR0001) +'@ diff --git a/tests/Integration/DSC_AdcsCertificationAuthority.Integration.Tests.ps1 b/tests/Integration/DSC_AdcsCertificationAuthority.Integration.Tests.ps1 index 15fd8e6..b3e2ef7 100644 --- a/tests/Integration/DSC_AdcsCertificationAuthority.Integration.Tests.ps1 +++ b/tests/Integration/DSC_AdcsCertificationAuthority.Integration.Tests.ps1 @@ -245,6 +245,10 @@ Describe 'DSC_AdcsAuthorityInformationAccess_Integration' -Skip:$skipIntegration } } + AfterEach { + Wait-ForIdleLcm + } + It 'Should compile and apply the MOF without throwing' { { & 'DSC_AdcsAuthorityInformationAccess_Config' ` @@ -290,6 +294,10 @@ Describe 'DSC_AdcsAuthorityInformationAccess_Integration' -Skip:$skipIntegration } } + AfterEach { + Wait-ForIdleLcm + } + It 'Should compile and apply the MOF without throwing' { { & 'DSC_AdcsAuthorityInformationAccess_Config' ` diff --git a/tests/Unit/Classes/AdcsAuthorityInformationAccess.Tests.ps1 b/tests/Unit/Classes/AdcsAuthorityInformationAccess.Tests.ps1 index 74b8b45..c73d1e5 100644 --- a/tests/Unit/Classes/AdcsAuthorityInformationAccess.Tests.ps1 +++ b/tests/Unit/Classes/AdcsAuthorityInformationAccess.Tests.ps1 @@ -594,15 +594,15 @@ Describe 'AdcsAuthorityInformationAccess\Test()' -Tag 'Test' { $script:getMethodCallCount += 1 } } + } - It 'Should return $true' { - InModuleScope -ScriptBlock { - Set-StrictMode -Version 1.0 + It 'Should return $true' { + InModuleScope -ScriptBlock { + Set-StrictMode -Version 1.0 - $script:mockInstance.Test() | Should -BeTrue + $script:mockInstance.Test() | Should -BeTrue - $script:getMethodCallCount | Should -Be 1 - } + $script:getMethodCallCount | Should -Be 1 } } } diff --git a/tests/Unit/Classes/AdcsOnlineResponder.Tests.ps1 b/tests/Unit/Classes/AdcsOnlineResponder.Tests.ps1 new file mode 100644 index 0000000..4b1c418 --- /dev/null +++ b/tests/Unit/Classes/AdcsOnlineResponder.Tests.ps1 @@ -0,0 +1,764 @@ +<# + .SYNOPSIS + Unit test for AdcsOnlineResponder DSC resource. +#> + +# Suppressing this rule because Script Analyzer does not understand Pester's syntax. +[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', '')] +param () + +BeforeDiscovery { + try + { + if (-not (Get-Module -Name 'DscResource.Test')) + { + # Assumes dependencies has been resolved, so if this module is not available, run 'noop' task. + if (-not (Get-Module -Name 'DscResource.Test' -ListAvailable)) + { + # Redirect all streams to $null, except the error stream (stream 2) + & "$PSScriptRoot/../../../build.ps1" -Tasks 'noop' 3>&1 4>&1 5>&1 6>&1 > $null + } + + # If the dependencies has not been resolved, this will throw an error. + Import-Module -Name 'DscResource.Test' -Force -ErrorAction 'Stop' + } + } + catch [System.IO.FileNotFoundException] + { + throw 'DscResource.Test module dependency not found. Please run ".\build.ps1 -ResolveDependency -Tasks build" first.' + } +} + +BeforeAll { + $script:dscModuleName = 'ActiveDirectoryCSDsc' + + # Loading mocked exception class + # New-MockObject -Type Microsoft.CertificateServices.Deployment.Common.OCSP.OnlineResponderSetupException + + Import-Module -Name $script:dscModuleName + + # Load stub cmdlets and classes. + Import-Module -Name (Join-Path -Path $PSScriptRoot -ChildPath '..\Stubs\AdcsDeploymentStub.psm1') + + $PSDefaultParameterValues['InModuleScope:ModuleName'] = $script:dscModuleName + $PSDefaultParameterValues['Mock:ModuleName'] = $script:dscModuleName + $PSDefaultParameterValues['Should:ModuleName'] = $script:dscModuleName +} + +AfterAll { + $PSDefaultParameterValues.Remove('InModuleScope:ModuleName') + $PSDefaultParameterValues.Remove('Mock:ModuleName') + $PSDefaultParameterValues.Remove('Should:ModuleName') + + # Unload stub module + Remove-Module -Name AdcsDeploymentStub -Force + + # Unload the module being tested so that it doesn't impact any other tests. + Get-Module -Name $script:dscModuleName -All | Remove-Module -Force +} + +Describe 'AdcsOnlineResponder' { + Context 'When class is instantiated' { + It 'Should not throw an exception' { + InModuleScope -ScriptBlock { + Set-StrictMode -Version 1.0 + + { [AdcsOnlineResponder]::new() } | Should -Not -Throw + } + } + + It 'Should have a default or empty constructor' { + InModuleScope -ScriptBlock { + Set-StrictMode -Version 1.0 + + $instance = [AdcsOnlineResponder]::new() + $instance | Should -Not -BeNullOrEmpty + } + } + + It 'Should be the correct type' { + InModuleScope -ScriptBlock { + Set-StrictMode -Version 1.0 + + $instance = [AdcsOnlineResponder]::new() + $instance.GetType().Name | Should -Be 'AdcsOnlineResponder' + } + } + } +} + +Describe 'AdcsOnlineResponder\Get()' -Tag 'Get' { + Context 'When the system is in the desired state' { + Context 'When AdcsOnlineResponder is installed' { + BeforeAll { + InModuleScope -ScriptBlock { + Set-StrictMode -Version 1.0 + + $script:mockCredential = [System.Management.Automation.PSCredential]::new('Administrator', ([System.Security.SecureString]::new())) + + $script:mockInstance = [AdcsOnlineResponder] @{ + IsSingleInstance = 'Yes' + Credential = $script:mockCredential + } + + <# + This mocks the method GetCurrentState(). + This mocks the method Assert(). + This mocks the method Normalize(). + + Method Get() will call the base method Get() which will + call back to the derived class methods. + #> + $script:mockInstance | + Add-Member -Force -MemberType 'ScriptMethod' -Name 'GetCurrentState' -Value { + return @{ + IsSingleInstance = 'Yes' + Credential = $script:mockCredential + } + } -PassThru | + Add-Member -Force -MemberType 'ScriptMethod' -Name 'Assert' -Value { + return + } -PassThru | + Add-Member -Force -MemberType 'ScriptMethod' -Name 'Normalize' -Value { + return + } -PassThru + } + } + + It 'Should return the correct values' { + InModuleScope -ScriptBlock { + Set-StrictMode -Version 1.0 + + $currentState = $script:mockInstance.Get() + + $currentState.IsSingleInstance | Should -Be 'Yes' + + $currentState.Credential | Should -Be $script:mockCredential + $currentState.Ensure | Should -Be 'Present' + + $currentState.Reasons | Should -BeNullOrEmpty + } + } + } + + Context 'When AdcsOnlineResponder is not installed' { + BeforeAll { + InModuleScope -ScriptBlock { + Set-StrictMode -Version 1.0 + + $script:mockInstance = [AdcsOnlineResponder] @{ + IsSingleInstance = 'Yes' + Credential = [System.Management.Automation.PSCredential]::new('Administrator', ([System.Security.SecureString]::new())) + Ensure = [Ensure]::Absent + } + + <# + This mocks the method GetCurrentState(). + This mocks the method Assert(). + This mocks the method Normalize(). + + Method Get() will call the base method Get() which will + call back to the derived class methods. + #> + $script:mockInstance | + Add-Member -Force -MemberType 'ScriptMethod' -Name 'GetCurrentState' -Value { + return @{} + } -PassThru | + Add-Member -Force -MemberType 'ScriptMethod' -Name 'Assert' -Value { + return + } -PassThru | + Add-Member -Force -MemberType 'ScriptMethod' -Name 'Normalize' -Value { + return + } -PassThru + } + } + + It 'Should return the correct values' { + InModuleScope -ScriptBlock { + Set-StrictMode -Version 1.0 + + $currentState = $script:mockInstance.Get() + + $currentState.IsSingleInstance | Should -Be 'Yes' + + $currentState.Credential | Should -BeNullOrEmpty + $currentState.Ensure | Should -Be 'Absent' + + $currentState.Reasons | Should -HaveCount 0 + } + } + } + } + + Context 'When the system is not in the desired state' { + Context 'When AdcsOnlineResponder is installed' { + BeforeAll { + InModuleScope -ScriptBlock { + Set-StrictMode -Version 1.0 + + $script:mockCredential = [System.Management.Automation.PSCredential]::new('Administrator', ([System.Security.SecureString]::new())) + + $script:mockInstance = [AdcsOnlineResponder] @{ + IsSingleInstance = 'Yes' + Credential = $script:mockCredential + Ensure = [Ensure]::Absent + } + + <# + This mocks the method GetCurrentState(). + This mocks the method Assert(). + This mocks the method Normalize(). + + Method Get() will call the base method Get() which will + call back to the derived class methods. + #> + $script:mockInstance | + Add-Member -Force -MemberType 'ScriptMethod' -Name 'GetCurrentState' -Value { + return @{ + IsSingleInstance = 'Yes' + Credential = $script:mockCredential + } + } -PassThru | + Add-Member -Force -MemberType 'ScriptMethod' -Name 'Assert' -Value { + return + } -PassThru | + Add-Member -Force -MemberType 'ScriptMethod' -Name 'Normalize' -Value { + return + } -PassThru + } + } + + It 'Should return the correct values' { + InModuleScope -ScriptBlock { + Set-StrictMode -Version 1.0 + + $currentState = $script:mockInstance.Get() + + $currentState.IsSingleInstance | Should -Be 'Yes' + + $currentState.Credential | Should -Be $script:mockCredential + $currentState.Ensure | Should -Be 'Present' + + + $currentState.Reasons | Should -HaveCount 1 + $currentState.Reasons[0].Code | Should -Be 'AdcsOnlineResponder:AdcsOnlineResponder:Ensure' + $currentState.Reasons[0].Phrase | Should -Be 'The property Ensure should be "Absent", but was "Present"' + } + } + } + + Context 'When AdcsOnlineResponder is not installed' { + BeforeAll { + InModuleScope -ScriptBlock { + Set-StrictMode -Version 1.0 + + $script:mockCredential = [System.Management.Automation.PSCredential]::new('Administrator', ([System.Security.SecureString]::new())) + + $script:mockInstance = [AdcsOnlineResponder] @{ + IsSingleInstance = 'Yes' + Credential = $script:mockCredential + } + + <# + This mocks the method GetCurrentState(). + This mocks the method Assert(). + This mocks the method Normalize(). + + Method Get() will call the base method Get() which will + call back to the derived class methods. + #> + $script:mockInstance | + Add-Member -Force -MemberType 'ScriptMethod' -Name 'GetCurrentState' -Value { + return @{} + } -PassThru | + Add-Member -Force -MemberType 'ScriptMethod' -Name 'Assert' -Value { + return + } -PassThru | + Add-Member -Force -MemberType 'ScriptMethod' -Name 'Normalize' -Value { + return + } -PassThru + } + } + + It 'Should return the correct values' { + InModuleScope -ScriptBlock { + Set-StrictMode -Version 1.0 + + $currentState = $script:mockInstance.Get() + + $currentState.IsSingleInstance | Should -Be 'Yes' + + $currentState.Credential | Should -BeNullOrEmpty + $currentState.Ensure | Should -Be 'Absent' + + + $currentState.Reasons | Should -HaveCount 1 + $currentState.Reasons[0].Code | Should -Be 'AdcsOnlineResponder:AdcsOnlineResponder:Ensure' + $currentState.Reasons[0].Phrase | Should -Be 'The property Ensure should be "Present", but was "Absent"' + } + } + } + } +} + +Describe 'AdcsOnlineResponder\Set()' -Tag 'Set' { + BeforeAll { + InModuleScope -ScriptBlock { + Set-StrictMode -Version 1.0 + + $script:mockCredential = [System.Management.Automation.PSCredential]::new('Administrator', ([System.Security.SecureString]::new())) + + $script:mockInstance = [AdcsOnlineResponder] @{ + IsSingleInstance = 'Yes' + Credential = $script:mockCredential + } | + # Mock method Modify which is called by the case method Set(). + Add-Member -Force -MemberType 'ScriptMethod' -Name 'Modify' -Value { + $script:methodModifyCallCount += 1 + } -PassThru + } + } + + BeforeEach { + InModuleScope -ScriptBlock { + Set-StrictMode -Version 1.0 + + $script:methodTestCallCount = 0 + $script:methodModifyCallCount = 0 + } + } + + Context 'When the system is in the desired state' { + BeforeAll { + InModuleScope -ScriptBlock { + Set-StrictMode -Version 1.0 + + $script:mockInstance | + # Mock method Test() which is called by the base method Set() + Add-Member -Force -MemberType 'ScriptMethod' -Name 'Test' -Value { + $script:methodTestCallCount += 1 + return $true + } + + } + } + + It 'Should not call method Modify()' { + InModuleScope -ScriptBlock { + Set-StrictMode -Version 1.0 + + $script:mockInstance.Set() + + $script:methodTestCallCount | Should -Be 1 + $script:methodModifyCallCount | Should -Be 0 + } + } + } + + Context 'When the system is not in the desired state' { + BeforeAll { + InModuleScope -ScriptBlock { + Set-StrictMode -Version 1.0 + + $script:mockInstance | + # Mock method Test() which is called by the base method Set() + Add-Member -Force -MemberType 'ScriptMethod' -Name 'Test' -Value { + $script:methodTestCallCount += 1 + return $false + } + + $script:mockInstance.PropertiesNotInDesiredState = @( + @{ + Property = 'Ensure' + ExpectedValue = 'Present' + ActualValue = 'Absent' + } + ) + } + } + + It 'Should call method Modify()' { + InModuleScope -ScriptBlock { + Set-StrictMode -Version 1.0 + + $script:mockInstance.Set() + + $script:methodTestCallCount | Should -Be 1 + $script:methodModifyCallCount | Should -Be 1 + } + } + } +} + +Describe 'AdcsOnlineResponder\Test()' -Tag 'Test' { + BeforeAll { + InModuleScope -ScriptBlock { + Set-StrictMode -Version 1.0 + + $script:mockCredential = [System.Management.Automation.PSCredential]::new('Administrator', ([System.Security.SecureString]::new())) + + $script:mockInstance = [AdcsOnlineResponder] @{ + IsSingleInstance = 'Yes' + Credential = $script:mockCredential + } + } + } + + BeforeEach { + InModuleScope -ScriptBlock { + Set-StrictMode -Version 1.0 + + $script:getMethodCallCount = 0 + } + } + + Context 'When the system is in the desired state' { + BeforeAll { + InModuleScope -ScriptBlock { + Set-StrictMode -Version 1.0 + + $script:mockInstance | + # Mock method Get() which is called by the base method Test() + Add-Member -Force -MemberType 'ScriptMethod' -Name 'Get' -Value { + $script:getMethodCallCount += 1 + } + } + } + + It 'Should return $true' { + InModuleScope -ScriptBlock { + Set-StrictMode -Version 1.0 + + $script:mockInstance.Test() | Should -BeTrue + + $script:getMethodCallCount | Should -Be 1 + } + } + + } + + Context 'When the system is not in the desired state' { + BeforeAll { + InModuleScope -ScriptBlock { + Set-StrictMode -Version 1.0 + + $script:mockInstance | + # Mock method Get() which is called by the base method Test() + Add-Member -Force -MemberType 'ScriptMethod' -Name 'Get' -Value { + $script:getMethodCallCount += 1 + } + + $script:mockInstance.PropertiesNotInDesiredState = @( + @{ + Property = 'Ensure' + ExpectedValue = 'Present' + ActualValue = 'Absent' + } + ) + } + } + + It 'Should return $false' { + InModuleScope -ScriptBlock { + Set-StrictMode -Version 1.0 + + $script:mockInstance.Test() | Should -BeFalse + + $script:getMethodCallCount | Should -Be 1 + } + } + } +} + +Describe 'AdcsOnlineResponder\GetCurrentState()' -Tag 'HiddenMember' { + Context 'When the OnlineResponder is not installed' { + BeforeAll { + InModuleScope -ScriptBlock { + Set-StrictMode -Version 1.0 + + $script:mockInstance = [AdcsOnlineResponder] @{ + IsSingleInstance = 'Yes' + Ensure = [Ensure]::Present + } + } + + Mock -CommandName Install-AdcsOnlineResponder + } + + It 'Should return the correct values' { + InModuleScope -ScriptBlock { + Set-StrictMode -Version 1.0 + + $currentState = $script:mockInstance.GetCurrentState( + @{ + IsSingleInstance = 'Yes' + } + ) + + $currentState.IsSingleInstance | Should -BeNullOrEmpty + } + + Should -Invoke -CommandName Install-AdcsOnlineResponder -Exactly -Times 1 -Scope It + } + } + + Context 'When the OnlineResponder is already installed' { + BeforeAll { + InModuleScope -ScriptBlock { + Set-StrictMode -Version 1.0 + + $script:mockInstance = [AdcsOnlineResponder] @{ + IsSingleInstance = 'Yes' + Ensure = [Ensure]::Present + } + } + + Mock -CommandName Install-AdcsOnlineResponder -MockWith { + throw [Microsoft.CertificateServices.Deployment.Common.OCSP.OnlineResponderSetupException]::new() + } + } + + It 'Should return the correct values' { + InModuleScope -ScriptBlock { + Set-StrictMode -Version 1.0 + + $currentState = $script:mockInstance.GetCurrentState( + @{ + IsSingleInstance = 'Yes' + } + ) + + $currentState.IsSingleInstance | Should -Be 'Yes' + } + + Should -Invoke -CommandName Install-AdcsOnlineResponder -Exactly -Times 1 -Scope It + } + } + + Context 'When the OnlineResponder throws an unexpected exception' { + BeforeAll { + InModuleScope -ScriptBlock { + Set-StrictMode -Version 1.0 + + $script:mockInstance = [AdcsOnlineResponder] @{ + IsSingleInstance = 'Yes' + Ensure = [Ensure]::Present + } + } + + Mock -CommandName Install-AdcsOnlineResponder -MockWith { + throw 'Another exception' + } + } + + It 'Should return the correct values' { + InModuleScope -ScriptBlock { + Set-StrictMode -Version 1.0 + + $errorRecord = Get-InvalidOperationRecord -Message $script:mockInstance.localizedData.ErrorGetCurrentState + + { + $script:mockInstance.GetCurrentState( + @{ + IsSingleInstance = 'Yes' + } + ) + } | Should -Throw -ExpectedMessage ($errorRecord.Exception.Message + '*') + } + + Should -Invoke -CommandName Install-AdcsOnlineResponder -Exactly -Times 1 -Scope It + } + } +} + +Describe 'AdcsOnlineResponder\Modify()' -Tag 'HiddenMember' { + Context 'When the resource should be added' { + BeforeAll { + InModuleScope -ScriptBlock { + Set-StrictMode -Version 1.0 + + $script:mockInstance = [AdcsOnlineResponder] @{ + IsSingleInstance = 'Yes' + } + + Mock -CommandName Install-AdcsOnlineResponder + } + } + + It 'Should call the correct mocks' { + InModuleScope -ScriptBlock { + Set-StrictMode -Version 1.0 + + $mockProperties = @{ + Ensure = [Ensure]::Present + } + + $script:mockInstance.PropertiesNotInDesiredState = @( + @{ + Property = 'Ensure' + ExpectedValue = 'Present' + ActualValue = 'Absent' + } + ) + + { $script:mockInstance.Modify($mockProperties) } | Should -Not -Throw + } + + Should -Invoke -CommandName Install-AdcsOnlineResponder -Exactly -Times 1 -Scope It + } + } + + Context 'When the resource should be added and fails' { + BeforeAll { + InModuleScope -ScriptBlock { + Set-StrictMode -Version 1.0 + + $script:mockInstance = [AdcsOnlineResponder] @{ + IsSingleInstance = 'Yes' + } + + Mock -CommandName Install-AdcsOnlineResponder -MockWith { throw } + } + } + + It 'Should call the correct mocks' { + InModuleScope -ScriptBlock { + Set-StrictMode -Version 1.0 + + $mockProperties = @{ + Ensure = [Ensure]::Present + } + + $script:mockInstance.PropertiesNotInDesiredState = @( + @{ + Property = 'Ensure' + ExpectedValue = 'Present' + ActualValue = 'Absent' + } + ) + + { $script:mockInstance.Modify($mockProperties) } | Should -Throw + } + + Should -Invoke -CommandName Install-AdcsOnlineResponder -Exactly -Times 1 -Scope It + } + } + + Context 'When the resource should be removed' { + BeforeAll { + InModuleScope -ScriptBlock { + Set-StrictMode -Version 1.0 + + $script:mockInstance = [AdcsOnlineResponder] @{ + IsSingleInstance = 'Yes' + } + + Mock -CommandName Uninstall-AdcsOnlineResponder + } + } + + It 'Should call the correct mocks' { + InModuleScope -ScriptBlock { + Set-StrictMode -Version 1.0 + + $mockProperties = @{ + Ensure = [Ensure]::Absent + } + + $script:mockInstance.PropertiesNotInDesiredState = @( + @{ + Property = 'Ensure' + ExpectedValue = 'Absent' + ActualValue = 'Present' + } + ) + + { $script:mockInstance.Modify($mockProperties) } | Should -Not -Throw + } + + Should -Invoke -CommandName Uninstall-AdcsOnlineResponder -Exactly -Times 1 -Scope It + } + } + + Context 'When the resource should be removed but fails' { + BeforeAll { + InModuleScope -ScriptBlock { + Set-StrictMode -Version 1.0 + + $script:mockInstance = [AdcsOnlineResponder] @{ + IsSingleInstance = 'Yes' + } + + Mock -CommandName Uninstall-AdcsOnlineResponder -MockWith { throw } + } + } + + It 'Should call the correct mocks' { + InModuleScope -ScriptBlock { + Set-StrictMode -Version 1.0 + + $mockProperties = @{ + Ensure = [Ensure]::Absent + } + + $script:mockInstance.PropertiesNotInDesiredState = @( + @{ + Property = 'Ensure' + ExpectedValue = 'Absent' + ActualValue = 'Present' + } + ) + + { $script:mockInstance.Modify($mockProperties) } | Should -Throw + } + + Should -Invoke -CommandName Uninstall-AdcsOnlineResponder -Exactly -Times 1 -Scope It + } + } +} + +Describe 'AdcsOnlineResponder\AssertProperties()' -Tag 'AssertProperties' { + BeforeAll { + InModuleScope -ScriptBlock { + Set-StrictMode -Version 1.0 + + $script:mockInstance = [AdcsOnlineResponder] @{} + } + } + + Context 'When required module is missing' { + BeforeAll { + Mock -CommandName Assert-Module -MockWith { throw } + } + + It 'Should throw an error' { + InModuleScope -ScriptBlock { + Set-StrictMode -Version 1.0 + + $mockProperties = @{ + IsSingleInstance = 'Yes' + } + + { $script:mockInstance.AssertProperties($mockProperties) } | Should -Throw + } + } + } + + Context 'When required module is present' { + BeforeAll { + Mock -CommandName Assert-Module + } + + It 'Should not throw an error' { + InModuleScope -ScriptBlock { + Set-StrictMode -Version 1.0 + + $mockProperties = @{ + IsSingleInstance = 'Yes' + } + + { $script:mockInstance.AssertProperties($mockProperties) } | Should -Not -Throw + } + } + } +} diff --git a/tests/Unit/DSC_AdcsOnlineResponder.Tests.ps1 b/tests/Unit/DSC_AdcsOnlineResponder.Tests.ps1 deleted file mode 100644 index 8a92e80..0000000 --- a/tests/Unit/DSC_AdcsOnlineResponder.Tests.ps1 +++ /dev/null @@ -1,398 +0,0 @@ -<# - .SYNOPSIS - Unit test for DSC_AdcsOnlineResponder DSC resource. - - .NOTES -#> - -# Suppressing this rule because Script Analyzer does not understand Pester's syntax. -[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', '')] -param () - -BeforeDiscovery { - try - { - if (-not (Get-Module -Name 'DscResource.Test')) - { - # Assumes dependencies has been resolved, so if this module is not available, run 'noop' task. - if (-not (Get-Module -Name 'DscResource.Test' -ListAvailable)) - { - # Redirect all streams to $null, except the error stream (stream 2) - & "$PSScriptRoot/../../build.ps1" -Tasks 'noop' 2>&1 4>&1 5>&1 6>&1 > $null - } - - # If the dependencies has not been resolved, this will throw an error. - Import-Module -Name 'DscResource.Test' -Force -ErrorAction 'Stop' - } - } - catch [System.IO.FileNotFoundException] - { - throw 'DscResource.Test module dependency not found. Please run ".\build.ps1 -ResolveDependency -Tasks build" first.' - } -} - -BeforeAll { - $script:dscModuleName = 'ActiveDirectoryCSDsc' - $script:dscResourceName = 'DSC_AdcsOnlineResponder' - - $script:testEnvironment = Initialize-TestEnvironment ` - -DSCModuleName $script:dscModuleName ` - -DSCResourceName $script:dscResourceName ` - -ResourceType 'Mof' ` - -TestType 'Unit' - - Import-Module -Name (Join-Path -Path $PSScriptRoot -ChildPath '..\TestHelpers\CommonTestHelper.psm1') - Import-Module -Name (Join-Path -Path $PSScriptRoot -ChildPath '.\Stubs\AdcsDeploymentStub.psm1') - - $PSDefaultParameterValues['InModuleScope:ModuleName'] = $script:dscResourceName - $PSDefaultParameterValues['Mock:ModuleName'] = $script:dscResourceName - $PSDefaultParameterValues['Should:ModuleName'] = $script:dscResourceName - - # Add Custom Type - if (-not ([System.Management.Automation.PSTypeName]'Microsoft.CertificateServices.Deployment.Common.OCSP.OnlineResponderSetupException').Type) - { - <# - Define the exception class: - Microsoft.CertificateServices.Deployment.Common.OCSP.OnlineResponderSetupException - so that unit tests can be run without ADCS being installed. - #> - - $ExceptionDefinition = @' -namespace Microsoft.CertificateServices.Deployment.Common.OCSP { - public class OnlineResponderSetupException: System.Exception { - } -} -'@ - Add-Type -TypeDefinition $ExceptionDefinition - } - - # Add Test Data - InModuleScope -ScriptBlock { - $DummyCredential = New-Object System.Management.Automation.PSCredential ('Administrator', (New-Object -Type SecureString)) - - $script:testParametersPresent = @{ - IsSingleInstance = 'Yes' - Ensure = 'Present' - Credential = $DummyCredential - Verbose = $false - } - - $script:TestParametersAbsent = @{ - IsSingleInstance = 'Yes' - Ensure = 'Absent' - Credential = $DummyCredential - Verbose = $false - } - } -} - -AfterAll { - $PSDefaultParameterValues.Remove('InModuleScope:ModuleName') - $PSDefaultParameterValues.Remove('Mock:ModuleName') - $PSDefaultParameterValues.Remove('Should:ModuleName') - - Restore-TestEnvironment -TestEnvironment $script:testEnvironment - - # Unload the module being tested so that it doesn't impact any other tests. - Get-Module -Name $script:dscResourceName -All | Remove-Module -Force - - Remove-Module -Name AdcsDeploymentStub -Force - - # Remove module common test helper. - Get-Module -Name 'CommonTestHelper' -All | Remove-Module -Force -} - -Describe 'DSC_AdcsOnlineResponder\Get-TargetResource' -Tag 'Get' { - Context 'When the Online Responder is installed' { - BeforeAll { - Mock ` - -CommandName Install-AdcsOnlineResponder ` - -MockWith { - Throw (New-Object -TypeName 'Microsoft.CertificateServices.Deployment.Common.OCSP.OnlineResponderSetupException') - } -Verifiable - } - - - It 'Should return Ensure set to Present' { - InModuleScope -ScriptBlock { - Set-StrictMode -Version 1.0 - - $getTargetResourceResult = Get-TargetResource @testParametersPresent - $getTargetResourceResult.Ensure | Should -Be 'Present' - } - } - - It 'Should call expected mocks' { - Should -InvokeVerifiable - Should -Invoke ` - -CommandName Install-AdcsOnlineResponder ` - -Exactly ` - -Times 1 -Scope Context - } - } - - Context 'When the Online Responder is not installed' { - BeforeAll { - Mock -CommandName Install-AdcsOnlineResponder - } - - - It 'Should return Ensure set to Absent' { - InModuleScope -ScriptBlock { - Set-StrictMode -Version 1.0 - - $getTargetResourceResult = Get-TargetResource @testParametersPresent - $getTargetResourceResult.Ensure | Should -Be 'Absent' - } - } - - It 'Should call expected mocks' { - Should -Invoke ` - -CommandName Install-AdcsOnlineResponder ` - -Exactly ` - -Times 1 -Scope Context - } - } - - Context 'When there is an unexpected error' { - BeforeAll { - Mock ` - -CommandName Install-AdcsOnlineResponder ` - -MockWith { Throw (New-Object -TypeName 'System.Exception') } ` - -Verifiable - } - - It 'Should throw an exception' { - InModuleScope -ScriptBlock { - Set-StrictMode -Version 1.0 - - { Get-TargetResource @testParametersPresent } | Should -Throw - } - } - - It 'Should call expected mocks' { - Should -InvokeVerifiable - Should -Invoke ` - -CommandName Install-AdcsOnlineResponder ` - -Exactly ` - -Times 1 -Scope Context - } - } -} - -Describe 'DSC_AdcsOnlineResponder\Set-TargetResource' -Tag 'Set' { - Context 'When the Online Responder is not installed but should be' { - BeforeAll { - Mock -CommandName Install-AdcsOnlineResponder - Mock -CommandName Uninstall-AdcsOnlineResponder - } - - It 'Should not throw an exception' { - InModuleScope -ScriptBlock { - Set-StrictMode -Version 1.0 - - { Set-TargetResource @testParametersPresent } | Should -Not -Throw - } - } - - It 'Should call expected mocks' { - Should -Invoke ` - -CommandName Install-AdcsOnlineResponder ` - -Exactly ` - -Times 1 -Scope Context - - Should -Invoke ` - -CommandName Uninstall-AdcsOnlineResponder ` - -Exactly ` - -Times 0 -Scope Context - } - } - - Context 'When the Online Responder is not installed but should be but an error is thrown installing it' { - BeforeAll { - Mock -CommandName Install-AdcsOnlineResponder ` - -MockWith { [PSObject] @{ ErrorString = 'Something went wrong' } } - - Mock -CommandName Uninstall-AdcsOnlineResponder - } - - It 'Should throw an exception' { - InModuleScope -ScriptBlock { - Set-StrictMode -Version 1.0 - - $errorRecord = Get-InvalidOperationRecord -Message 'Something went wrong' - - { Set-TargetResource @testParametersPresent } | Should -Throw $errorRecord - } - } - - It 'Should call expected mocks' { - Should -Invoke ` - -CommandName Install-AdcsOnlineResponder ` - -Exactly ` - -Times 1 -Scope Context - - Should -Invoke ` - -CommandName Uninstall-AdcsOnlineResponder ` - -Exactly ` - -Times 0 -Scope Context - } - } - - Context 'When the Online Responder is installed but should not be' { - BeforeAll { - Mock -CommandName Install-AdcsOnlineResponder - Mock -CommandName Uninstall-AdcsOnlineResponder - } - - It 'Should not throw an exception' { - InModuleScope -ScriptBlock { - Set-StrictMode -Version 1.0 - - { Set-TargetResource @TestParametersAbsent } | Should -Not -Throw - } - } - - It 'Should call expected mocks' { - Should -Invoke ` - -CommandName Install-AdcsOnlineResponder ` - -Exactly ` - -Times 0 -Scope Context - - Should -Invoke ` - -CommandName Uninstall-AdcsOnlineResponder ` - -Exactly ` - -Times 1 -Scope Context - } - } -} - -Describe 'DSC_AdcsOnlineResponder\Test-TargetResource' -Tag 'Test' { - Context 'When the Online Responder is installed' { - Context 'When the Online Responder should be installed' { - BeforeAll { - Mock -CommandName Install-AdcsOnlineResponder ` - -MockWith { Throw (New-Object -TypeName 'Microsoft.CertificateServices.Deployment.Common.OCSP.OnlineResponderSetupException') } ` - -Verifiable - } - - It 'Should return true' { - InModuleScope -ScriptBlock { - Set-StrictMode -Version 1.0 - - $testTargetResourceResult = Test-TargetResource @testParametersPresent - $testTargetResourceResult | Should -BeTrue - } - } - - It 'Should call expected mocks' { - Should -InvokeVerifiable - Should -Invoke ` - -CommandName Install-AdcsOnlineResponder ` - -Exactly ` - -Times 1 -Scope Context - } - } - - Context 'When the Online Responder should not be installed' { - BeforeAll { - Mock -CommandName Install-AdcsOnlineResponder ` - -MockWith { Throw (New-Object -TypeName 'Microsoft.CertificateServices.Deployment.Common.OCSP.OnlineResponderSetupException') } ` - -Verifiable - } - - - It 'Should return false' { - InModuleScope -ScriptBlock { - Set-StrictMode -Version 1.0 - - $testTargetResourceResult = Test-TargetResource @TestParametersAbsent - $testTargetResourceResult | Should -BeFalse - } - } - - It 'Should call expected mocks' { - Should -InvokeVerifiable - Should -Invoke ` - -CommandName Install-AdcsOnlineResponder ` - -Exactly ` - -Times 1 -Scope Context - } - } - } - - Context 'When the Online Responder is not installed' { - Context 'When the Online Responder should be installed' { - BeforeAll { - Mock -CommandName Install-AdcsOnlineResponder ` - -Verifiable - } - - It 'Should return false' { - InModuleScope -ScriptBlock { - Set-StrictMode -Version 1.0 - - $testTargetResourceResult = Test-TargetResource @testParametersPresent - $testTargetResourceResult | Should -BeFalse - } - } - - It 'Should call expected mocks' { - Should -InvokeVerifiable - Should -Invoke ` - -CommandName Install-AdcsOnlineResponder ` - -Exactly ` - -Times 1 -Scope Context - } - } - - Context 'When the Online Responder should not be installed' { - BeforeAll { - Mock -CommandName Install-AdcsOnlineResponder ` - -Verifiable - } - - - It 'Should return true' { - InModuleScope -ScriptBlock { - Set-StrictMode -Version 1.0 - - $testTargetResourceResult = Test-TargetResource @TestParametersAbsent - $testTargetResourceResult | Should -BeTrue - } - } - - It 'Should call expected mocks' { - Should -InvokeVerifiable - Should -Invoke ` - -CommandName Install-AdcsOnlineResponder ` - -Exactly ` - -Times 1 -Scope Context - } - } - } - - Context 'Should throw on any other error' { - BeforeAll { - Mock -CommandName Install-AdcsOnlineResponder ` - -MockWith { Throw (New-Object -TypeName 'System.Exception') } ` - -Verifiable - } - - It 'Should throw an exception' { - InModuleScope -ScriptBlock { - Set-StrictMode -Version 1.0 - - { Test-TargetResource @testParametersPresent } | Should -Throw - } - } - - It 'Should call expected mocks' { - Should -InvokeVerifiable - Should -Invoke ` - -CommandName Install-AdcsOnlineResponder ` - -Exactly ` - -Times 1 -Scope Context - } - } -} diff --git a/tests/Unit/Stubs/AdcsDeploymentStub.psm1 b/tests/Unit/Stubs/AdcsDeploymentStub.psm1 index f6724b5..a7ebffc 100644 --- a/tests/Unit/Stubs/AdcsDeploymentStub.psm1 +++ b/tests/Unit/Stubs/AdcsDeploymentStub.psm1 @@ -7,6 +7,15 @@ [CmdletBinding()] param () +Add-Type -TypeDefinition @' +namespace Microsoft.CertificateServices.Deployment.Common.OCSP { + public class OnlineResponderSetupException : System.Exception { + public OnlineResponderSetupException() {} + public OnlineResponderSetupException(string message) : base(message) {} + } +} +'@ + function Install-AdcsCertificationAuthority { <#