Skip to content

Commit 32c5546

Browse files
committed
Add TLS protocol conversion and testing functions for SQL Server 2025
1 parent 55257e3 commit 32c5546

6 files changed

Lines changed: 455 additions & 0 deletions

File tree

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
<#
2+
.SYNOPSIS
3+
Converts a friendly protocol identifier to the SCHANNEL registry key name.
4+
5+
.DESCRIPTION
6+
Maps user-friendly protocol names accepted by the public commands
7+
(e.g. Tls12) to the actual SCHANNEL registry key names (e.g. 'TLS 1.2').
8+
9+
.PARAMETER Protocol
10+
The protocol identifier, e.g. 'Tls12', 'Ssl3', 'Tls'.
11+
12+
.OUTPUTS
13+
System.String
14+
#>
15+
function ConvertTo-TlsProtocolRegistryKeyName
16+
{
17+
[CmdletBinding()]
18+
param
19+
(
20+
[Parameter(Mandatory = $true)]
21+
[System.String]
22+
$Protocol
23+
)
24+
25+
$protocolRegistryKeyName = switch ($Protocol.ToLower())
26+
{
27+
'ssl2'
28+
{
29+
'SSL 2.0'
30+
}
31+
32+
'ssl3'
33+
{
34+
'SSL 3.0'
35+
}
36+
37+
'tls'
38+
{
39+
'TLS 1.0'
40+
}
41+
42+
'tls11'
43+
{
44+
'TLS 1.1'
45+
}
46+
47+
'tls12'
48+
{
49+
'TLS 1.2'
50+
}
51+
52+
'tls13'
53+
{
54+
'TLS 1.3'
55+
}
56+
57+
default
58+
{
59+
$message = "Unknown protocol '$Protocol'. Valid values: Ssl2, Ssl3, Tls, Tls11, Tls12, Tls13."
60+
$exception = New-Exception -Message $message
61+
$errorRecord = New-ErrorRecord -Exception $exception -ErrorId 'InvalidProtocol' -ErrorCategory ([System.Management.Automation.ErrorCategory]::InvalidArgument) -TargetObject $Protocol
62+
$PSCmdlet.ThrowTerminatingError($errorRecord)
63+
}
64+
}
65+
66+
return $protocolRegistryKeyName
67+
}

source/Public/Test-TlsProtocol.ps1

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
<#
2+
.SYNOPSIS
3+
Tests if specified TLS/SSL protocols are enabled on the local machine.
4+
5+
.DESCRIPTION
6+
Tests one or more SCHANNEL protocol keys under
7+
HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols
8+
to determine whether the protocol is enabled for server-side connections.
9+
10+
.PARAMETER Protocol
11+
One or more protocol names to check. Valid values: Ssl2, Ssl3, Tls, Tls11, Tls12, Tls13.
12+
13+
.PARAMETER Client
14+
When specified, will check the protocol `Client` registry
15+
key instead of the default `Server` key.
16+
17+
.PARAMETER Disabled
18+
When specified, test that the protocol(s) are disabled. By default the
19+
command tests that the protocol(s) are enabled.
20+
21+
.OUTPUTS
22+
System.Boolean
23+
#>
24+
function Test-TlsProtocol
25+
{
26+
[CmdletBinding()]
27+
[OutputType([System.Boolean])]
28+
param
29+
(
30+
[Parameter(Mandatory = $true)]
31+
[ValidateSet('Ssl2', 'Ssl3', 'Tls', 'Tls11', 'Tls12', 'Tls13', IgnoreCase = $true)]
32+
[System.String[]]
33+
$Protocol,
34+
35+
[Parameter()]
36+
[System.Management.Automation.SwitchParameter]
37+
$Client,
38+
39+
[Parameter()]
40+
[System.Management.Automation.SwitchParameter]
41+
$Disabled
42+
)
43+
44+
foreach ($p in $Protocol)
45+
{
46+
$protocolTarget = if ($Client.IsPresent) { 'Client' } else { 'Server' }
47+
48+
$protocolKeyName = ConvertTo-TlsProtocolRegistryKeyName -Protocol $p
49+
50+
$regPath = "HKLM:\\SYSTEM\\CurrentControlSet\\Control\\SecurityProviders\\SCHANNEL\\Protocols\\$protocolKeyName\\$protocolTarget"
51+
52+
$protocolEnabled = Get-RegistryPropertyValue -Path $regPath -Name 'Enabled' -ErrorAction SilentlyContinue
53+
$protocolDisabled = Get-RegistryPropertyValue -Path $regPath -Name 'DisabledByDefault' -ErrorAction SilentlyContinue
54+
55+
$protocolEnabled = if ($null -ne $protocolEnabled)
56+
{
57+
[System.Int32] $protocolEnabled
58+
}
59+
else
60+
{
61+
$null
62+
}
63+
64+
$protocolDisabled = if ($null -ne $protocolDisabled)
65+
{
66+
[System.Int32] $protocolDisabled
67+
}
68+
else
69+
{
70+
$null
71+
}
72+
73+
if ($Disabled.IsPresent)
74+
{
75+
# Consider protocol enabled when both Enabled and DisabledByDefault are missing
76+
if ($null -eq $protocolEnabled -and $null -eq $protocolDisabled)
77+
{
78+
return $false
79+
}
80+
81+
# Consider protocol disabled when Enabled != 1 or DisabledByDefault == 1
82+
if (($null -ne $protocolEnabled -and $protocolEnabled -ne 1) -or ($null -ne $protocolDisabled -and $protocolDisabled -eq 1))
83+
{
84+
continue
85+
}
86+
else
87+
{
88+
return $false
89+
}
90+
}
91+
else
92+
{
93+
if ($null -eq $protocolEnabled -and $null -eq $protocolDisabled)
94+
{
95+
continue
96+
}
97+
98+
if ($protocolEnabled -eq 1 -and $protocolDisabled -ne 1)
99+
{
100+
continue
101+
}
102+
else
103+
{
104+
return $false
105+
}
106+
}
107+
}
108+
109+
return $true
110+
}

tests/Integration/Commands/Prerequisites.Integration.Tests.ps1

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,17 @@ Describe 'Prerequisites' {
254254
}
255255
}
256256

257+
Context 'Ensure TLS 1.2 is enabled' -Tag @('Integration_SQL2025') {
258+
# SQL Server 2025 installation can fail when TLS 1.2 is disabled:
259+
# https://learn.microsoft.com/en-us/sql/sql-server/sql-server-2025-known-issues?view=sql-server-ver17#sql-server-2025-installation-fails-when-tls-12-is-disabled
260+
It 'Should have TLS 1.2 enabled on the node' -Tag @('Integration_SQL2025') {
261+
# Test-TlsProtocol returns $true when the protocol is enabled.
262+
# Assert for both Server and Client registry keys.
263+
(Test-TlsProtocol -Protocol 'Tls12') | Should -BeTrue
264+
(Test-TlsProtocol -Protocol 'Tls12' -Client) | Should -BeTrue
265+
}
266+
}
267+
257268
Context 'Download correct SQL Server 2017 Reporting Services installation executable' {
258269
It 'Should download SQL Server 2017 Reporting Services installation executable' -Tag @('Integration_SQL2017_RS') {
259270
# Microsoft SQL Server 2017 Reporting Services (14.0.601.20 - 2023-02-14) - https://www.microsoft.com/en-us/download/details.aspx?id=55252

tests/Integration/Resources/DSC_SqlSetup.Integration.Tests.ps1

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -255,6 +255,17 @@ Describe "$($script:dscResourceName)_Integration" -Tag @('Integration_SQL2016',
255255
}
256256
}
257257

258+
Context 'Ensure TLS 1.2 is enabled' -Tag @('Integration_SQL2025') {
259+
# SQL Server 2025 installation can fail when TLS 1.2 is disabled:
260+
# https://learn.microsoft.com/en-us/sql/sql-server/sql-server-2025-known-issues?view=sql-server-ver17#sql-server-2025-installation-fails-when-tls-12-is-disabled
261+
It 'Should have TLS 1.2 enabled on the node' -Tag @('Integration_SQL2025') {
262+
# Test-TlsProtocol returns $true when the protocol is enabled.
263+
# Assert for both Server and Client registry keys.
264+
(Test-TlsProtocol -Protocol 'Tls12') | Should -BeTrue
265+
(Test-TlsProtocol -Protocol 'Tls12' -Client) | Should -BeTrue
266+
}
267+
}
268+
258269
Context ('When using configuration <_>') -ForEach @(
259270
"$($script:dscResourceName)_InstallDatabaseEngineNamedInstanceAsSystem_Config"
260271
) -Skip:$(if ($env:SKIP_DATABASE_ENGINE_INSTANCE) { $true } else { $false }) {
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', '', Justification = 'Suppressing this rule because Script Analyzer does not understand Pester syntax.')]
2+
param ()
3+
4+
BeforeDiscovery {
5+
try
6+
{
7+
if (-not (Get-Module -Name 'DscResource.Test'))
8+
{
9+
if (-not (Get-Module -Name 'DscResource.Test' -ListAvailable))
10+
{
11+
& "$PSScriptRoot/../../../build.ps1" -Tasks 'noop' 3>&1 4>&1 5>&1 6>&1 > $null
12+
}
13+
14+
Import-Module -Name 'DscResource.Test' -Force -ErrorAction 'Stop'
15+
}
16+
}
17+
catch [System.IO.FileNotFoundException]
18+
{
19+
throw 'DscResource.Test module dependency not found. Please run ".\build.ps1 -ResolveDependency -Tasks noop" first.'
20+
}
21+
}
22+
23+
BeforeAll {
24+
$script:moduleName = 'SqlServerDsc'
25+
26+
$env:SqlServerDscCI = $true
27+
28+
Import-Module -Name $script:moduleName -ErrorAction 'Stop'
29+
30+
$PSDefaultParameterValues['InModuleScope:ModuleName'] = $script:moduleName
31+
$PSDefaultParameterValues['Mock:ModuleName'] = $script:moduleName
32+
$PSDefaultParameterValues['Should:ModuleName'] = $script:moduleName
33+
}
34+
35+
AfterAll {
36+
$PSDefaultParameterValues.Remove('InModuleScope:ModuleName')
37+
$PSDefaultParameterValues.Remove('Mock:ModuleName')
38+
$PSDefaultParameterValues.Remove('Should:ModuleName')
39+
40+
Remove-Item -Path 'env:SqlServerDscCI'
41+
}
42+
43+
Describe 'ConvertTo-TlsProtocolRegistryKeyName' -Tag 'Private' {
44+
Context 'When converting known friendly protocol names' {
45+
It 'Maps Tls12 to TLS 1.2' {
46+
InModuleScope -ScriptBlock {
47+
ConvertTo-TlsProtocolRegistryKeyName -Protocol 'Tls12' | Should -Be 'TLS 1.2'
48+
}
49+
}
50+
51+
It 'Maps Tls11 to TLS 1.1' {
52+
InModuleScope -ScriptBlock {
53+
ConvertTo-TlsProtocolRegistryKeyName -Protocol 'Tls11' | Should -Be 'TLS 1.1'
54+
}
55+
}
56+
57+
It 'Maps Tls to TLS 1.0' {
58+
InModuleScope -ScriptBlock {
59+
ConvertTo-TlsProtocolRegistryKeyName -Protocol 'Tls' | Should -Be 'TLS 1.0'
60+
}
61+
}
62+
63+
It 'Maps Ssl3 to SSL 3.0' {
64+
InModuleScope -ScriptBlock {
65+
ConvertTo-TlsProtocolRegistryKeyName -Protocol 'Ssl3' | Should -Be 'SSL 3.0'
66+
}
67+
}
68+
69+
It 'Maps Ssl2 to SSL 2.0' {
70+
InModuleScope -ScriptBlock {
71+
ConvertTo-TlsProtocolRegistryKeyName -Protocol 'Ssl2' | Should -Be 'SSL 2.0'
72+
}
73+
}
74+
75+
It 'Maps Tls13 to TLS 1.3' {
76+
InModuleScope -ScriptBlock {
77+
ConvertTo-TlsProtocolRegistryKeyName -Protocol 'Tls13' | Should -Be 'TLS 1.3'
78+
}
79+
}
80+
}
81+
82+
Context 'When given an unknown protocol' {
83+
It 'Should throw a terminating error' {
84+
InModuleScope -ScriptBlock {
85+
{ ConvertTo-TlsProtocolRegistryKeyName -Protocol 'NoSuchProto' } | Should -Throw -ErrorId 'InvalidProtocol,ConvertTo-TlsProtocolRegistryKeyName'
86+
}
87+
}
88+
}
89+
}

0 commit comments

Comments
 (0)