From aee02aba3fdb24530ae1009df763cfcf24ed035f Mon Sep 17 00:00:00 2001 From: Marko Bozikovic Date: Tue, 23 May 2017 16:51:53 +0100 Subject: [PATCH 01/12] [#567] Updated CHANGELOG.md --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8e77ac965..d43983130 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -62,7 +62,7 @@ - Refactored some of the code, cleaned up the rest and fixed PSSA rules warnings (issue #261). - If parameter TcpDynamicPort is set to '0' at the same time as TcpPort is set the resource will now throw an error (issue #535). - Added examples (issue #536). - - When TcpDynamicPorts is set to '0' the Test-TargetResource function will no longer fail each time (issue #564). + - When TcpDynamicPorts is set to '0' the Test-TargetResource function will no longer fail each time (issue #564). - Changes to xSQLServerRSConfig - Replaced sqlcmd.exe usages with Invoke-Sqlcmd calls (issue #567). - Changes to xSQLServerDatabasePermission From d26b1ef84142a6dfabfb66ed0cf70642a29cf6a1 Mon Sep 17 00:00:00 2001 From: Marko Bozikovic Date: Tue, 23 May 2017 17:36:15 +0100 Subject: [PATCH 02/12] [#568] xSQLServerRSConfig: $SQLAdminCredential is now optional --- CHANGELOG.md | 3 +- .../MSFT_xSQLServerRSConfig.psm1 | 34 +++++++++++++++---- .../MSFT_xSQLServerRSConfig.schema.mof | 2 +- 3 files changed, 30 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d43983130..49e21f588 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -62,9 +62,10 @@ - Refactored some of the code, cleaned up the rest and fixed PSSA rules warnings (issue #261). - If parameter TcpDynamicPort is set to '0' at the same time as TcpPort is set the resource will now throw an error (issue #535). - Added examples (issue #536). - - When TcpDynamicPorts is set to '0' the Test-TargetResource function will no longer fail each time (issue #564). + - When TcpDynamicPorts is set to '0' the Test-TargetResource function will no longer fail each time (issue #564). - Changes to xSQLServerRSConfig - Replaced sqlcmd.exe usages with Invoke-Sqlcmd calls (issue #567). + - $SQLAdminCredential is now optional. To use the credential, CredSSP authentication must be properly configured on the target node. - Changes to xSQLServerDatabasePermission - Fixed code style, updated README.md and removed *-SqlDatabasePermission functions from xSQLServerHelper.psm1. - Added the option 'GrantWithGrant' with gives the user grant rights, together with the ability to grant others the same right. diff --git a/DSCResources/MSFT_xSQLServerRSConfig/MSFT_xSQLServerRSConfig.psm1 b/DSCResources/MSFT_xSQLServerRSConfig/MSFT_xSQLServerRSConfig.psm1 index f619d2b3f..a9c117010 100644 --- a/DSCResources/MSFT_xSQLServerRSConfig/MSFT_xSQLServerRSConfig.psm1 +++ b/DSCResources/MSFT_xSQLServerRSConfig/MSFT_xSQLServerRSConfig.psm1 @@ -22,7 +22,7 @@ function Get-TargetResource [System.String] $RSSQLInstanceName, - [parameter(Mandatory = $true)] + [parameter()] [System.Management.Automation.PSCredential] $SQLAdminCredential ) @@ -31,12 +31,22 @@ function Get-TargetResource { $InstanceKey = (Get-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Microsoft SQL Server\Instance Names\RS" -Name $InstanceName).$InstanceName $SQLVersion = ((Get-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Microsoft SQL Server\$InstanceKey\Setup" -Name "Version").Version).Split(".")[0] - $RSConfig = Invoke-Command -ComputerName . -Credential $SQLAdminCredential -ScriptBlock { + + $invokeParameters = @{ + ComputerName = "localhost" + ArgumentList = @($SQLVersion,$InstanceName) + } + if($SQLAdminCredential -ne $null) { + $invokeParameters.Add("Credential", $SQLAdminCredential) + $invokeParameters.Add("Authentication", "CredSSP") + } + + $RSConfig = Invoke-Command @invokeParameters -ScriptBlock { $SQLVersion = $args[0] $InstanceName = $args[1] $RSConfig = Get-WmiObject -Class MSReportServer_ConfigurationSetting -Namespace "root\Microsoft\SQLServer\ReportServer\RS_$InstanceName\v$SQLVersion\Admin" $RSConfig - } -ArgumentList @($SQLVersion,$InstanceName) + } if($RSConfig.DatabaseServerName.Contains("\")) { $RSSQLServer = $RSConfig.DatabaseServerName.Split("\")[0] @@ -82,14 +92,24 @@ function Set-TargetResource [System.String] $RSSQLInstanceName, - [parameter(Mandatory = $true)] + [parameter()] [System.Management.Automation.PSCredential] $SQLAdminCredential ) if(Get-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Microsoft SQL Server\Instance Names\RS" -Name $InstanceName -ErrorAction SilentlyContinue) { - Invoke-Command -ComputerName . -Credential $SQLAdminCredential -ScriptBlock { + + $invokeParameters = @{ + ComputerName = "localhost" + ArgumentList = @($InstanceName,$RSSQLServer,$RSSQLInstanceName) + } + if($SQLAdminCredential -ne $null) { + $invokeParameters.Add("Credential", $SQLAdminCredential) + $invokeParameters.Add("Authentication", "CredSSP") + } + + Invoke-Command @invokeParameters -ScriptBlock { # this is a separate PS session, need to load Common Code again Import-Module $using:currentPath\..\..\xSQLServerHelper.psm1 -Verbose -ErrorAction Stop # smart import of the SQL module @@ -145,7 +165,7 @@ function Set-TargetResource $RSConfig.SetDatabaseConnection($RSConnection,$RSDatabase,2,"","") $RSConfig.InitializeReportServer($RSConfig.InstallationID) - } -ArgumentList @($InstanceName,$RSSQLServer,$RSSQLInstanceName) + } } if(!(Test-TargetResource @PSBoundParameters)) @@ -173,7 +193,7 @@ function Test-TargetResource [System.String] $RSSQLInstanceName, - [parameter(Mandatory = $true)] + [parameter()] [System.Management.Automation.PSCredential] $SQLAdminCredential ) diff --git a/DSCResources/MSFT_xSQLServerRSConfig/MSFT_xSQLServerRSConfig.schema.mof b/DSCResources/MSFT_xSQLServerRSConfig/MSFT_xSQLServerRSConfig.schema.mof index 5891a288e..4383dffe3 100644 --- a/DSCResources/MSFT_xSQLServerRSConfig/MSFT_xSQLServerRSConfig.schema.mof +++ b/DSCResources/MSFT_xSQLServerRSConfig/MSFT_xSQLServerRSConfig.schema.mof @@ -4,6 +4,6 @@ class MSFT_xSQLServerRSConfig : 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 Service database.")] String RSSQLServer; [Required, Description("Name of the SQL Server instance to host the Reporting Service database.")] String RSSQLInstanceName; - [Required, EmbeddedInstance("MSFT_Credential"), Description("Credential to be used to perform the configuration.")] String SQLAdminCredential; + [EmbeddedInstance("MSFT_Credential"), Description("Credential to be used to perform the configuration. Optional.")] String SQLAdminCredential; [Read, Description("Is the Reporting Services instance initialized.")] Boolean IsInitialized; }; From cc051b0de6560f5398f91ae553040cd5042ad452 Mon Sep 17 00:00:00 2001 From: Marko Bozikovic Date: Wed, 24 May 2017 14:40:41 +0100 Subject: [PATCH 03/12] [#568] MOF schema fix. --- .../MSFT_xSQLServerRSConfig/MSFT_xSQLServerRSConfig.schema.mof | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DSCResources/MSFT_xSQLServerRSConfig/MSFT_xSQLServerRSConfig.schema.mof b/DSCResources/MSFT_xSQLServerRSConfig/MSFT_xSQLServerRSConfig.schema.mof index 4383dffe3..7796e9246 100644 --- a/DSCResources/MSFT_xSQLServerRSConfig/MSFT_xSQLServerRSConfig.schema.mof +++ b/DSCResources/MSFT_xSQLServerRSConfig/MSFT_xSQLServerRSConfig.schema.mof @@ -4,6 +4,6 @@ class MSFT_xSQLServerRSConfig : 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 Service database.")] String RSSQLServer; [Required, Description("Name of the SQL Server instance to host the Reporting Service database.")] String RSSQLInstanceName; - [EmbeddedInstance("MSFT_Credential"), Description("Credential to be used to perform the configuration. Optional.")] String SQLAdminCredential; + [Write, EmbeddedInstance("MSFT_Credential"), Description("Credential to be used to perform the configuration. Optional.")] String SQLAdminCredential; [Read, Description("Is the Reporting Services instance initialized.")] Boolean IsInitialized; }; From a6acec1755276681b8c70dd33052b9c079c44a49 Mon Sep 17 00:00:00 2001 From: Marko Bozikovic Date: Wed, 24 May 2017 16:59:10 +0100 Subject: [PATCH 04/12] [#568] We don't need ComputerName when not using $SQLAdminCredential --- .../MSFT_xSQLServerRSConfig/MSFT_xSQLServerRSConfig.psm1 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/DSCResources/MSFT_xSQLServerRSConfig/MSFT_xSQLServerRSConfig.psm1 b/DSCResources/MSFT_xSQLServerRSConfig/MSFT_xSQLServerRSConfig.psm1 index a9c117010..e36c71361 100644 --- a/DSCResources/MSFT_xSQLServerRSConfig/MSFT_xSQLServerRSConfig.psm1 +++ b/DSCResources/MSFT_xSQLServerRSConfig/MSFT_xSQLServerRSConfig.psm1 @@ -33,10 +33,10 @@ function Get-TargetResource $SQLVersion = ((Get-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Microsoft SQL Server\$InstanceKey\Setup" -Name "Version").Version).Split(".")[0] $invokeParameters = @{ - ComputerName = "localhost" ArgumentList = @($SQLVersion,$InstanceName) } if($SQLAdminCredential -ne $null) { + $invokeParameters.Add("ComputerName", "localhost") $invokeParameters.Add("Credential", $SQLAdminCredential) $invokeParameters.Add("Authentication", "CredSSP") } @@ -101,10 +101,10 @@ function Set-TargetResource { $invokeParameters = @{ - ComputerName = "localhost" ArgumentList = @($InstanceName,$RSSQLServer,$RSSQLInstanceName) } if($SQLAdminCredential -ne $null) { + $invokeParameters.Add("ComputerName", "localhost") $invokeParameters.Add("Credential", $SQLAdminCredential) $invokeParameters.Add("Authentication", "CredSSP") } From 8472973b3a676a26e889fb092a8a7e11b9d77510 Mon Sep 17 00:00:00 2001 From: Marko Bozikovic Date: Wed, 24 May 2017 17:27:25 +0100 Subject: [PATCH 05/12] [#568] Passing in SQL helper module path as an argument to Invoke-Command --- .../MSFT_xSQLServerRSConfig.psm1 | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/DSCResources/MSFT_xSQLServerRSConfig/MSFT_xSQLServerRSConfig.psm1 b/DSCResources/MSFT_xSQLServerRSConfig/MSFT_xSQLServerRSConfig.psm1 index e36c71361..5fb6a1fe0 100644 --- a/DSCResources/MSFT_xSQLServerRSConfig/MSFT_xSQLServerRSConfig.psm1 +++ b/DSCResources/MSFT_xSQLServerRSConfig/MSFT_xSQLServerRSConfig.psm1 @@ -101,7 +101,7 @@ function Set-TargetResource { $invokeParameters = @{ - ArgumentList = @($InstanceName,$RSSQLServer,$RSSQLInstanceName) + ArgumentList = @("$currentPath\..\..\xSQLServerHelper.psm1", $InstanceName,$RSSQLServer,$RSSQLInstanceName) } if($SQLAdminCredential -ne $null) { $invokeParameters.Add("ComputerName", "localhost") @@ -111,13 +111,13 @@ function Set-TargetResource Invoke-Command @invokeParameters -ScriptBlock { # this is a separate PS session, need to load Common Code again - Import-Module $using:currentPath\..\..\xSQLServerHelper.psm1 -Verbose -ErrorAction Stop + Import-Module $args[0] -Verbose -ErrorAction Stop # smart import of the SQL module Import-SQLPSModule - $InstanceName = $args[0] - $RSSQLServer = $args[1] - $RSSQLInstanceName = $args[2] + $InstanceName = $args[1] + $RSSQLServer = $args[2] + $RSSQLInstanceName = $args[3] $InstanceKey = (Get-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Microsoft SQL Server\Instance Names\RS" -Name $InstanceName).$InstanceName $SQLVersion = ((Get-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Microsoft SQL Server\$InstanceKey\Setup" -Name "Version").Version).Split(".")[0] if($InstanceName -eq "MSSQLSERVER") From b3b3076c5ab35099e1c58cdaa94b6d0c94962c23 Mon Sep 17 00:00:00 2001 From: Marko Bozikovic Date: Thu, 25 May 2017 16:57:47 +0100 Subject: [PATCH 06/12] [#568] Removed $SQLAdminCredential parameter. xSQLServer module aims to drop WMF 4.0 support. WMF 5.0 and later supports a common parameter (PsDscRunAsCredential) for running DSC resources under different credentials, which eliminates the need for the $SQLAdminCredential parameter. --- CHANGELOG.md | 3 +- .../MSFT_xSQLServerRSConfig.psm1 | 140 ++++++------------ .../MSFT_xSQLServerRSConfig.schema.mof | 1 - README.md | 1 - 4 files changed, 50 insertions(+), 95 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 49e21f588..fb0e7a8d6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,8 @@ # Change log for xSQLServer ## Unreleased +- Changes to xSQLServerRSConfig + - BREAKING CHANGE: removed $SQLAdminCredential parameter. Use common parameter PsDscRunAsCredential (WMF 5.0+) to run the resource under different credentials. PsDscRunAsCredential Windows account must be a sysadmin on SQL Server (issue #568). ## 7.1.0.0 @@ -65,7 +67,6 @@ - When TcpDynamicPorts is set to '0' the Test-TargetResource function will no longer fail each time (issue #564). - Changes to xSQLServerRSConfig - Replaced sqlcmd.exe usages with Invoke-Sqlcmd calls (issue #567). - - $SQLAdminCredential is now optional. To use the credential, CredSSP authentication must be properly configured on the target node. - Changes to xSQLServerDatabasePermission - Fixed code style, updated README.md and removed *-SqlDatabasePermission functions from xSQLServerHelper.psm1. - Added the option 'GrantWithGrant' with gives the user grant rights, together with the ability to grant others the same right. diff --git a/DSCResources/MSFT_xSQLServerRSConfig/MSFT_xSQLServerRSConfig.psm1 b/DSCResources/MSFT_xSQLServerRSConfig/MSFT_xSQLServerRSConfig.psm1 index 5fb6a1fe0..905c55ecc 100644 --- a/DSCResources/MSFT_xSQLServerRSConfig/MSFT_xSQLServerRSConfig.psm1 +++ b/DSCResources/MSFT_xSQLServerRSConfig/MSFT_xSQLServerRSConfig.psm1 @@ -20,11 +20,7 @@ function Get-TargetResource [parameter(Mandatory = $true)] [System.String] - $RSSQLInstanceName, - - [parameter()] - [System.Management.Automation.PSCredential] - $SQLAdminCredential + $RSSQLInstanceName ) if(Get-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Microsoft SQL Server\Instance Names\RS" -Name $InstanceName -ErrorAction SilentlyContinue) @@ -32,21 +28,7 @@ function Get-TargetResource $InstanceKey = (Get-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Microsoft SQL Server\Instance Names\RS" -Name $InstanceName).$InstanceName $SQLVersion = ((Get-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Microsoft SQL Server\$InstanceKey\Setup" -Name "Version").Version).Split(".")[0] - $invokeParameters = @{ - ArgumentList = @($SQLVersion,$InstanceName) - } - if($SQLAdminCredential -ne $null) { - $invokeParameters.Add("ComputerName", "localhost") - $invokeParameters.Add("Credential", $SQLAdminCredential) - $invokeParameters.Add("Authentication", "CredSSP") - } - - $RSConfig = Invoke-Command @invokeParameters -ScriptBlock { - $SQLVersion = $args[0] - $InstanceName = $args[1] - $RSConfig = Get-WmiObject -Class MSReportServer_ConfigurationSetting -Namespace "root\Microsoft\SQLServer\ReportServer\RS_$InstanceName\v$SQLVersion\Admin" - $RSConfig - } + $RSConfig = Get-WmiObject -Class MSReportServer_ConfigurationSetting -Namespace "root\Microsoft\SQLServer\ReportServer\RS_$InstanceName\v$SQLVersion\Admin" if($RSConfig.DatabaseServerName.Contains("\")) { $RSSQLServer = $RSConfig.DatabaseServerName.Split("\")[0] @@ -90,82 +72,60 @@ function Set-TargetResource [parameter(Mandatory = $true)] [System.String] - $RSSQLInstanceName, - - [parameter()] - [System.Management.Automation.PSCredential] - $SQLAdminCredential + $RSSQLInstanceName ) if(Get-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Microsoft SQL Server\Instance Names\RS" -Name $InstanceName -ErrorAction SilentlyContinue) { + # smart import of the SQL module + Import-SQLPSModule - $invokeParameters = @{ - ArgumentList = @("$currentPath\..\..\xSQLServerHelper.psm1", $InstanceName,$RSSQLServer,$RSSQLInstanceName) + $InstanceKey = (Get-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Microsoft SQL Server\Instance Names\RS" -Name $InstanceName).$InstanceName + $SQLVersion = ((Get-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Microsoft SQL Server\$InstanceKey\Setup" -Name "Version").Version).Split(".")[0] + if($InstanceName -eq "MSSQLSERVER") + { + $RSServiceName = "ReportServer" + $RSVirtualDirectory = "ReportServer" + $RMVirtualDirectory = "Reports" + $RSDatabase = "ReportServer" + } + else + { + $RSServiceName = "ReportServer`$$InstanceName" + $RSVirtualDirectory = "ReportServer_$InstanceName" + $RMVirtualDirectory = "Reports_$InstanceName" + $RSDatabase = "ReportServer`$$InstanceName" + } + if($RSSQLInstanceName -eq "MSSQLSERVER") + { + $RSConnection = "$RSSQLServer" } - if($SQLAdminCredential -ne $null) { - $invokeParameters.Add("ComputerName", "localhost") - $invokeParameters.Add("Credential", $SQLAdminCredential) - $invokeParameters.Add("Authentication", "CredSSP") + else + { + $RSConnection = "$RSSQLServer\$RSSQLInstanceName" } + $Language = (Get-WMIObject -Class Win32_OperatingSystem -Namespace root/cimv2 -ErrorAction SilentlyContinue).OSLanguage + $RSConfig = Get-WmiObject -Class MSReportServer_ConfigurationSetting -Namespace "root\Microsoft\SQLServer\ReportServer\RS_$InstanceName\v$SQLVersion\Admin" + if($RSConfig.VirtualDirectoryReportServer -ne $RSVirtualDirectory) + { + $null = $RSConfig.SetVirtualDirectory("ReportServerWebService",$RSVirtualDirectory,$Language) + $null = $RSConfig.ReserveURL("ReportServerWebService","http://+:80",$Language) + } + if($RSConfig.VirtualDirectoryReportManager -ne $RMVirtualDirectory) + { + $null = $RSConfig.SetVirtualDirectory("ReportManager",$RMVirtualDirectory,$Language) + $null = $RSConfig.ReserveURL("ReportManager","http://+:80",$Language) + } + $RSCreateScript = $RSConfig.GenerateDatabaseCreationScript($RSDatabase,$Language,$false) - Invoke-Command @invokeParameters -ScriptBlock { - # this is a separate PS session, need to load Common Code again - Import-Module $args[0] -Verbose -ErrorAction Stop - # smart import of the SQL module - Import-SQLPSModule - - $InstanceName = $args[1] - $RSSQLServer = $args[2] - $RSSQLInstanceName = $args[3] - $InstanceKey = (Get-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Microsoft SQL Server\Instance Names\RS" -Name $InstanceName).$InstanceName - $SQLVersion = ((Get-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Microsoft SQL Server\$InstanceKey\Setup" -Name "Version").Version).Split(".")[0] - if($InstanceName -eq "MSSQLSERVER") - { - $RSServiceName = "ReportServer" - $RSVirtualDirectory = "ReportServer" - $RMVirtualDirectory = "Reports" - $RSDatabase = "ReportServer" - } - else - { - $RSServiceName = "ReportServer`$$InstanceName" - $RSVirtualDirectory = "ReportServer_$InstanceName" - $RMVirtualDirectory = "Reports_$InstanceName" - $RSDatabase = "ReportServer`$$InstanceName" - } - if($RSSQLInstanceName -eq "MSSQLSERVER") - { - $RSConnection = "$RSSQLServer" - } - else - { - $RSConnection = "$RSSQLServer\$RSSQLInstanceName" - } - $Language = (Get-WMIObject -Class Win32_OperatingSystem -Namespace root/cimv2 -ErrorAction SilentlyContinue).OSLanguage - $RSConfig = Get-WmiObject -Class MSReportServer_ConfigurationSetting -Namespace "root\Microsoft\SQLServer\ReportServer\RS_$InstanceName\v$SQLVersion\Admin" - if($RSConfig.VirtualDirectoryReportServer -ne $RSVirtualDirectory) - { - $null = $RSConfig.SetVirtualDirectory("ReportServerWebService",$RSVirtualDirectory,$Language) - $null = $RSConfig.ReserveURL("ReportServerWebService","http://+:80",$Language) - } - if($RSConfig.VirtualDirectoryReportManager -ne $RMVirtualDirectory) - { - $null = $RSConfig.SetVirtualDirectory("ReportManager",$RMVirtualDirectory,$Language) - $null = $RSConfig.ReserveURL("ReportManager","http://+:80",$Language) - } - $RSCreateScript = $RSConfig.GenerateDatabaseCreationScript($RSDatabase,$Language,$false) - - # Determine RS service account - $RSSvcAccountUsername = (Get-WmiObject -Class Win32_Service | Where-Object {$_.Name -eq $RSServiceName}).StartName - $RSRightsScript = $RSConfig.GenerateDatabaseRightsScript($RSSvcAccountUsername,$RSDatabase,$false,$true) - - Invoke-Sqlcmd -ServerInstance $RSConnection -Query $RSCreateScript.Script - Invoke-Sqlcmd -ServerInstance $RSConnection -Query $RSRightsScript.Script - $RSConfig.SetDatabaseConnection($RSConnection,$RSDatabase,2,"","") - $RSConfig.InitializeReportServer($RSConfig.InstallationID) + # Determine RS service account + $RSSvcAccountUsername = (Get-WmiObject -Class Win32_Service | Where-Object {$_.Name -eq $RSServiceName}).StartName + $RSRightsScript = $RSConfig.GenerateDatabaseRightsScript($RSSvcAccountUsername,$RSDatabase,$false,$true) - } + Invoke-Sqlcmd -ServerInstance $RSConnection -Query $RSCreateScript.Script + Invoke-Sqlcmd -ServerInstance $RSConnection -Query $RSRightsScript.Script + $RSConfig.SetDatabaseConnection($RSConnection,$RSDatabase,2,"","") + $RSConfig.InitializeReportServer($RSConfig.InstallationID) } if(!(Test-TargetResource @PSBoundParameters)) @@ -191,11 +151,7 @@ function Test-TargetResource [parameter(Mandatory = $true)] [System.String] - $RSSQLInstanceName, - - [parameter()] - [System.Management.Automation.PSCredential] - $SQLAdminCredential + $RSSQLInstanceName ) $result = (Get-TargetResource @PSBoundParameters).IsInitialized diff --git a/DSCResources/MSFT_xSQLServerRSConfig/MSFT_xSQLServerRSConfig.schema.mof b/DSCResources/MSFT_xSQLServerRSConfig/MSFT_xSQLServerRSConfig.schema.mof index 7796e9246..06674454c 100644 --- a/DSCResources/MSFT_xSQLServerRSConfig/MSFT_xSQLServerRSConfig.schema.mof +++ b/DSCResources/MSFT_xSQLServerRSConfig/MSFT_xSQLServerRSConfig.schema.mof @@ -4,6 +4,5 @@ class MSFT_xSQLServerRSConfig : 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 Service database.")] String RSSQLServer; [Required, Description("Name of the SQL Server instance to host the Reporting Service database.")] String RSSQLInstanceName; - [Write, EmbeddedInstance("MSFT_Credential"), Description("Credential to be used to perform the configuration. Optional.")] String SQLAdminCredential; [Read, Description("Is the Reporting Services instance initialized.")] Boolean IsInitialized; }; diff --git a/README.md b/README.md index 48c180454..97d56fc94 100644 --- a/README.md +++ b/README.md @@ -879,7 +879,6 @@ No description. * **[String] InstanceName** _(Key)_: Name of the SQL Server Reporting Services instance to be configured. * **[String] RSSQLServer** _(Required)_: Name of the SQL Server to host the Reporting Service database. * **[String] RSSQLInstanceName** _(Required)_: Name of the SQL Server instance to host the Reporting Service database. -* **[PSCredential] SQLAdminCredential** _(Required)_: Credential to be used to perform the configuration. #### Read-Only Properties from Get-TargetResource From 78bcbdc129c3e6a87fff6ad735ff6225f6b14ea1 Mon Sep 17 00:00:00 2001 From: Marko Bozikovic Date: Fri, 2 Jun 2017 11:52:41 +0100 Subject: [PATCH 07/12] [#568] Test fix for CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index fb0e7a8d6..185ecc946 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ # Change log for xSQLServer ## Unreleased + - Changes to xSQLServerRSConfig - BREAKING CHANGE: removed $SQLAdminCredential parameter. Use common parameter PsDscRunAsCredential (WMF 5.0+) to run the resource under different credentials. PsDscRunAsCredential Windows account must be a sysadmin on SQL Server (issue #568). From 83eb76b7422d4940e05f61613c02559aa720de0e Mon Sep 17 00:00:00 2001 From: Marko Bozikovic Date: Wed, 24 May 2017 15:20:13 +0100 Subject: [PATCH 08/12] [#569] A fix for SQL 2016 virtual directory name change. --- CHANGELOG.md | 1 + .../MSFT_xSQLServerRSConfig.psm1 | 11 +++++++---- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 185ecc946..4b9110780 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ - Changes to xSQLServerRSConfig - BREAKING CHANGE: removed $SQLAdminCredential parameter. Use common parameter PsDscRunAsCredential (WMF 5.0+) to run the resource under different credentials. PsDscRunAsCredential Windows account must be a sysadmin on SQL Server (issue #568). + - Fixed virtual directory creation for SQL Server 2016. ## 7.1.0.0 diff --git a/DSCResources/MSFT_xSQLServerRSConfig/MSFT_xSQLServerRSConfig.psm1 b/DSCResources/MSFT_xSQLServerRSConfig/MSFT_xSQLServerRSConfig.psm1 index 905c55ecc..4e6b0ed47 100644 --- a/DSCResources/MSFT_xSQLServerRSConfig/MSFT_xSQLServerRSConfig.psm1 +++ b/DSCResources/MSFT_xSQLServerRSConfig/MSFT_xSQLServerRSConfig.psm1 @@ -113,8 +113,11 @@ function Set-TargetResource } if($RSConfig.VirtualDirectoryReportManager -ne $RMVirtualDirectory) { - $null = $RSConfig.SetVirtualDirectory("ReportManager",$RMVirtualDirectory,$Language) - $null = $RSConfig.ReserveURL("ReportManager","http://+:80",$Language) + # SSRS Web Portal application name changed in SQL Server 2016 + # https://docs.microsoft.com/en-us/sql/reporting-services/breaking-changes-in-sql-server-reporting-services-in-sql-server-2016 + $virtualDirectoryName = if ($SQLVersion -ge 13) { 'ReportServerWebApp' } else { 'ReportManager'} + $null = $RSConfig.SetVirtualDirectory($virtualDirectoryName,$RMVirtualDirectory,$Language) + $null = $RSConfig.ReserveURL($virtualDirectoryName,"http://+:80",$Language) } $RSCreateScript = $RSConfig.GenerateDatabaseCreationScript($RSDatabase,$Language,$false) @@ -124,8 +127,8 @@ function Set-TargetResource Invoke-Sqlcmd -ServerInstance $RSConnection -Query $RSCreateScript.Script Invoke-Sqlcmd -ServerInstance $RSConnection -Query $RSRightsScript.Script - $RSConfig.SetDatabaseConnection($RSConnection,$RSDatabase,2,"","") - $RSConfig.InitializeReportServer($RSConfig.InstallationID) + $null = $RSConfig.SetDatabaseConnection($RSConnection,$RSDatabase,2,"","") + $null = $RSConfig.InitializeReportServer($RSConfig.InstallationID) } if(!(Test-TargetResource @PSBoundParameters)) From ae5abde67a6fc91bf537c5863346543fc6d023b3 Mon Sep 17 00:00:00 2001 From: Johan Ljunggren Date: Fri, 26 May 2017 19:02:52 +0200 Subject: [PATCH 09/12] Changes to xSQLServerRSConfig Added unit tests (issue #295). --- CHANGELOG.md | 1 + Tests/Unit/MSFT_xSQLServerRSConfig.Tests.ps1 | 303 +++++++++++++++++++ 2 files changed, 304 insertions(+) create mode 100644 Tests/Unit/MSFT_xSQLServerRSConfig.Tests.ps1 diff --git a/CHANGELOG.md b/CHANGELOG.md index 4b9110780..9e09e54eb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ - Changes to xSQLServerRSConfig - BREAKING CHANGE: removed $SQLAdminCredential parameter. Use common parameter PsDscRunAsCredential (WMF 5.0+) to run the resource under different credentials. PsDscRunAsCredential Windows account must be a sysadmin on SQL Server (issue #568). - Fixed virtual directory creation for SQL Server 2016. + - Added unit tests (issue #295). ## 7.1.0.0 diff --git a/Tests/Unit/MSFT_xSQLServerRSConfig.Tests.ps1 b/Tests/Unit/MSFT_xSQLServerRSConfig.Tests.ps1 new file mode 100644 index 000000000..3913bf9dd --- /dev/null +++ b/Tests/Unit/MSFT_xSQLServerRSConfig.Tests.ps1 @@ -0,0 +1,303 @@ +$script:DSCModuleName = 'xSQLServer' +$script:DSCResourceName = 'MSFT_xSQLServerRSConfig' + +#region HEADER + +# Unit Test Template Version: 1.2.0 +$script:moduleRoot = Split-Path -Parent (Split-Path -Parent $PSScriptRoot) +if ( (-not (Test-Path -Path (Join-Path -Path $script:moduleRoot -ChildPath 'DSCResource.Tests'))) -or ` + (-not (Test-Path -Path (Join-Path -Path $script:moduleRoot -ChildPath 'DSCResource.Tests\TestHelper.psm1'))) ) +{ + & git @('clone','https://github.com/PowerShell/DscResource.Tests.git',(Join-Path -Path $script:moduleRoot -ChildPath '\DSCResource.Tests\')) +} + +Import-Module -Name (Join-Path -Path $script:moduleRoot -ChildPath 'DSCResource.Tests\TestHelper.psm1') -Force + +$TestEnvironment = Initialize-TestEnvironment ` + -DSCModuleName $script:DSCModuleName ` + -DSCResourceName $script:DSCResourceName ` + -TestType Unit + +#endregion HEADER + +function Invoke-TestSetup { + #Add-Type -Path (Join-Path -Path (Join-Path -Path (Join-Path -Path (Join-Path -Path $script:moduleRoot -ChildPath 'Tests') -ChildPath 'Unit') -ChildPath 'Stubs') -ChildPath 'SqlPowerShellSqlExecutionException.cs') + Import-Module -Name (Join-Path -Path (Join-Path -Path (Join-Path -Path (Join-Path -Path $script:moduleRoot -ChildPath 'Tests') -ChildPath 'Unit') -ChildPath 'Stubs') -ChildPath 'SQLPSStub.psm1') -Global -Force +} + +function Invoke-TestCleanup { + Restore-TestEnvironment -TestEnvironment $TestEnvironment +} + +# Begin Testing +try +{ + Invoke-TestSetup + + InModuleScope $script:DSCResourceName { + $mockNamedInstanceName = 'INSTANCE' + $mockDefaultInstanceName = 'MSSQLSERVER' + $mockReportingServicesDatabaseServerName = 'SERVER' + $mockReportingServicesDatabaseNamedInstanceName = $mockNamedInstanceName + $mockReportingServicesDatabaseDefaultInstanceName = $mockDefaultInstanceName + + $mockGetItemProperty = { + return @{ + InstanceName = $mockInstanceName + Version = $mockDynamic_SqlBuildVersion + } + } + + $mockGetWmiObject_ConfigurationSetting_NamedInstance = { + return New-Object 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 'VirtualDirectoryReportServer' -Value '' -PassThru | + Add-Member -MemberType NoteProperty -Name 'VirtualDirectoryReportManager' -Value '' -PassThru | + Add-Member -MemberType ScriptMethod -Name SetVirtualDirectory { + return $null + } -PassThru | + Add-Member -MemberType ScriptMethod -Name ReserveURL { + return $null + } -PassThru | + Add-Member -MemberType ScriptMethod -Name GenerateDatabaseCreationScript { + return @{ + Script = 'select * from something' + } + } -PassThru | + Add-Member -MemberType ScriptMethod -Name GenerateDatabaseRightsScript { + return @{ + Script = 'select * from something' + } + } -PassThru | + Add-Member -MemberType ScriptMethod -Name SetDatabaseConnection { + return $null + } -PassThru | + Add-Member -MemberType ScriptMethod -Name InitializeReportServer { + return $null + } -PassThru -Force + } + + $mockGetWmiObject_ConfigurationSetting_DefaultInstance = { + return @{ + DatabaseServerName = $mockReportingServicesDatabaseServerName + IsInitialized = $false + } + } + + $mockGetWmiObject_ConfigurationSetting_ParameterFilter = { + $Class -eq 'MSReportServer_ConfigurationSetting' + } + + $mockGetWmiObject_Language = { + return @{ + Language = 'en-US' + } + } + + $mockGetWmiObject_OperatingSystem_ParameterFilter = { + $Class -eq 'Win32_OperatingSystem' + } + + Describe "xSQLServerRSConfig\Get-TargetResource" -Tag 'Get' { + BeforeAll { + $mockDynamic_SqlBuildVersion = '13.0.4001.0' + + Mock -CommandName Get-ItemProperty -MockWith $mockGetItemProperty -Verifiable + + $testParameters = @{ + InstanceName = $mockNamedInstanceName + RSSQLServer = $mockReportingServicesDatabaseServerName + RSSQLInstanceName = $mockReportingServicesDatabaseNamedInstanceName + } + } + + Context 'When the system is in the desired state' { + BeforeEach { + Mock -CommandName Get-WmiObject ` + -MockWith $mockGetWmiObject_ConfigurationSetting_NamedInstance ` + -ParameterFilter $mockGetWmiObject_ConfigurationSetting_ParameterFilter ` + -Verifiable + } + + It 'Should return the same values as passed as parameters' { + $resultGetTargetResource = Get-TargetResource @testParameters + $resultGetTargetResource.InstanceName | Should Be $mockNamedInstanceName + $resultGetTargetResource.RSSQLServer | Should Be $mockReportingServicesDatabaseServerName + $resultGetTargetResource.RSSQLInstanceName | Should Be $mockReportingServicesDatabaseNamedInstanceName + $resultGetTargetResource | Should BeOfType [System.Collections.Hashtable] + } + + It 'Should return the the state as initialized' { + $resultGetTargetResource = Get-TargetResource @testParameters + $resultGetTargetResource.IsInitialized | Should Be $true + } + } + + Context 'When the system is not in the desired state' { + BeforeEach { + Mock -CommandName Get-WmiObject ` + -MockWith $mockGetWmiObject_ConfigurationSetting_DefaultInstance ` + -ParameterFilter $mockGetWmiObject_ConfigurationSetting_ParameterFilter ` + -Verifiable + } + + It 'Should return the same values as passed as parameters' { + $resultGetTargetResource = Get-TargetResource @testParameters + $resultGetTargetResource.InstanceName | Should Be $mockNamedInstanceName + $resultGetTargetResource.RSSQLServer | Should Be $mockReportingServicesDatabaseServerName + $resultGetTargetResource.RSSQLInstanceName | Should Be 'MSSQLSERVER' + $resultGetTargetResource | Should BeOfType [System.Collections.Hashtable] + } + + It 'Should return the the state as initialized' { + $resultGetTargetResource = Get-TargetResource @testParameters + $resultGetTargetResource.IsInitialized | Should Be $false + } + + Context 'When there is no Reporting Services instance' { + BeforeEach { + Mock -CommandName Get-ItemProperty + } + + It 'Should return the the state as initialized' { + { Get-TargetResource @testParameters } | Should Throw 'SQL Reporting Services instance ''INSTANCE'' does not exist!' + } + } + } + } + + Describe "xSQLServerRSConfig\Set-TargetResource" -Tag 'Set' { + BeforeAll { + Mock -CommandName Import-SQLPSModule + Mock -CommandName Invoke-Sqlcmd + Mock -CommandName Get-ItemProperty -MockWith $mockGetItemProperty -Verifiable + } + + Context 'When the system is not in the desired state' { + Context 'When configuring a named instance' { + BeforeAll { + $mockDynamic_SqlBuildVersion = '13.0.4001.0' + + Mock -CommandName Test-TargetResource -MockWith { + return $true + } + + $testParameters = @{ + InstanceName = $mockNamedInstanceName + RSSQLServer = $mockReportingServicesDatabaseServerName + RSSQLInstanceName = $mockReportingServicesDatabaseNamedInstanceName + } + } + + BeforeEach { + Mock -CommandName Get-WmiObject ` + -MockWith $mockGetWmiObject_ConfigurationSetting_NamedInstance ` + -ParameterFilter $mockGetWmiObject_ConfigurationSetting_ParameterFilter ` + -Verifiable + + Mock -CommandName Get-WmiObject ` + -MockWith $mockGetWmiObject_Language ` + -ParameterFilter $mockGetWmiObject_OperatingSystem_ParameterFilter ` + -Verifiable + } + + It 'Should configure Reporting Service without throwing an error' { + { Set-TargetResource @testParameters } | Should Not Throw + } + + Context 'When there is no Reporting Services instance' { + BeforeEach { + Mock -CommandName Get-ItemProperty + Mock -CommandName Test-TargetResource + } + + It 'Should return the the state as initialized' { + { Set-TargetResource @testParameters } | Should Throw 'Test-TargetResource returned false after calling set.' + } + } + } + + Context 'When configuring a default instance' { + BeforeAll { + $mockDynamic_SqlBuildVersion = '12.0.4100.1' + + Mock -CommandName Test-TargetResource -MockWith { + return $true + } + + $testParameters = @{ + InstanceName = $mockDefaultInstanceName + RSSQLServer = $mockReportingServicesDatabaseServerName + RSSQLInstanceName = $mockReportingServicesDatabaseDefaultInstanceName + } + } + + BeforeEach { + Mock -CommandName Get-WmiObject ` + -MockWith $mockGetWmiObject_ConfigurationSetting_NamedInstance ` + -ParameterFilter $mockGetWmiObject_ConfigurationSetting_ParameterFilter ` + -Verifiable + + Mock -CommandName Get-WmiObject ` + -MockWith $mockGetWmiObject_Language ` + -ParameterFilter $mockGetWmiObject_OperatingSystem_ParameterFilter ` + -Verifiable + } + + It 'Should configure Reporting Service without throwing an error' { + { Set-TargetResource @testParameters } | Should Not Throw + } + } + } + } + + Describe "xSQLServerRSConfig\Test-TargetResource" -Tag 'Test' { + Context 'When the system is not in the desired state' { + BeforeAll { + Mock -CommandName Get-TargetResource -MockWith { + return @{ + IsInitialized = $false + } + } + + $testParameters = @{ + InstanceName = $mockNamedInstanceName + RSSQLServer = $mockReportingServicesDatabaseServerName + RSSQLInstanceName = $mockReportingServicesDatabaseNamedInstanceName + } + } + + It 'Should return state as not in desired state' { + $resultTestTargetResource = Test-TargetResource @testParameters + $resultTestTargetResource | Should Be $false + } + } + + Context 'When the system is in the desired state' { + BeforeAll { + Mock -CommandName Get-TargetResource -MockWith { + return @{ + IsInitialized = $true + } + } + + $testParameters = @{ + InstanceName = $mockNamedInstanceName + RSSQLServer = $mockReportingServicesDatabaseServerName + RSSQLInstanceName = $mockReportingServicesDatabaseNamedInstanceName + } + } + + It 'Should return state as in desired state' { + $resultTestTargetResource = Test-TargetResource @testParameters + $resultTestTargetResource | Should Be $true + } + } + } + } +} +finally +{ + Invoke-TestCleanup +} From 969aa8561825e66c21edf54d77e9c4a91334b112 Mon Sep 17 00:00:00 2001 From: Johan Ljunggren Date: Sat, 27 May 2017 12:26:42 +0200 Subject: [PATCH 10/12] Changed language string to correct value in the test --- Tests/Unit/MSFT_xSQLServerRSConfig.Tests.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tests/Unit/MSFT_xSQLServerRSConfig.Tests.ps1 b/Tests/Unit/MSFT_xSQLServerRSConfig.Tests.ps1 index 3913bf9dd..6f3b875e0 100644 --- a/Tests/Unit/MSFT_xSQLServerRSConfig.Tests.ps1 +++ b/Tests/Unit/MSFT_xSQLServerRSConfig.Tests.ps1 @@ -91,7 +91,7 @@ try $mockGetWmiObject_Language = { return @{ - Language = 'en-US' + Language = '1033' } } From 1a29064322fb57bf154a47b4e6b0143c4c23ce94 Mon Sep 17 00:00:00 2001 From: Marko Bozikovic Date: Tue, 30 May 2017 15:06:52 +0100 Subject: [PATCH 11/12] [#569] Added explicit cast to int for SQL Server version value --- .../MSFT_xSQLServerRSConfig/MSFT_xSQLServerRSConfig.psm1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DSCResources/MSFT_xSQLServerRSConfig/MSFT_xSQLServerRSConfig.psm1 b/DSCResources/MSFT_xSQLServerRSConfig/MSFT_xSQLServerRSConfig.psm1 index 4e6b0ed47..54f178a84 100644 --- a/DSCResources/MSFT_xSQLServerRSConfig/MSFT_xSQLServerRSConfig.psm1 +++ b/DSCResources/MSFT_xSQLServerRSConfig/MSFT_xSQLServerRSConfig.psm1 @@ -81,7 +81,7 @@ function Set-TargetResource Import-SQLPSModule $InstanceKey = (Get-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Microsoft SQL Server\Instance Names\RS" -Name $InstanceName).$InstanceName - $SQLVersion = ((Get-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Microsoft SQL Server\$InstanceKey\Setup" -Name "Version").Version).Split(".")[0] + $SQLVersion = [int]((Get-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Microsoft SQL Server\$InstanceKey\Setup" -Name "Version").Version).Split(".")[0] if($InstanceName -eq "MSSQLSERVER") { $RSServiceName = "ReportServer" From ebe2d64fc4ccfe6c73a8c78ba08f11bc99f813a3 Mon Sep 17 00:00:00 2001 From: Marko Bozikovic Date: Thu, 1 Jun 2017 17:25:57 +0100 Subject: [PATCH 12/12] [#570] Virtual directories and URL reservations. --- CHANGELOG.md | 1 + .../MSFT_xSQLServerRSConfig.psm1 | 233 +++++++++++++++--- .../MSFT_xSQLServerRSConfig.schema.mof | 4 + README.md | 6 +- 4 files changed, 213 insertions(+), 31 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9e09e54eb..8501c3ad9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ - BREAKING CHANGE: removed $SQLAdminCredential parameter. Use common parameter PsDscRunAsCredential (WMF 5.0+) to run the resource under different credentials. PsDscRunAsCredential Windows account must be a sysadmin on SQL Server (issue #568). - Fixed virtual directory creation for SQL Server 2016. - Added unit tests (issue #295). + - Added support for configuring URL reservations and virtual directory names (issue #570) ## 7.1.0.0 diff --git a/DSCResources/MSFT_xSQLServerRSConfig/MSFT_xSQLServerRSConfig.psm1 b/DSCResources/MSFT_xSQLServerRSConfig/MSFT_xSQLServerRSConfig.psm1 index 54f178a84..c970216e9 100644 --- a/DSCResources/MSFT_xSQLServerRSConfig/MSFT_xSQLServerRSConfig.psm1 +++ b/DSCResources/MSFT_xSQLServerRSConfig/MSFT_xSQLServerRSConfig.psm1 @@ -20,13 +20,29 @@ function Get-TargetResource [parameter(Mandatory = $true)] [System.String] - $RSSQLInstanceName + $RSSQLInstanceName, + + [parameter()] + [System.String] + $ReportServerVirtualDir, + + [parameter()] + [System.String] + $ReportsVirtualDir, + + [parameter()] + [System.String[]] + $ReportServerReservedUrl, + + [parameter()] + [System.String[]] + $ReportsReservedUrl ) if(Get-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Microsoft SQL Server\Instance Names\RS" -Name $InstanceName -ErrorAction SilentlyContinue) { $InstanceKey = (Get-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Microsoft SQL Server\Instance Names\RS" -Name $InstanceName).$InstanceName - $SQLVersion = ((Get-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Microsoft SQL Server\$InstanceKey\Setup" -Name "Version").Version).Split(".")[0] + $SQLVersion = [int]((Get-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Microsoft SQL Server\$InstanceKey\Setup" -Name "Version").Version).Split(".")[0] $RSConfig = Get-WmiObject -Class MSReportServer_ConfigurationSetting -Namespace "root\Microsoft\SQLServer\ReportServer\RS_$InstanceName\v$SQLVersion\Admin" if($RSConfig.DatabaseServerName.Contains("\")) @@ -40,6 +56,27 @@ function Get-TargetResource $RSSQLInstanceName = "MSSQLSERVER" } $IsInitialized = $RSConfig.IsInitialized + + if($IsInitialized) + { + # SSRS Web Portal application name changed in SQL Server 2016 + # https://docs.microsoft.com/en-us/sql/reporting-services/breaking-changes-in-sql-server-reporting-services-in-sql-server-2016 + $RMApplicationName = if ($SQLVersion -ge 13) { 'ReportServerWebApp' } else { 'ReportManager'} + + $ReportServerVirtualDir = $RSConfig.VirtualDirectoryReportServer + $ReportsVirtualDir = $RSConfig.VirtualDirectoryReportManager + + $reservedUrls = $RSConfig.ListReservedUrls() + + $ReportServerReservedUrl = @() + $ReportsReservedUrl = @() + + for($i = 0; $i -lt $reservedUrls.Application.Count; ++$i) + { + if($reservedUrls.Application[$i] -eq "ReportServerWebService") { $ReportServerReservedUrl += $reservedUrls.UrlString[$i] } + if($reservedUrls.Application[$i] -eq "$RMApplicationName") { $ReportsReservedUrl += $reservedUrls.UrlString[$i] } + } + } } else { @@ -50,6 +87,10 @@ function Get-TargetResource InstanceName = $InstanceName RSSQLServer = $RSSQLServer RSSQLInstanceName = $RSSQLInstanceName + ReportServerVirtualDir = $ReportServerVirtualDir + ReportsVirtualDir = $ReportsVirtualDir + ReportServerReservedUrl = $ReportServerReservedUrl + ReportsReservedUrl = $ReportsReservedUrl IsInitialized = $IsInitialized } @@ -72,28 +113,41 @@ function Set-TargetResource [parameter(Mandatory = $true)] [System.String] - $RSSQLInstanceName + $RSSQLInstanceName, + + [parameter()] + [System.String] + $ReportServerVirtualDir, + + [parameter()] + [System.String] + $ReportsVirtualDir, + + [parameter()] + [System.String[]] + $ReportServerReservedUrl, + + [parameter()] + [System.String[]] + $ReportsReservedUrl ) if(Get-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Microsoft SQL Server\Instance Names\RS" -Name $InstanceName -ErrorAction SilentlyContinue) { - # smart import of the SQL module - Import-SQLPSModule - $InstanceKey = (Get-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Microsoft SQL Server\Instance Names\RS" -Name $InstanceName).$InstanceName $SQLVersion = [int]((Get-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Microsoft SQL Server\$InstanceKey\Setup" -Name "Version").Version).Split(".")[0] if($InstanceName -eq "MSSQLSERVER") { $RSServiceName = "ReportServer" - $RSVirtualDirectory = "ReportServer" - $RMVirtualDirectory = "Reports" + if([string]::IsNullOrEmpty($ReportServerVirtualDir)) { $ReportServerVirtualDir = "ReportServer" } + if([string]::IsNullOrEmpty($ReportsVirtualDir)) { $ReportsVirtualDir = "Reports" } $RSDatabase = "ReportServer" } else { $RSServiceName = "ReportServer`$$InstanceName" - $RSVirtualDirectory = "ReportServer_$InstanceName" - $RMVirtualDirectory = "Reports_$InstanceName" + if([string]::IsNullOrEmpty($ReportServerVirtualDir)) { $ReportServerVirtualDir = "ReportServer_$InstanceName" } + if([string]::IsNullOrEmpty($ReportsVirtualDir)) { $ReportsVirtualDir = "Reports_$InstanceName" } $RSDatabase = "ReportServer`$$InstanceName" } if($RSSQLInstanceName -eq "MSSQLSERVER") @@ -106,29 +160,100 @@ function Set-TargetResource } $Language = (Get-WMIObject -Class Win32_OperatingSystem -Namespace root/cimv2 -ErrorAction SilentlyContinue).OSLanguage $RSConfig = Get-WmiObject -Class MSReportServer_ConfigurationSetting -Namespace "root\Microsoft\SQLServer\ReportServer\RS_$InstanceName\v$SQLVersion\Admin" - if($RSConfig.VirtualDirectoryReportServer -ne $RSVirtualDirectory) + + # SSRS Web Portal application name changed in SQL Server 2016 + # https://docs.microsoft.com/en-us/sql/reporting-services/breaking-changes-in-sql-server-reporting-services-in-sql-server-2016 + $RMApplicationName = if ($SQLVersion -ge 13) { 'ReportServerWebApp' } else { 'ReportManager'} + + if(!$RSConfig.IsInitialized) { - $null = $RSConfig.SetVirtualDirectory("ReportServerWebService",$RSVirtualDirectory,$Language) - $null = $RSConfig.ReserveURL("ReportServerWebService","http://+:80",$Language) + New-VerboseMessage -Message "Initializing Reporting Services on $RSSQLServer\$RSSQLInstanceName." + + if($ReportServerReservedUrl -eq $null) { $ReportServerReservedUrl = @("http://+:80") } + if($ReportsReservedUrl -eq $null) { $ReportsReservedUrl = @("http://+:80") } + + if($RSConfig.VirtualDirectoryReportServer -ne $ReportServerVirtualDir) + { + New-VerboseMessage -Message "Setting report server virtual directory on $RSSQLServer\$RSSQLInstanceName to $ReportServerVirtualDir." + $null = $RSConfig.SetVirtualDirectory("ReportServerWebService",$ReportServerVirtualDir,$Language) + $ReportServerReservedUrl | ForEach-Object { + New-VerboseMessage -Message "Adding report server URL reservation on $RSSQLServer\$RSSQLInstanceName`: $_." + $null = $RSConfig.ReserveURL("ReportServerWebService",$_,$Language) + } + } + if($RSConfig.VirtualDirectoryReportManager -ne $ReportsVirtualDir) + { + New-VerboseMessage -Message "Setting reports virtual directory on $RSSQLServer\$RSSQLInstanceName to $ReportServerVirtualDir." + $null = $RSConfig.SetVirtualDirectory($RMApplicationName,$ReportsVirtualDir,$Language) + $ReportsReservedUrl | ForEach-Object { + New-VerboseMessage -Message "Adding reports URL reservation on $RSSQLServer\$RSSQLInstanceName`: $_." + $null = $RSConfig.ReserveURL($RMApplicationName,$_,$Language) + } + } + $RSCreateScript = $RSConfig.GenerateDatabaseCreationScript($RSDatabase,$Language,$false) + + # Determine RS service account + $RSSvcAccountUsername = (Get-WmiObject -Class Win32_Service | Where-Object {$_.Name -eq $RSServiceName}).StartName + $RSRightsScript = $RSConfig.GenerateDatabaseRightsScript($RSSvcAccountUsername,$RSDatabase,$false,$true) + + # smart import of the SQL module + Import-SQLPSModule + Invoke-Sqlcmd -ServerInstance $RSConnection -Query $RSCreateScript.Script + Invoke-Sqlcmd -ServerInstance $RSConnection -Query $RSRightsScript.Script + + $null = $RSConfig.SetDatabaseConnection($RSConnection,$RSDatabase,2,"","") + $null = $RSConfig.InitializeReportServer($RSConfig.InstallationID) } - if($RSConfig.VirtualDirectoryReportManager -ne $RMVirtualDirectory) + else { - # SSRS Web Portal application name changed in SQL Server 2016 - # https://docs.microsoft.com/en-us/sql/reporting-services/breaking-changes-in-sql-server-reporting-services-in-sql-server-2016 - $virtualDirectoryName = if ($SQLVersion -ge 13) { 'ReportServerWebApp' } else { 'ReportManager'} - $null = $RSConfig.SetVirtualDirectory($virtualDirectoryName,$RMVirtualDirectory,$Language) - $null = $RSConfig.ReserveURL($virtualDirectoryName,"http://+:80",$Language) - } - $RSCreateScript = $RSConfig.GenerateDatabaseCreationScript($RSDatabase,$Language,$false) + $currentConfig = Get-TargetResource @PSBoundParameters + + if(![string]::IsNullOrEmpty($ReportServerVirtualDir) -and ($ReportServerVirtualDir -ne $currentConfig.ReportServerVirtualDir)) + { + New-VerboseMessage -Message "Setting report server virtual directory on $RSSQLServer\$RSSQLInstanceName to $ReportServerVirtualDir." + + # to change a virtual directory, we first need to remove all URL reservations, + # change the virtual directory and re-add URL reservations + $currentConfig.ReportServerReservedUrl | ForEach-Object { $null = $RSConfig.RemoveURL("ReportServerWebService",$_,$Language) } + $RSConfig.SetVirtualDirectory("ReportServerWebService",$ReportServerVirtualDir,$Language) + $currentConfig.ReportServerReservedUrl | ForEach-Object { $null = $RSConfig.ReserveURL("ReportServerWebService",$_,$Language) } + } + + if(![string]::IsNullOrEmpty($ReportsVirtualDir) -and ($ReportsVirtualDir -ne $currentConfig.ReportsVirtualDir)) + { + New-VerboseMessage -Message "Setting reports virtual directory on $RSSQLServer\$RSSQLInstanceName to $ReportServerVirtualDir." - # Determine RS service account - $RSSvcAccountUsername = (Get-WmiObject -Class Win32_Service | Where-Object {$_.Name -eq $RSServiceName}).StartName - $RSRightsScript = $RSConfig.GenerateDatabaseRightsScript($RSSvcAccountUsername,$RSDatabase,$false,$true) + # to change a virtual directory, we first need to remove all URL reservations, + # change the virtual directory and re-add URL reservations + $currentConfig.ReportsReservedUrl | ForEach-Object { $null = $RSConfig.RemoveURL($RMApplicationName,$_,$Language) } + $RSConfig.SetVirtualDirectory($RMApplicationName,$ReportsVirtualDir,$Language) + $currentConfig.ReportsReservedUrl | ForEach-Object { $null = $RSConfig.ReserveURL($RMApplicationName,$_,$Language) } + } - Invoke-Sqlcmd -ServerInstance $RSConnection -Query $RSCreateScript.Script - Invoke-Sqlcmd -ServerInstance $RSConnection -Query $RSRightsScript.Script - $null = $RSConfig.SetDatabaseConnection($RSConnection,$RSDatabase,2,"","") - $null = $RSConfig.InitializeReportServer($RSConfig.InstallationID) + if(($ReportServerReservedUrl -ne $null) -and ((Compare-Object -ReferenceObject $currentConfig.ReportServerReservedUrl -DifferenceObject $ReportServerReservedUrl) -ne $null)) + { + $currentConfig.ReportServerReservedUrl | ForEach-Object { + $null = $RSConfig.RemoveURL("ReportServerWebService",$_,$Language) + } + + $ReportServerReservedUrl | ForEach-Object { + New-VerboseMessage -Message "Adding report server URL reservation on $RSSQLServer\$RSSQLInstanceName`: $_." + $null = $RSConfig.ReserveURL("ReportServerWebService",$_,$Language) + } + } + + if(($ReportsReservedUrl -ne $null) -and ((Compare-Object -ReferenceObject $currentConfig.ReportsReservedUrl -DifferenceObject $ReportsReservedUrl) -ne $null)) + { + $currentConfig.ReportsReservedUrl | ForEach-Object { + $null = $RSConfig.RemoveURL($RMApplicationName,$_,$Language) + } + + $ReportsReservedUrl | ForEach-Object { + New-VerboseMessage -Message "Adding reports URL reservation on $RSSQLServer\$RSSQLInstanceName`: $_." + $null = $RSConfig.ReserveURL($RMApplicationName,$_,$Language) + } + } + } } if(!(Test-TargetResource @PSBoundParameters)) @@ -154,11 +279,59 @@ function Test-TargetResource [parameter(Mandatory = $true)] [System.String] - $RSSQLInstanceName + $RSSQLInstanceName, + + [parameter()] + [System.String] + $ReportServerVirtualDir, + + [parameter()] + [System.String] + $ReportsVirtualDir, + + [parameter()] + [System.String[]] + $ReportServerReservedUrl, + + [parameter()] + [System.String[]] + $ReportsReservedUrl ) - $result = (Get-TargetResource @PSBoundParameters).IsInitialized + $result = $true + + $currentConfig = Get-TargetResource @PSBoundParameters + if(!$currentConfig.IsInitialized) + { + New-VerboseMessage -Message "Reporting services $RSSQLServer\$RSSQLInstanceName are not initialized." + $result = $false + } + + if(![string]::IsNullOrEmpty($ReportServerVirtualDir) -and ($ReportServerVirtualDir -ne $currentConfig.ReportServerVirtualDir)) + { + New-VerboseMessage -Message "Report server virtual directory on $RSSQLServer\$RSSQLInstanceName is $($currentConfig.ReportServerVirtualDir), should be $ReportServerVirtualDir." + $result = $false + } + + if(![string]::IsNullOrEmpty($ReportsVirtualDir) -and ($ReportsVirtualDir -ne $currentConfig.ReportsVirtualDir)) + { + New-VerboseMessage -Message "Reports virtual directory on $RSSQLServer\$RSSQLInstanceName is $($currentConfig.ReportsVirtualDir), should be $ReportsVirtualDir." + $result = $false + } + + if(($ReportServerReservedUrl -ne $null) -and ((Compare-Object -ReferenceObject $currentConfig.ReportServerReservedUrl -DifferenceObject $ReportServerReservedUrl) -ne $null)) + { + New-VerboseMessage -Message "Report server reserved URLs on $RSSQLServer\$RSSQLInstanceName are $($currentConfig.ReportServerReservedUrl -join ', '), should be $($ReportServerReservedUrl -join ', ')." + $result = $false + } + + if(($ReportsReservedUrl -ne $null) -and ((Compare-Object -ReferenceObject $currentConfig.ReportsReservedUrl -DifferenceObject $ReportsReservedUrl) -ne $null)) + { + New-VerboseMessage -Message "Reports reserved URLs on $RSSQLServer\$RSSQLInstanceName are $($currentConfig.ReportsReservedUrl -join ', ')), should be $($ReportsReservedUrl -join ', ')." + $result = $false + } + $result } diff --git a/DSCResources/MSFT_xSQLServerRSConfig/MSFT_xSQLServerRSConfig.schema.mof b/DSCResources/MSFT_xSQLServerRSConfig/MSFT_xSQLServerRSConfig.schema.mof index 06674454c..c39f79b22 100644 --- a/DSCResources/MSFT_xSQLServerRSConfig/MSFT_xSQLServerRSConfig.schema.mof +++ b/DSCResources/MSFT_xSQLServerRSConfig/MSFT_xSQLServerRSConfig.schema.mof @@ -4,5 +4,9 @@ class MSFT_xSQLServerRSConfig : 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 Service database.")] String RSSQLServer; [Required, Description("Name of the SQL Server instance to host the Reporting Service database.")] String RSSQLInstanceName; + [Write, Description("Report Server virtual directory name. Optional.")] String ReportServerVirtualDir; + [Write, Description("Report Manager/Report Web App virtual directory name. Optional.")] String ReportsVirtualDir; + [Write, Description("Report Server reserved URLs. Optional.")] String ReportServerReservedUrl[]; + [Write, Description("Report Manager/Report Web App reserved URLs. Optional.")] String ReportsReservedUrl[]; [Read, Description("Is the Reporting Services instance initialized.")] Boolean IsInitialized; }; diff --git a/README.md b/README.md index 97d56fc94..33471e840 100644 --- a/README.md +++ b/README.md @@ -867,7 +867,7 @@ This resource is used to create a server role, when Ensure is set to 'Present'. ### xSQLServerRSConfig -No description. +Initializes and configures SQL Reporting Services server. #### Requirements @@ -879,6 +879,10 @@ No description. * **[String] InstanceName** _(Key)_: Name of the SQL Server Reporting Services instance to be configured. * **[String] RSSQLServer** _(Required)_: Name of the SQL Server to host the Reporting Service database. * **[String] RSSQLInstanceName** _(Required)_: Name of the SQL Server instance to host the Reporting Service database. +* **[String] ReportServerVirtualDir** _(Write)_: Report Server Web Service virtual directory. Optional. +* **[String] ReportsVirtualDir** _(Write)_: Report Manager virtual directory. Optional. +* **[String[]] ReportServerReservedUrl** _(Write)_: Report Server URL reservations. Optional. If not specified, "http://+:80" URL reservation will be used. +* **[String[]] ReportsReservedUrl** _(Write)_: Report Manager URL reservations. Optional. If not specified, "http://+:80" URL reservation will be used. #### Read-Only Properties from Get-TargetResource