Skip to content

Commit

Permalink
[dsccommunity#570] Virtual directories and URL reservations.
Browse files Browse the repository at this point in the history
  • Loading branch information
bozho committed Jun 1, 2017
1 parent 18da6aa commit 1ce3850
Show file tree
Hide file tree
Showing 4 changed files with 214 additions and 32 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,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 (issue #569).
- Added unit tests (issue #295).
- Added support for configuring URL reservations and virtual directory names (issue #570)
- 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.
Expand Down
233 changes: 203 additions & 30 deletions DSCResources/MSFT_xSQLServerRSConfig/MSFT_xSQLServerRSConfig.psm1
Original file line number Diff line number Diff line change
Expand Up @@ -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("\"))
Expand All @@ -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
{
Expand All @@ -50,6 +87,10 @@ function Get-TargetResource
InstanceName = $InstanceName
RSSQLServer = $RSSQLServer
RSSQLInstanceName = $RSSQLInstanceName
ReportServerVirtualDir = $ReportServerVirtualDir
ReportsVirtualDir = $ReportsVirtualDir
ReportServerReservedUrl = $ReportServerReservedUrl
ReportsReservedUrl = $ReportsReservedUrl
IsInitialized = $IsInitialized
}

Expand All @@ -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")
Expand All @@ -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))
Expand All @@ -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
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
};
8 changes: 6 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand All @@ -878,7 +878,11 @@ 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] 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.
* **[PSCredential] SQLAdminCredential** _(Required)_: Credential to be used to perform the configuration.

#### Read-Only Properties from Get-TargetResource
Expand Down

0 comments on commit 1ce3850

Please sign in to comment.