Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
for SQL Server Reporting Services or Power BI Report Server. Supports waiting
for dependent services, configurable wait time, and accepts pipeline input
from `Get-SqlDscRSConfiguration`.
- Added public commands `Get-SqlDscRSSslCertificateBinding`,
`Add-SqlDscRSSslCertificateBinding`, `Remove-SqlDscRSSslCertificateBinding`,
and `Set-SqlDscRSSslCertificateBinding` to manage SSL certificate bindings
for SQL Server Reporting Services or Power BI Report Server. These commands
wrap the `ListSSLCertificateBindings`, `CreateSSLCertificateBinding`, and
`RemoveSSLCertificateBinding` CIM methods. The `Set-SqlDscRSSslCertificateBinding`
command provides a declarative approach to set SSL bindings to an exact list.
- Added public command `New-SqlDscRSEncryptionKey` to delete and regenerate the
Reporting Services encryption key. Wraps the `DeleteEncryptionKey` CIM method.
Warning: This operation cannot be undone and renders all encrypted content
Expand All @@ -237,6 +244,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
by calling the `InitializeReportServer` CIM method. Used to complete initial
configuration after database and URL setup
([issue #2014](https://github.com/dsccommunity/SqlServerDsc/issues/2014)).
- Added public command `Get-SqlDscRSSslCertificate` to list available SSL
certificates that can be used for Reporting Services. Wraps the
`ListSSLCertificates` CIM method.
- Added public command `Get-SqlDscRSIPAddress` to list IP addresses available
for URL reservations. Wraps the `ListIPAddresses` CIM method.
- Added public command `Get-SqlDscRSDatabaseInstallation` to determine whether
Expand Down
77 changes: 77 additions & 0 deletions azure-pipelines.yml
Original file line number Diff line number Diff line change
Expand Up @@ -712,6 +712,83 @@ stages:
testResultsFiles: '$(buildFolderName)/$(testResultFolderName)/NUnit*.xml'
testRunTitle: 'Integration Commands ($(TEST_CONFIGURATION) / $(JOB_VMIMAGE))'

- stage: Integration_Test_Commands_BIReportServer_Secure
displayName: 'Integration Test Commands - BI Report Server SSL/TLS'
dependsOn: Build #Integration_Test_Commands_SqlServer
jobs:
- job: Test_Integration
displayName: 'Commands'
strategy:
matrix:
PowerBI_WIN2022:
JOB_VMIMAGE: 'windows-2022'
TEST_CONFIGURATION: 'Integration_PowerBI'
PowerBI_WIN2025:
JOB_VMIMAGE: 'windows-2025'
TEST_CONFIGURATION: 'Integration_PowerBI'
pool:
vmImage: $(JOB_VMIMAGE)
timeoutInMinutes: '0'
steps:
- task: DownloadPipelineArtifact@2
displayName: 'Download Build Artifact'
inputs:
buildType: 'current'
artifactName: $(buildArtifactName)
targetPath: '$(Build.SourcesDirectory)/$(buildFolderName)'
- task: PowerShell@2
name: configureWinRM
displayName: 'Configure WinRM'
inputs:
targetType: 'inline'
script: 'winrm quickconfig -quiet'
pwsh: false
- powershell: |
Import-Module -Name ./tests/TestHelpers/CommonTestHelper.psm1
Remove-PowerShellModuleFromCI -Name @('SqlServer', 'SQLPS')
Remove-Module -Name CommonTestHelper
name: cleanCIWorker
displayName: 'Clean CI worker'
- powershell: |
./build.ps1 -Tasks test -CodeCoverageThreshold 0 -PesterTag $(TEST_CONFIGURATION) -PesterPath @(
# Run the integration tests in a specific group order.
# Group 0
'tests/Integration/Commands/Prerequisites.Integration.Tests.ps1'
'tests/Integration/Commands/Prerequisites.RSDB.Integration.Tests.ps1'
'tests/Integration/Commands/Save-SqlDscSqlServerMediaFile.Integration.Tests.ps1'
'tests/Integration/Commands/Import-SqlDscPreferredModule.Integration.Tests.ps1'
# Group 1
'tests/Integration/Commands/Install-SqlDscPowerBIReportServer.Integration.Tests.ps1'
# Group 2
'tests/Integration/Commands/Request-SqlDscRSDatabaseScript.Integration.Tests.ps1'
'tests/Integration/Commands/Request-SqlDscRSDatabaseRightsScript.Integration.Tests.ps1'
# Group 3
'tests/Integration/Commands/Enable-SqlDscRsSecureConnection.Integration.Tests.ps1'
'tests/Integration/Commands/Set-SqlDscRSVirtualDirectory.Integration.Tests.ps1'
'tests/Integration/Commands/Pre.Set-SqlDscRSUrlReservation.Integration.Tests.ps1'
'tests/Integration/Commands/Add-SqlDscRSSslCertificateBinding.Integration.Tests.ps1'
'tests/Integration/Commands/Set-SqlDscRSDatabaseConnection.Integration.Tests.ps1'
'tests/Integration/Commands/Restart-SqlDscRSService.Integration.Tests.ps1'
# Group 4
'tests/Integration/Commands/Initialize-SqlDscRS.Integration.Tests.ps1'
# Group 5 - Post-initialization validation
'tests/Integration/Commands/Post.Certificate.RS.Integration.Tests.ps1'
# Group 6
'tests/Integration/Commands/Get-SqlDscRSSslCertificate.Integration.Tests.ps1'
'tests/Integration/Commands/Get-SqlDscRSSslCertificateBinding.Integration.Tests.ps1'
'tests/Integration/Commands/Remove-SqlDscRSSslCertificateBinding.Integration.Tests.ps1'
'tests/Integration/Commands/Set-SqlDscRSSslCertificateBinding.Integration.Tests.ps1'
)
name: test
displayName: 'Run Integration Test'
- task: PublishTestResults@2
displayName: 'Publish Test Results'
condition: succeededOrFailed()
inputs:
testResultsFormat: 'NUnit'
testResultsFiles: '$(buildFolderName)/$(testResultFolderName)/NUnit*.xml'
testRunTitle: 'Integration Commands ($(TEST_CONFIGURATION) / $(JOB_VMIMAGE))'

- stage: Integration_Test_Resources_SqlServer
displayName: 'Integration Test Resources - SQL Server'
dependsOn: Quality_Test_and_Unit_Test
Expand Down
190 changes: 190 additions & 0 deletions source/Public/Add-SqlDscRSSslCertificateBinding.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,190 @@
<#
.SYNOPSIS
Adds an SSL certificate binding for SQL Server Reporting Services.

.DESCRIPTION
Adds an SSL certificate binding for SQL Server Reporting Services or
Power BI Report Server by calling the `CreateSSLCertificateBinding`
method on the `MSReportServer_ConfigurationSetting` CIM instance.

This command binds an SSL certificate to a specific application,
IP address, and port for the Reporting Services instance. URL reservations
must be set prior for the specified application to determine if the TLS/SSL
certificate binding is valid.

The configuration CIM instance can be obtained using the
`Get-SqlDscRSConfiguration` command and passed via the pipeline.

.PARAMETER Configuration
Specifies the `MSReportServer_ConfigurationSetting` CIM instance for
the Reporting Services instance. This can be obtained using the
`Get-SqlDscRSConfiguration` command. This parameter accepts pipeline
input.

.PARAMETER Application
Specifies the application for which to create the SSL binding.
Valid values are:
- 'ReportServerWebService': The Report Server Web Service.
- 'ReportServerWebApp': The Reports web application (SQL Server 2016+).
- 'ReportManager': The Report Manager (SQL Server 2014 and earlier).

.PARAMETER CertificateHash
Specifies the thumbprint (hash) of the SSL certificate to bind.
The certificate must be installed in the local machine certificate
store.

.PARAMETER IPAddress
Specifies the IP address for the SSL binding. Use '0.0.0.0' to bind
to all IP addresses. Default value is '0.0.0.0'.

.PARAMETER Port
Specifies the port number for the SSL binding. Default value is 443.

.PARAMETER Lcid
Specifies the language code identifier (LCID) for the operation.
If not specified, defaults to the operating system language. Common
values include 1033 for English (US).

.PARAMETER PassThru
If specified, returns the configuration CIM instance after adding
the SSL certificate binding.

.PARAMETER Force
If specified, suppresses the confirmation prompt.

.EXAMPLE
Get-SqlDscRSConfiguration -InstanceName 'SSRS' | Add-SqlDscRSSslCertificateBinding -Application 'ReportServerWebService' -CertificateHash 'A1B2C3D4E5F6...'

Adds an SSL certificate binding for the Report Server Web Service
using the default IP address (0.0.0.0) and port (443).

.EXAMPLE
$config = Get-SqlDscRSConfiguration -InstanceName 'SSRS'
Add-SqlDscRSSslCertificateBinding -Configuration $config -Application 'ReportServerWebApp' -CertificateHash 'A1B2C3D4E5F6...' -Port 8443 -Confirm:$false

Adds an SSL certificate binding on port 8443 without confirmation.

.EXAMPLE
Get-SqlDscRSConfiguration -InstanceName 'SSRS' | Add-SqlDscRSSslCertificateBinding -Application 'ReportServerWebService' -CertificateHash 'A1B2C3D4E5F6...' -PassThru

Adds the SSL binding and returns the configuration CIM instance.

.INPUTS
`Microsoft.Management.Infrastructure.CimInstance`

Accepts MSReportServer_ConfigurationSetting CIM instance via pipeline.

.OUTPUTS
None. By default, this command does not generate any output.

.OUTPUTS
`Microsoft.Management.Infrastructure.CimInstance`

When PassThru is specified, returns the MSReportServer_ConfigurationSetting
CIM instance.

.NOTES
The Reporting Services service may need to be restarted for the change
to take effect.

.LINK
https://docs.microsoft.com/en-us/sql/reporting-services/wmi-provider-library-reference/configurationsetting-method-createsslcertificatebinding
#>
function Add-SqlDscRSSslCertificateBinding
{
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('UseSyntacticallyCorrectExamples', '', Justification = 'Because the examples use pipeline input the rule cannot validate.')]
[CmdletBinding(SupportsShouldProcess = $true, ConfirmImpact = 'Medium')]
[OutputType([System.Object])]
param
(
[Parameter(Mandatory = $true, ValueFromPipeline = $true)]
[System.Object]
$Configuration,

[Parameter(Mandatory = $true)]
[ValidateSet('ReportServerWebService', 'ReportServerWebApp', 'ReportManager')]
[System.String]
$Application,

[Parameter(Mandatory = $true)]
[System.String]
$CertificateHash,

[Parameter()]
[System.String]
$IPAddress = '0.0.0.0',

[Parameter()]
[System.Int32]
$Port = 443,

[Parameter()]
[System.Int32]
$Lcid,

[Parameter()]
[System.Management.Automation.SwitchParameter]
$PassThru,

[Parameter()]
[System.Management.Automation.SwitchParameter]
$Force
)

process
{
if ($Force.IsPresent -and -not $Confirm)
{
$ConfirmPreference = 'None'
}

$instanceName = $Configuration.InstanceName

if (-not $PSBoundParameters.ContainsKey('Lcid'))
{
$Lcid = (Get-OperatingSystem).OSLanguage
}

Write-Verbose -Message ($script:localizedData.Add_SqlDscRSSslCertificateBinding_Adding -f $CertificateHash, $Application, $instanceName)

$descriptionMessage = $script:localizedData.Add_SqlDscRSSslCertificateBinding_ShouldProcessDescription -f $CertificateHash, $Application, $instanceName
$confirmationMessage = $script:localizedData.Add_SqlDscRSSslCertificateBinding_ShouldProcessConfirmation -f $CertificateHash, $Application
$captionMessage = $script:localizedData.Add_SqlDscRSSslCertificateBinding_ShouldProcessCaption

if ($PSCmdlet.ShouldProcess($descriptionMessage, $confirmationMessage, $captionMessage))
{
$invokeRsCimMethodParameters = @{
CimInstance = $Configuration
MethodName = 'CreateSSLCertificateBinding'
Arguments = @{
Application = $Application
CertificateHash = $CertificateHash.ToLower()
IPAddress = $IPAddress
Port = $Port
Lcid = $Lcid
}
}

try
{
$null = Invoke-RsCimMethod @invokeRsCimMethodParameters -ErrorAction 'Stop'
}
catch
{
$PSCmdlet.ThrowTerminatingError(
[System.Management.Automation.ErrorRecord]::new(
($script:localizedData.Add_SqlDscRSSslCertificateBinding_FailedToAdd -f $instanceName, $_.Exception.Message),
'ASRSSCB0001',
[System.Management.Automation.ErrorCategory]::InvalidOperation,
$Configuration
)
)
}
}

if ($PassThru.IsPresent)
{
return $Configuration
}
}
}
15 changes: 7 additions & 8 deletions source/Public/Get-SqlDscRSDatabaseInstallation.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -99,14 +99,13 @@ function Get-SqlDscRSDatabaseInstallation
}
catch
{
$PSCmdlet.ThrowTerminatingError(
[System.Management.Automation.ErrorRecord]::new(
($script:localizedData.Get_SqlDscRSDatabaseInstallation_FailedToGet -f $instanceName, $_.Exception.Message),
'GSRSDI0001',
[System.Management.Automation.ErrorCategory]::InvalidOperation,
$Configuration
)
)
$errorMessage = $script:localizedData.Get_SqlDscRSDatabaseInstallation_FailedToGet -f $instanceName

$exception = New-Exception -Message $errorMessage -ErrorRecord $_

$errorRecord = New-ErrorRecord -Exception $exception -ErrorId 'GSRSDI0001' -ErrorCategory ([System.Management.Automation.ErrorCategory]::InvalidOperation) -TargetObject $Configuration

$PSCmdlet.ThrowTerminatingError($errorRecord)
}
}
}
Loading
Loading