From e7b347e002c0745649d2a91ed085f9b208e0943e Mon Sep 17 00:00:00 2001 From: Johan Ljunggren Date: Sat, 1 Apr 2023 21:11:36 +0200 Subject: [PATCH] SqlSecureConnection: Added new parameter `ServerName` (#1892) - `SqlSecureConnection` - Added new parameter `ServerName` that will be used as the host name when restarting the SQL Server instance. The specified value should be the same name that is used in the certificate (issue #1888). --- CHANGELOG.md | 4 ++ .../DSC_SqlSecureConnection.psm1 | 44 +++++++++++++++++-- .../DSC_SqlSecureConnection.schema.mof | 2 +- .../1-ForceSecureConnection.ps1 | 1 + ..._SqlSecureConnection.Integration.Tests.ps1 | 9 ++-- .../DSC_SqlSecureConnection.config.ps1 | 15 ++++--- tests/Unit/DSC_SqlSecureConnection.Tests.ps1 | 13 ++++-- tests/Unit/SqlServerDsc.Common.Tests.ps1 | 6 ++- 8 files changed, 75 insertions(+), 19 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f0b2438f1..c4abc4802 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 other values that the default values. - Now updates GitHub Actions automatically by allowing dependabot sending in pull requests. +- `SqlSecureConnection` + - Added new parameter `ServerName` that will be used as the host name when + restarting the SQL Server instance. The specified value should be the same + name that is used in the certificate ([issue #1888](https://github.com/dsccommunity/SqlServerDsc/issues/1888)). ### Changed diff --git a/source/DSCResources/DSC_SqlSecureConnection/DSC_SqlSecureConnection.psm1 b/source/DSCResources/DSC_SqlSecureConnection/DSC_SqlSecureConnection.psm1 index d44a8f76f..62c1de3ee 100644 --- a/source/DSCResources/DSC_SqlSecureConnection/DSC_SqlSecureConnection.psm1 +++ b/source/DSCResources/DSC_SqlSecureConnection/DSC_SqlSecureConnection.psm1 @@ -29,6 +29,13 @@ $script:localizedData = Get-LocalizedData -DefaultUICulture 'en-US' If set to $true then the required restart will be suppressed. You will need to restart the service before changes will take effect. The default value is $false. + + .PARAMETER ServerName + Specifies the host name that will be used when restarting the SQL Server + instance. If the SQL Server belongs to a cluster or availability group + specify the host name for the listener or cluster group. The specified + name must match the name that is used by the certificate specified for + the parameter `Thumbprint`. Default value is `localhost`. #> function Get-TargetResource { @@ -61,7 +68,11 @@ function Get-TargetResource [Parameter()] [System.Boolean] - $SuppressRestart = $false + $SuppressRestart = $false, + + [Parameter()] + [System.String] + $ServerName = 'localhost' ) Write-Verbose -Message ( @@ -165,6 +176,7 @@ function Get-TargetResource Ensure = [System.String] $ensureValue ServiceAccount = [System.String] $ServiceAccount SuppressRestart = [System.Boolean] $SuppressRestart + ServerName = [System.String] $ServerName } } @@ -191,6 +203,13 @@ function Get-TargetResource If set to $true then the required restart will be suppressed. You will need to restart the service before changes will take effect. The default value is $false. + + .PARAMETER ServerName + Specifies the host name that will be used when restarting the SQL Server + instance. If the SQL Server belongs to a cluster or availability group + specify the host name for the listener or cluster group. The specified + name must match the name that is used by the certificate specified for + the parameter `Thumbprint`. Default value is `localhost`. #> function Set-TargetResource { @@ -222,7 +241,11 @@ function Set-TargetResource [Parameter()] [System.Boolean] - $SuppressRestart = $false + $SuppressRestart = $false, + + [Parameter()] + [System.String] + $ServerName = 'localhost' ) # Configuration manager requires thumbprint to be lowercase or it won't display the configured certificate. @@ -282,7 +305,7 @@ function Set-TargetResource $script:localizedData.RestartingService -f $InstanceName ) - Restart-SqlService -ServerName localhost -InstanceName $InstanceName + Restart-SqlService -ServerName $ServerName -InstanceName $InstanceName } } @@ -310,6 +333,15 @@ function Set-TargetResource You will need to restart the service before changes will take effect. The default value is $false. + Not used in Test-TargetResource. + + .PARAMETER ServerName + Specifies the host name that will be used when restarting the SQL Server + instance. If the SQL Server belongs to a cluster or availability group + specify the host name for the listener or cluster group. The specified + name must match the name that is used by the certificate specified for + the parameter `Thumbprint`. Default value is `localhost`. + Not used in Test-TargetResource. #> function Test-TargetResource @@ -343,7 +375,11 @@ function Test-TargetResource [Parameter()] [System.Boolean] - $SuppressRestart = $false + $SuppressRestart = $false, + + [Parameter()] + [System.String] + $ServerName = 'localhost' ) $parameters = @{ diff --git a/source/DSCResources/DSC_SqlSecureConnection/DSC_SqlSecureConnection.schema.mof b/source/DSCResources/DSC_SqlSecureConnection/DSC_SqlSecureConnection.schema.mof index 084015edd..4213749d7 100644 --- a/source/DSCResources/DSC_SqlSecureConnection/DSC_SqlSecureConnection.schema.mof +++ b/source/DSCResources/DSC_SqlSecureConnection/DSC_SqlSecureConnection.schema.mof @@ -8,5 +8,5 @@ class DSC_SqlSecureConnection : OMI_BaseResource [Required, Description("Name of the account running the _SQL Server_ _Windows_ service. If this parameter is set to `'LocalSystem'` then a connection error is displayed, instead use the value `'SYSTEM'`.")] String ServiceAccount; [Write, Description("If set to `$true` then the required restart will be suppressed. You will need to restart the service before changes will take effect. The default value is `$false`.")] Boolean SuppressRestart; [Write, Description("If encryption should be enabled (`'Present'`) or disabled (`'Absent'`)."), ValueMap{"Present","Absent"}, Values{"Present","Absent"}] String Ensure; + [Write, Description("Specifies the host name that will be used when restarting the SQL Server instance. If the SQL Server belongs to a cluster or availability group specify the host name for the listener or cluster group. The specified name must match the name that is used by the certificate specified for the parameter `Thumbprint`. Default value is `localhost`.")] String ServerName; }; - diff --git a/source/Examples/Resources/SqlSecureConnection/1-ForceSecureConnection.ps1 b/source/Examples/Resources/SqlSecureConnection/1-ForceSecureConnection.ps1 index d86550fcf..ad40373c6 100644 --- a/source/Examples/Resources/SqlSecureConnection/1-ForceSecureConnection.ps1 +++ b/source/Examples/Resources/SqlSecureConnection/1-ForceSecureConnection.ps1 @@ -15,6 +15,7 @@ Configuration Example ForceEncryption = $true Ensure = 'Present' ServiceAccount = 'SqlSvc' + ServerName = 'host.company.local' } } } diff --git a/tests/Integration/DSC_SqlSecureConnection.Integration.Tests.ps1 b/tests/Integration/DSC_SqlSecureConnection.Integration.Tests.ps1 index 14938a548..71ede1b37 100644 --- a/tests/Integration/DSC_SqlSecureConnection.Integration.Tests.ps1 +++ b/tests/Integration/DSC_SqlSecureConnection.Integration.Tests.ps1 @@ -114,8 +114,10 @@ Describe "$($script:dscResourceName)_Integration" -Tag @('Integration_SQL2016', $_.ConfigurationName -eq $configurationName ` -and $_.ResourceId -eq $resourceId } + $resourceCurrentState.Thumbprint | Should -Be $env:SqlCertificateThumbprint - $resourceCurrentState.ForceEncryption | Should -Be $true + $resourceCurrentState.ForceEncryption | Should -BeTrue + $resourceCurrentState.ServerName | Should -Be 'localhost' } It 'Should return $true when Test-DscConfiguration is run' { @@ -169,8 +171,9 @@ Describe "$($script:dscResourceName)_Integration" -Tag @('Integration_SQL2016', -and $_.ResourceId -eq $resourceId } - $resultObject.Thumbprint | Should -BeNullOrEmpty - $resourceCurrentState.ForceEncryption | Should -Be $false + $resourceCurrentState.Thumbprint | Should -Be 'Empty' + $resourceCurrentState.ForceEncryption | Should -BeFalse + $resourceCurrentState.ServerName | Should -Be 'localhost' } It 'Should return $true when Test-DscConfiguration is run' { diff --git a/tests/Integration/DSC_SqlSecureConnection.config.ps1 b/tests/Integration/DSC_SqlSecureConnection.config.ps1 index 0b9072c85..6d13cb63a 100644 --- a/tests/Integration/DSC_SqlSecureConnection.config.ps1 +++ b/tests/Integration/DSC_SqlSecureConnection.config.ps1 @@ -43,11 +43,12 @@ Configuration DSC_SqlSecureConnection_AddSecureConnection_Config { SqlSecureConnection 'Integration_Test' { - InstanceName = $Node.InstanceName - Ensure = 'Present' - Thumbprint = $Node.Thumbprint - ServiceAccount = $Node.ServiceAccount + InstanceName = $Node.InstanceName + Ensure = 'Present' + Thumbprint = $Node.Thumbprint + ServiceAccount = $Node.ServiceAccount ForceEncryption = $true + ServerName = 'localhost' } } } @@ -64,9 +65,9 @@ Configuration DSC_SqlSecureConnection_RemoveSecureConnection_Config { SqlSecureConnection 'Integration_Test' { - InstanceName = $Node.InstanceName - Ensure = 'Absent' - Thumbprint = '' + InstanceName = $Node.InstanceName + Ensure = 'Absent' + Thumbprint = '' ServiceAccount = $Node.ServiceAccount } } diff --git a/tests/Unit/DSC_SqlSecureConnection.Tests.ps1 b/tests/Unit/DSC_SqlSecureConnection.Tests.ps1 index 679963db4..0e24ebbc3 100644 --- a/tests/Unit/DSC_SqlSecureConnection.Tests.ps1 +++ b/tests/Unit/DSC_SqlSecureConnection.Tests.ps1 @@ -97,6 +97,7 @@ Describe 'SqlSecureConnection\Get-TargetResource' -Tag 'Get' { BeforeEach { InModuleScope -ScriptBlock { $script:mockGetTargetResourceParameters.Ensure = 'Present' + $script:mockGetTargetResourceParameters.ServerName = 'MyHostName' } } @@ -125,6 +126,7 @@ Describe 'SqlSecureConnection\Get-TargetResource' -Tag 'Get' { $resultGetTargetResource.ServiceAccount | Should -Be 'SqlSvc' $resultGetTargetResource.ForceEncryption | Should -BeTrue $resultGetTargetResource.Ensure | Should -Be 'Present' + $resultGetTargetResource.ServerName | Should -Be 'MyHostName' } Should -Invoke -CommandName Get-EncryptedConnectionSetting -Exactly -Times 1 -Scope It @@ -165,6 +167,7 @@ Describe 'SqlSecureConnection\Get-TargetResource' -Tag 'Get' { $resultGetTargetResource.ServiceAccount | Should -Be 'SqlSvc' $resultGetTargetResource.ForceEncryption | Should -BeFalse $resultGetTargetResource.Ensure | Should -Be 'Absent' + $resultGetTargetResource.ServerName | Should -Be 'localhost' } Should -Invoke -CommandName Get-EncryptedConnectionSetting -Exactly -Times 1 -Scope It @@ -386,7 +389,9 @@ Describe 'SqlSecureConnection\Set-TargetResource' -Tag 'Set' { Should -Invoke -CommandName Set-EncryptedConnectionSetting -Exactly -Times 1 -Scope It -ParameterFilter { $Thumbprint -ceq '2A11AB1AB1A11111A1111AB111111AB11ABCDEFB'.ToLower() } Should -Invoke -CommandName Set-CertificatePermission -Exactly -Times 1 -Scope It -ParameterFilter { $Thumbprint -ceq '2A11AB1AB1A11111A1111AB111111AB11ABCDEFB'.ToLower() } - Should -Invoke -CommandName Restart-SqlService -Exactly -Times 1 -Scope It + Should -Invoke -CommandName Restart-SqlService -ParameterFilter { + $ServerName -eq 'localhost' + } -Exactly -Times 1 -Scope It } } @@ -436,12 +441,14 @@ Describe 'SqlSecureConnection\Set-TargetResource' -Tag 'Set' { InModuleScope -ScriptBlock { Set-StrictMode -Version 1.0 - { Set-TargetResource @mockSetTargetResourceParameters } | Should -Not -Throw + { Set-TargetResource @mockSetTargetResourceParameters -ServerName 'MyHostName'} | Should -Not -Throw } Should -Invoke -CommandName Set-EncryptedConnectionSetting -Exactly -Times 1 -Scope It Should -Invoke -CommandName Set-CertificatePermission -Exactly -Times 0 -Scope It - Should -Invoke -CommandName Restart-SqlService -Exactly -Times 1 -Scope It + Should -Invoke -CommandName Restart-SqlService -ParameterFilter { + $ServerName -eq 'MyHostName' + } -Exactly -Times 1 -Scope It } } diff --git a/tests/Unit/SqlServerDsc.Common.Tests.ps1 b/tests/Unit/SqlServerDsc.Common.Tests.ps1 index fb6378348..215e7ac59 100644 --- a/tests/Unit/SqlServerDsc.Common.Tests.ps1 +++ b/tests/Unit/SqlServerDsc.Common.Tests.ps1 @@ -1088,6 +1088,10 @@ Describe 'SqlServerDsc.Common\Restart-SqlService' -Tag 'RestartSqlService' { Restart-SqlService -ServerName $env:ComputerName -InstanceName 'MSSQLSERVER' -Timeout 4 -SkipClusterCheck } | Should -Throw -ExpectedMessage $mockErrorMessage + <# + Not using -Exactly to handle when CI is slower, result is + that there are 3 calls to Connect-SQL. + #> Should -Invoke -CommandName Connect-SQL -ParameterFilter { <# Make sure we assert the second call to Connect-SQL @@ -1096,7 +1100,7 @@ Describe 'SqlServerDsc.Common\Restart-SqlService' -Tag 'RestartSqlService' { we cannot use `$PSBoundParameters.ContainsKey('ErrorAction') -eq $true`. #> $ErrorAction -eq 'SilentlyContinue' - } -Scope It -Exactly -Times 2 + } -Scope It -Times 2 } } }