diff --git a/coverage.xml b/coverage.xml new file mode 100644 index 000000000..7fe532563 --- /dev/null +++ b/coverage.xml @@ -0,0 +1,458 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/source/DSCResources/DSC_SqlRS/DSC_SqlRS.psm1 b/source/DSCResources/DSC_SqlRS/DSC_SqlRS.psm1 index 747164102..623ecd55e 100644 --- a/source/DSCResources/DSC_SqlRS/DSC_SqlRS.psm1 +++ b/source/DSCResources/DSC_SqlRS/DSC_SqlRS.psm1 @@ -68,6 +68,7 @@ function Get-TargetResource UseSsl = $false IsInitialized = $false Encrypt = $Encrypt + WindowsServiceIdentityActual = $null } $reportingServicesData = Get-ReportingServicesData -InstanceName $InstanceName @@ -86,8 +87,9 @@ function Get-TargetResource } $isInitialized = $reportingServicesData.Configuration.IsInitialized + $getTargetResourceResult.IsInitialized = [System.Boolean] $isInitialized - [System.Boolean] $getTargetResourceResult.IsInitialized = $isInitialized + $getTargetResourceResult.WindowsServiceIdentityActual = $reportingServicesData.Configuration.WindowsServiceIdentityActual if ( $isInitialized ) { @@ -249,6 +251,10 @@ function Set-TargetResource [System.String] $DatabaseInstanceName, + [Parameter()] + [System.Management.Automation.PSCredential] + $ServiceAccount, + [Parameter()] [System.String] $ReportServerVirtualDirectory, @@ -283,7 +289,12 @@ function Set-TargetResource if ( $null -ne $reportingServicesData.Configuration ) { - if ( $reportingServicesData.SqlVersion -ge 14 ) + if ( $null -ne $reportingServicesData.Configuration.ServiceName ) + { + $reportingServicesServiceName = $reportServicesData.Configuration.ServiceName + $reportingServicesDatabaseName = 'ReportServer' + } + elseif ( $reportingServicesData.SqlVersion -ge 14 ) { if ( [string]::IsNullOrEmpty($ReportServerVirtualDirectory) ) { @@ -354,6 +365,22 @@ function Set-TargetResource # We will restart Reporting Services after initialization (unless SuppressRestart is set) $restartReportingService = $true + if ($PSBoundParameters.ContainsKey('ServiceAccount') -and $ServiceAccount.UserName -ne $reportingServicesData.Configuration.WindowsServiceIdentityActual) + { + Write-Verbose -Message ($script:localizedData.SetServiceAccount -f $ServiceAccount.UserName, $reportingServicesData.Configuration.WindowsServiceIdentityActual) -Verbose + $invokeRsCimMethodParameters = @{ + CimInstance = $reportingServicesData.Configuration + MethodName = 'SetWindowsServiceIdentity' + Arguments = @{ + Account = $ServiceAccount.UserName + Password = $ServiceAccount.GetNetworkCredential().Password + UseBuiltInAccount = $false + } + } + + $setWindowsServiceIdentityResult = Invoke-RsCimMethod @invokeRsCimMethodParameters + } + # If no Report Server reserved URLs have been specified, use the default one. if ( $null -eq $ReportServerReservedUrl ) { @@ -597,6 +624,22 @@ function Set-TargetResource $currentConfig = Get-TargetResource @getTargetResourceParameters + if ($PSBoundParameters.ContainsKey('ServiceAccount') -and $ServiceAccount.UserName -ne $currentConfig.WindowsServiceIdentityActual) + { + Write-Verbose -Message ($script:localizedData.SetServiceAccount -f $ServiceAccount.UserName,$currentConfig.WindowsServiceIdentityActual) -Verbose + $invokeRsCimMethodParameters = @{ + CimInstance = $reportingServicesData.Configuration + MethodName = 'SetWindowsServiceIdentity' + Arguments = @{ + Account = $ServiceAccount.UserName + Password = $ServiceAccount.GetNetworkCredential().Password + UseBuiltInAccount = $false + } + } + + $setWindowsServiceIdentityResult = Invoke-RsCimMethod @invokeRsCimMethodParameters + } + <# SQL Server Reporting Services virtual directories (both Report Server and Report Manager/Report Web App) are a @@ -890,6 +933,10 @@ function Test-TargetResource [System.String] $DatabaseInstanceName, + [Parameter()] + [System.Management.Automation.PSCredential] + $ServiceAccount, + [Parameter()] [System.String] $ReportServerVirtualDirectory, @@ -1003,6 +1050,12 @@ function Test-TargetResource $result = $false } + if ($PSBoundParameters.ContainsKey('ServiceAccount') -and $ServiceAccount.UserName -ne $currentConfig.WindowsServiceIdentityActual) + { + Write-Verbose -Message "The value for ServiceAccount is not in the desired state. Should be '$($ServiceAccount.UserName))', but is '$($currentConfig.WindowsServiceIdentityActual)'." + $result = $false + } + $result } diff --git a/source/DSCResources/DSC_SqlRS/DSC_SqlRS.schema.mof b/source/DSCResources/DSC_SqlRS/DSC_SqlRS.schema.mof index c4d7fdc3a..539fdbb77 100644 --- a/source/DSCResources/DSC_SqlRS/DSC_SqlRS.schema.mof +++ b/source/DSCResources/DSC_SqlRS/DSC_SqlRS.schema.mof @@ -4,6 +4,7 @@ class DSC_SqlRS : OMI_BaseResource [Key, Description("Name of the _SQL Server Reporting Services_ instance to be configured.")] String InstanceName; [Required, Description("Name of the _SQL Server_ to host the _Reporting Services_ database.")] String DatabaseServerName; [Required, Description("Name of the _SQL Server_ instance to host the _Reporting Services_ database.")] String DatabaseInstanceName; + [Write, EmbeddedInstance("MSFT_Credential"), Description("The service account that should be used when running the _Windows_ service.")] String ServiceAccount; [Write, Description("_Report Server Web Service_ virtual directory. Optional.")] String ReportServerVirtualDirectory; [Write, Description("_Report Manager_ or _Report Web App_ virtual directory name. Optional.")] String ReportsVirtualDirectory; [Write, Description("_Report Server_ URL reservations. Optional. If not specified, `'http://+:80'` URL reservation will be used.")] String ReportServerReservedUrl[]; diff --git a/source/DSCResources/DSC_SqlRS/en-US/DSC_SqlRS.strings.psd1 b/source/DSCResources/DSC_SqlRS/en-US/DSC_SqlRS.strings.psd1 index 07dd9a79e..4824276e0 100644 --- a/source/DSCResources/DSC_SqlRS/en-US/DSC_SqlRS.strings.psd1 +++ b/source/DSCResources/DSC_SqlRS/en-US/DSC_SqlRS.strings.psd1 @@ -5,4 +5,5 @@ ConvertFrom-StringData @' ReportingServicesNotFound = SQL Reporting Services instance '{0}' does not exist. GetConfiguration = Get the current reporting services configuration for the instance '{0}'. RestartToFinishInitialization = Restarting Reporting Services to finish initialization. + SetServiceAccount = The WindowsServiceIdentityActual should be '{0}' but is '{1}'. '@ diff --git a/tests/Unit/DSC_SqlRS.Tests.ps1 b/tests/Unit/DSC_SqlRS.Tests.ps1 index 81c270cdd..34bcf9092 100644 --- a/tests/Unit/DSC_SqlRS.Tests.ps1 +++ b/tests/Unit/DSC_SqlRS.Tests.ps1 @@ -77,7 +77,7 @@ Describe 'SqlRS\Get-TargetResource' -Tag 'Get' { $mockReportingServicesDatabaseServerName = 'SERVER' $mockReportingServicesDatabaseNamedInstanceName = $mockNamedInstanceName $mockReportingServicesDatabaseDefaultInstanceName = $mockDefaultInstanceName - + $mockServiceAccountName = 'Contoso\ServiceAccount' $mockReportsApplicationName = 'ReportServerWebApp' $mockReportServerApplicationName = 'ReportServerWebService' $mockReportsApplicationUrl = 'http://+:80' @@ -112,7 +112,8 @@ Describe 'SqlRS\Get-TargetResource' -Tag 'Get' { Add-Member -MemberType NoteProperty -Name 'InstanceName' -Value $mockNamedInstanceName -PassThru | Add-Member -MemberType NoteProperty -Name 'VirtualDirectoryReportServer' -Value $mockVirtualDirectoryReportServerName -PassThru | Add-Member -MemberType NoteProperty -Name 'VirtualDirectoryReportManager' -Value $mockVirtualDirectoryReportManagerName -PassThru | - Add-Member -MemberType NoteProperty -Name 'SecureConnectionLevel' -Value $mockDynamicSecureConnectionLevel -PassThru -Force + Add-Member -MemberType NoteProperty -Name 'SecureConnectionLevel' -Value $mockDynamicSecureConnectionLevel -PassThru | + Add-Member -MemberType NoteProperty -Name WindowsServiceIdentityActual -Value $mockServiceAccountName -PassThru -Force ), ( # Array is a regression test for issue #819. @@ -132,8 +133,9 @@ Describe 'SqlRS\Get-TargetResource' -Tag 'Get' { Add-Member -MemberType NoteProperty -Name 'IsInitialized' -Value $false -PassThru | Add-Member -MemberType NoteProperty -Name 'InstanceName' -Value $mockDefaultInstanceName -PassThru | Add-Member -MemberType NoteProperty -Name 'VirtualDirectoryReportServer' -Value '' -PassThru | - Add-Member -MemberType NoteProperty -Name 'VirtualDirectoryReportManager' -Value '' -PassThru -Force | - Add-Member -MemberType NoteProperty -Name 'SecureConnectionLevel' -Value $mockDynamicSecureConnectionLevel -PassThru -Force + Add-Member -MemberType NoteProperty -Name 'VirtualDirectoryReportManager' -Value '' -PassThru | + Add-Member -MemberType NoteProperty -Name 'SecureConnectionLevel' -Value $mockDynamicSecureConnectionLevel -PassThru | + Add-Member -MemberType NoteProperty -Name WindowsServiceIdentityActual -Value $mockServiceAccountName -PassThru -Force } Mock -CommandName Invoke-RsCimMethod -MockWith $mockInvokeRsCimMethod_ListReservedUrls -ParameterFilter { @@ -195,6 +197,7 @@ Describe 'SqlRS\Get-TargetResource' -Tag 'Get' { InModuleScope -ScriptBlock { Set-StrictMode -Version 1.0 + $mockServiceAccountName = 'Contoso\ServiceAccount' $mockReportsApplicationUrl = 'http://+:80' $mockReportServerApplicationUrl = 'http://+:80' $mockVirtualDirectoryReportManagerName = 'Reports_SQL2016' @@ -208,6 +211,7 @@ Describe 'SqlRS\Get-TargetResource' -Tag 'Get' { $resultGetTargetResource.ReportServerReservedUrl | Should -Be $mockReportServerApplicationUrl $resultGetTargetResource.ReportsReservedUrl | Should -Be $mockReportsApplicationUrl $resultGetTargetResource.UseSsl | Should -BeFalse + $resultGetTargetResource.WindowsServiceIdentityActual | Should -Be $mockServiceAccountName } Should -Invoke -CommandName Invoke-RsCimMethod -ParameterFilter { @@ -416,6 +420,13 @@ Describe 'SqlRS\Set-TargetResource' -Tag 'Set' { $mockVirtualDirectoryReportManagerName = 'Reports_SQL2016' $mockVirtualDirectoryReportServerName = 'ReportServer_SQL2016' + $mockServiceNamePowerBiReportServer = 'PowerBIReportServer' + + $mockServiceAccount = 'CONTOSO\ServiceAccount' + $mockPassword = [System.Security.SecureString]::new() + $mockPassword.AppendChar(' ') + $mockServiceAccountCredential = [System.Management.Automation.PSCredential]::new($mockServiceAccount, $mockPassword) + $mockInvokeCimMethod = { throw 'Should not call Invoke-CimMethod directly, should call the wrapper Invoke-RsCimMethod.' } @@ -483,6 +494,31 @@ Describe 'SqlRS\Set-TargetResource' -Tag 'Set' { Add-Member -MemberType NoteProperty -Name 'SecureConnectionLevel' -Value $mockDynamicSecureConnectionLevel -PassThru -Force } + $mockGetCimInstance_ConfigurationSetting_PowerBIReportServer = { + return @( + ( + New-Object -TypeName Microsoft.Management.Infrastructure.CimInstance -ArgumentList @( + 'MSReportServer_ConfigurationSetting' + 'root/Microsoft/SQLServer/ReportServer/RS_PBIRS/v15/Admin' + ) | Add-Member -MemberType NoteProperty -Name 'DatabaseServerName' -Value "$mockReportingServicesDatabaseServerName\$mockReportingServicesDatabaseNamedInstanceName" -PassThru | + Add-Member -MemberType NoteProperty -Name 'IsInitialized' -Value $mockDynamicIsInitialized -PassThru | + Add-Member -MemberType NoteProperty -Name 'InstanceName' -Value $mockNamedInstanceName -PassThru | + Add-Member -MemberType NoteProperty -Name 'VirtualDirectoryReportServer' -Value $mockVirtualDirectoryReportServerName -PassThru | + Add-Member -MemberType NoteProperty -Name 'VirtualDirectoryReportManager' -Value $mockVirtualDirectoryReportManagerName -PassThru | + Add-Member -MemberType NoteProperty -Name 'SecureConnectionLevel' -Value $mockDynamicSecureConnectionLevel -PassThru | + Add-Member -MemberType NoteProperty -Name 'ServiceName' -Value $mockServiceNamePowerBiReportServer -PassThru | + Add-Member -MemberType NoteProperty -Name 'WindowsServiceIdentityActual' -Value 'NT AUTHORITY\SYSTEM' -PassThru -Force + ), + ( + # Array is a regression test for issue #819. + New-Object -TypeName Object | + Add-Member -MemberType NoteProperty -Name 'DatabaseServerName' -Value "$mockReportingServicesDatabaseServerName\$mockReportingServicesDatabaseNamedInstanceName" -PassThru | + Add-Member -MemberType NoteProperty -Name 'IsInitialized' -Value $true -PassThru | + Add-Member -MemberType NoteProperty -Name 'InstanceName' -Value 'DummyInstance' -PassThru -Force + ) + ) + } + $mockGetCimInstance_ConfigurationSetting_ParameterFilter = { $ClassName -eq 'MSReportServer_ConfigurationSetting' } @@ -497,6 +533,16 @@ Describe 'SqlRS\Set-TargetResource' -Tag 'Set' { $ClassName -eq 'Win32_OperatingSystem' } + $mockGetCimInstance_Service_ParameterFilter = { + $ClassName -eq 'Win32_Service' + } + + $mockGetCimInstance_ServiceAccountUserName = { + return @{ + Name = $mockServiceAccountName + } + } + Mock -CommandName Invoke-RsCimMethod -MockWith $mockInvokeRsCimMethod_ListReservedUrls -ParameterFilter { $MethodName -eq 'ListReservedUrls' } @@ -584,6 +630,10 @@ Describe 'SqlRS\Set-TargetResource' -Tag 'Set' { Mock -CommandName Get-CimInstance ` -MockWith $mockGetCimInstance_Language ` -ParameterFilter $mockGetCimInstance_OperatingSystem_ParameterFilter + + Mock -CommandName Get-CimInstance ` + -MockWith $mockGetCimInstance_ServiceAccountUserName ` + -ParameterFilter $mockGetCimInstance_Service_ParameterFilter } It 'Should configure Reporting Service without throwing an error' { @@ -640,7 +690,14 @@ Describe 'SqlRS\Set-TargetResource' -Tag 'Set' { $MethodName -eq 'ReserveUrl' -and $Arguments.Application -eq $mockReportsApplicationName } -Exactly -Times 1 -Scope It - Should -Invoke -CommandName Get-CimInstance -Exactly -Times 1 -Scope It + Should -Invoke -CommandName Get-CimInstance -ParameterFilter { + $ClassName -eq 'Win32_Service' + } -Exactly -Times 1 -Scope It + + Should -Invoke -CommandName Get-CimInstance -ParameterFilter { + $ClassName -eq 'Win32_OperatingSystem' + } -Exactly -Times 1 -Scope It + Should -Invoke -CommandName Invoke-SqlCmd -Exactly -Times 2 -Scope It Should -Invoke -CommandName Restart-ReportingServicesService -Exactly -Times 2 -Scope It } @@ -977,6 +1034,188 @@ Describe 'SqlRS\Set-TargetResource' -Tag 'Set' { } } + Context 'When Power BI Report Server is not in the desired state' { + Context "When configuring an instance that is not initialized" { + BeforeAll { + $mockDynamicIsInitialized = $false + + Mock -CommandName Test-TargetResource -MockWith { + return $true + } + + $defaultParameters = @{ + InstanceName = 'PBIRS' + DatabaseServerName = $mockReportingServicesDatabaseServerName + DatabaseInstanceName = $mockReportingServicesDatabaseDefaultInstanceName + ServiceAccount = $mockServiceAccountCredential + } + + Mock -CommandName Get-ReportingServicesData -MockWith { + return @{ + Configuration = (& $mockGetCimInstance_ConfigurationSetting_PowerBIReportServer)[0] + ReportsApplicationName = 'ReportServerWebApp' + SqlVersion = 15 + } + } + + Mock -CommandName Get-CimInstance ` + -MockWith $mockGetCimInstance_Language ` + -ParameterFilter $mockGetCimInstance_OperatingSystem_ParameterFilter + } + + It 'Should configure Reporting Service without throwing an error' { + { Set-TargetResource @defaultParameters } | Should -Not -Throw + + Should -Invoke -CommandName Invoke-RsCimMethod -ParameterFilter { + $MethodName -eq 'SetWindowsServiceIdentity' + } -Exactly -Times 1 -Scope It + + Should -Invoke -CommandName Invoke-RsCimMethod -ParameterFilter { + $MethodName -eq 'RemoveURL' + } -Exactly -Times 0 -Scope It + + Should -Invoke -CommandName Invoke-RsCimMethod -ParameterFilter { + $MethodName -eq 'InitializeReportServer' + } -Exactly -Times 1 -Scope It + + Should -Invoke -CommandName Invoke-RsCimMethod -ParameterFilter { + $MethodName -eq 'SetDatabaseConnection' + } -Exactly -Times 1 -Scope It + + Should -Invoke -CommandName Invoke-RsCimMethod -ParameterFilter { + $MethodName -eq 'GenerateDatabaseRightsScript' + } -Exactly -Times 1 -Scope It + + Should -Invoke -CommandName Invoke-RsCimMethod -ParameterFilter { + $MethodName -eq 'GenerateDatabaseCreationScript' + } -Exactly -Times 1 -Scope It + + Should -Invoke -CommandName Invoke-RsCimMethod -ParameterFilter { + $MethodName -eq 'SetVirtualDirectory' -and $Arguments.Application -eq $mockReportServerApplicationName + } -Exactly -Times 1 -Scope It + + Should -Invoke -CommandName Invoke-RsCimMethod -ParameterFilter { + $MethodName -eq 'SetVirtualDirectory' -and $Arguments.Application -eq $mockReportsApplicationName + } -Exactly -Times 1 -Scope It + + Should -Invoke -CommandName Invoke-RsCimMethod -ParameterFilter { + $MethodName -eq 'ReserveUrl' -and $Arguments.Application -eq $mockReportServerApplicationName + } -Exactly -Times 1 -Scope It + + Should -Invoke -CommandName Invoke-RsCimMethod -ParameterFilter { + $MethodName -eq 'ReserveUrl' -and $Arguments.Application -eq $mockReportsApplicationName + } -Exactly -Times 1 -Scope It + + Should -Invoke -CommandName Invoke-RsCimMethod -ParameterFilter { + $MethodName -eq 'ReserveUrl' -and $Arguments.Application -eq $mockReportsApplicationName + } -Exactly -Times 1 -Scope It + + Should -Invoke -CommandName Get-CimInstance -Exactly -Times 1 -Scope It + Should -Invoke -CommandName Invoke-Sqlcmd -Exactly -Times 2 -Scope It + Should -Invoke -CommandName Restart-ReportingServicesService -Exactly -Times 2 -Scope It + } + } + + Context "When configuring an instance that is already initialized" { + BeforeAll { + $mockDynamicIsInitialized = $true + + Mock -CommandName Get-ReportingServicesData -MockWith { + return @{ + Configuration = (& $mockGetCimInstance_ConfigurationSetting_PowerBIReportServer)[0] + ReportsApplicationName = 'ReportServerWebApp' + SqlVersion = 15 + } + } + + Mock -CommandName Get-TargetResource -MockWith { + return @{ + ReportServerReservedUrl = $mockReportServerApplicationUrl + ReportsReservedUrl = $mockReportsApplicationUrl + } + } + + Mock -CommandName Test-TargetResource -MockWith { + return $true + } + + $testParameters = @{ + InstanceName = 'PBIRS' + DatabaseServerName = $mockReportingServicesDatabaseServerName + DatabaseInstanceName = $mockReportingServicesDatabaseNamedInstanceName + ReportServerVirtualDirectory = 'ReportServer_NewName' + ReportsVirtualDirectory = 'Reports_NewName' + ReportServerReservedUrl = 'https://+:4443' + ReportsReservedUrl = 'https://+:4443' + UseSsl = $true + ServiceAccount = $mockServiceAccountCredential + } + } + + BeforeEach { + Mock -CommandName Get-CimInstance ` + -MockWith $mockGetCimInstance_Language ` + -ParameterFilter $mockGetCimInstance_OperatingSystem_ParameterFilter + } + + It 'Should configure Reporting Service without throwing an error' { + { Set-TargetResource @testParameters } | Should -Not -Throw + + Should -Invoke -CommandName Invoke-RsCimMethod -ParameterFilter { + $MethodName -eq 'SetWindowsServiceIdentity' + } -Exactly -Times 1 -Scope It + + Should -Invoke -CommandName Invoke-RsCimMethod -ParameterFilter { + $MethodName -eq 'SetSecureConnectionLevel' + } -Exactly -Times 1 -Scope It + + Should -Invoke -CommandName Invoke-RsCimMethod -ParameterFilter { + $MethodName -eq 'RemoveURL' -and $Arguments.Application -eq $mockReportServerApplicationName + } -Exactly -Times 2 -Scope It + + Should -Invoke -CommandName Invoke-RsCimMethod -ParameterFilter { + $MethodName -eq 'RemoveURL' -and $Arguments.Application -eq $mockReportsApplicationName + } -Exactly -Times 2 -Scope It + + Should -Invoke -CommandName Invoke-RsCimMethod -ParameterFilter { + $MethodName -eq 'InitializeReportServer' + } -Exactly -Times 0 -Scope It + + Should -Invoke -CommandName Invoke-RsCimMethod -ParameterFilter { + $MethodName -eq 'SetDatabaseConnection' + } -Exactly -Times 0 -Scope It + + Should -Invoke -CommandName Invoke-RsCimMethod -ParameterFilter { + $MethodName -eq 'GenerateDatabaseRightsScript' + } -Exactly -Times 0 -Scope It + + Should -Invoke -CommandName Invoke-RsCimMethod -ParameterFilter { + $MethodName -eq 'GenerateDatabaseCreationScript' + } -Exactly -Times 0 -Scope It + + Should -Invoke -CommandName Invoke-RsCimMethod -ParameterFilter { + $MethodName -eq 'SetVirtualDirectory' -and $Arguments.Application -eq $mockReportServerApplicationName + } -Exactly -Times 1 -Scope It + + Should -Invoke -CommandName Invoke-RsCimMethod -ParameterFilter { + $MethodName -eq 'SetVirtualDirectory' -and $Arguments.Application -eq $mockReportsApplicationName + } -Exactly -Times 1 -Scope It + + Should -Invoke -CommandName Invoke-RsCimMethod -ParameterFilter { + $MethodName -eq 'ReserveUrl' -and $Arguments.Application -eq $mockReportServerApplicationName + } -Exactly -Times 2 -Scope It + + Should -Invoke -CommandName Invoke-RsCimMethod -ParameterFilter { + $MethodName -eq 'ReserveUrl' -and $Arguments.Application -eq $mockReportsApplicationName + } -Exactly -Times 2 -Scope It + + Should -Invoke -CommandName Get-CimInstance -Exactly -Times 1 -Scope It + Should -Invoke -CommandName Invoke-Sqlcmd -Exactly -Times 0 -Scope It + Should -Invoke -CommandName Restart-ReportingServicesService -Exactly -Times 1 -Scope It + } + } + } + Context "When configuring a named instance of SQL Server Reporting Services 2019 that have been initialized by restarting the service" { BeforeAll { $script:alreadyCalledGetReportingServicesData = $false @@ -1303,6 +1542,38 @@ Describe 'SqlRS\Test-TargetResource' -Tag 'Test' { } } } + + Context 'When the service account is not to the desired state' { + BeforeAll { + Mock -CommandName Get-TargetResource -MockWith { + return @{ + IsInitialized = $true + WindowsServiceIdentityActual = 'NT AUTHORITY\SYSTEM' + } + } + } + + It 'Should return state as not in desired state' { + InModuleScope -ScriptBlock { + Set-StrictMode -Version 1.0 + + $mockServiceAccount = 'CONTOSO\ServiceAccount' + $mockPassword = [System.Security.SecureString]::new() + $mockPassword.AppendChar(' ') + $mockServiceAccountCredential = [System.Management.Automation.PSCredential]::new($mockServiceAccount,$mockPassword) + + $testParameters = @{ + InstanceName = 'INSTANCE' + DatabaseServerName = 'DBSERVER' + DatabaseInstanceName = 'DBINSTANCE' + ServiceAccount = $mockServiceAccountCredential + } + + $resultTestTargetResource = Test-TargetResource @testParameters + $resultTestTargetResource | Should -BeFalse + } + } + } } Context 'When the system is in the desired state' { @@ -1540,7 +1811,8 @@ Describe 'SqlRS\Get-ReportingServicesData' -Tag 'Helper' { Add-Member -MemberType NoteProperty -Name 'InstanceName' -Value 'INSTANCE' -PassThru | Add-Member -MemberType NoteProperty -Name 'VirtualDirectoryReportServer' -Value 'ReportServer' -PassThru | Add-Member -MemberType NoteProperty -Name 'VirtualDirectoryReportManager' -Value 'Reports' -PassThru | - Add-Member -MemberType NoteProperty -Name 'SecureConnectionLevel' -Value $false -PassThru -Force + Add-Member -MemberType NoteProperty -Name 'SecureConnectionLevel' -Value $false -PassThru | + Add-Member -MemberType NoteProperty -Name WindowsServiceIdentityActual -Value 'Contoso\ssrsServiceAccount' -PassThru -Force ), ( # Array is a regression test for issue #819. @@ -1579,6 +1851,7 @@ Describe 'SqlRS\Get-ReportingServicesData' -Tag 'Helper' { $getReportingServicesDataResult.Configuration.VirtualDirectoryReportServer | Should -Be 'ReportServer' $getReportingServicesDataResult.Configuration.VirtualDirectoryReportManager | Should -Be 'Reports' $getReportingServicesDataResult.Configuration.SecureConnectionLevel | Should -Be 0 + $getReportingServicesDataResult.Configuration.WindowsServiceIdentityActual | Should -Be 'Contoso\ssrsServiceAccount' $getReportingServicesDataResult.ReportsApplicationName | Should -Be 'ReportManager' $getReportingServicesDataResult.SqlVersion | Should -Be '12' } @@ -1619,6 +1892,7 @@ Describe 'SqlRS\Get-ReportingServicesData' -Tag 'Helper' { $getReportingServicesDataResult.Configuration.VirtualDirectoryReportServer | Should -Be 'ReportServer' $getReportingServicesDataResult.Configuration.VirtualDirectoryReportManager | Should -Be 'Reports' $getReportingServicesDataResult.Configuration.SecureConnectionLevel | Should -Be 0 + $getReportingServicesDataResult.Configuration.WindowsServiceIdentityActual | Should -Be 'Contoso\ssrsServiceAccount' $getReportingServicesDataResult.ReportsApplicationName | Should -Be 'ReportServerWebApp' $getReportingServicesDataResult.SqlVersion | Should -Be '13' } @@ -1659,6 +1933,7 @@ Describe 'SqlRS\Get-ReportingServicesData' -Tag 'Helper' { $getReportingServicesDataResult.Configuration.VirtualDirectoryReportServer | Should -Be 'ReportServer' $getReportingServicesDataResult.Configuration.VirtualDirectoryReportManager | Should -Be 'Reports' $getReportingServicesDataResult.Configuration.SecureConnectionLevel | Should -Be 0 + $getReportingServicesDataResult.Configuration.WindowsServiceIdentityActual | Should -Be 'Contoso\ssrsServiceAccount' $getReportingServicesDataResult.ReportsApplicationName | Should -Be 'ReportServerWebApp' $getReportingServicesDataResult.SqlVersion | Should -Be '14' } @@ -1699,6 +1974,7 @@ Describe 'SqlRS\Get-ReportingServicesData' -Tag 'Helper' { $getReportingServicesDataResult.Configuration.VirtualDirectoryReportServer | Should -Be 'ReportServer' $getReportingServicesDataResult.Configuration.VirtualDirectoryReportManager | Should -Be 'Reports' $getReportingServicesDataResult.Configuration.SecureConnectionLevel | Should -Be 0 + $getReportingServicesDataResult.Configuration.WindowsServiceIdentityActual | Should -Be 'Contoso\ssrsServiceAccount' $getReportingServicesDataResult.ReportsApplicationName | Should -Be 'ReportServerWebApp' $getReportingServicesDataResult.SqlVersion | Should -Be '15' }