diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..faff990 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +.vs/ +ssrs-powershell-deploy/obj/ diff --git a/README.md b/README.md index 0b4e4f5..c5d52d4 100644 --- a/README.md +++ b/README.md @@ -69,8 +69,9 @@ parameters. Publish-SSRSProject [-Path] [[-Configuration] ] [[-ServerUrl] ] [[-Folder] ] [[-DataSourceFolder] ] [[-DataSetFolder] ] - [[-OutputPath] ] [[-OverwriteDataSources] ] - [[-OverwriteDatasets] ] [[-Credential] ] + [[-OutputPath] ] + [[-OverwriteDataSources] ] [[-OverwriteDatasets] ] + [[-Credential] ] [-CustomAuthentication] [] ## Example reports diff --git a/ssrs-powershell-deploy/SSRS/Get-SSRSProjectConfiguration.ps1 b/ssrs-powershell-deploy/SSRS/Get-SSRSProjectConfiguration.ps1 index 6047d89..7d8eb9a 100644 --- a/ssrs-powershell-deploy/SSRS/Get-SSRSProjectConfiguration.ps1 +++ b/ssrs-powershell-deploy/SSRS/Get-SSRSProjectConfiguration.ps1 @@ -20,33 +20,25 @@ Write-Verbose "Reading '$Configuration' config from '$Path'" [xml]$Project = Get-Content -Path $Path + $Namespace = New-Object Xml.XmlNamespaceManager $Project.NameTable + $Namespace.AddNamespace('ns', $Project.DocumentElement.NamespaceURI) - $propertyGroupCount = $Project.Project.PropertyGroup.Count + $Config = $Project.SelectNodes('//ns:PropertyGroup', $Namespace) | + Where-Object { $_.FullPath -eq $Configuration } | + Select-Object -First 1 - for($i = 0; $i -lt $propertyGroupCount; $i++) - { - if($Project.Project.PropertyGroup[$i].FullPath -eq $Configuration) - { - $Config = $Project.Project.PropertyGroup[$i] - break - } - } - - #$Config = $Project.SelectNodes('Project/PropertyGroup') | - # Where-Object { $_.FullPath -eq $Configuration } | - # Select-Object -First 1 if (-not $Config) { throw "Could not find configuration '$Configuration'." } $OverwriteDataSources = $false - if ($Config.SelectSingleNode('OverwriteDataSources')) { + if ($Config.SelectSingleNode('ns:OverwriteDataSources', $Namespace)) { $OverwriteDataSources = [Convert]::ToBoolean($Config.OverwriteDataSources) } $OverwriteDatasets = $false - if ($Config.SelectSingleNode('OverwriteDatasets')) { + if ($Config.SelectSingleNode('ns:OverwriteDatasets', $Namespace)) { $OverwriteDatasets = [Convert]::ToBoolean($Config.OverwriteDatasets) } diff --git a/ssrs-powershell-deploy/SSRS/New-SSRSDataSource.ps1 b/ssrs-powershell-deploy/SSRS/New-SSRSDataSource.ps1 index 9499bdf..5a1c98a 100644 --- a/ssrs-powershell-deploy/SSRS/New-SSRSDataSource.ps1 +++ b/ssrs-powershell-deploy/SSRS/New-SSRSDataSource.ps1 @@ -19,6 +19,8 @@ function New-SSRSDataSource ( $Definition.ConnectString = $ConnProps.ConnectString $Definition.Extension = $ConnProps.Extension + $connectionString = New-Object System.Data.Common.DbConnectionStringBuilder + $connectionString.set_ConnectionString($ConnProps.ConnectString) #Does the IntegratedSecurity property exist $integratedproperty = $ConnProps | Get-Member -MemberType Property | where {$_.name -like 'IntegratedSecurity'} @@ -31,6 +33,10 @@ function New-SSRSDataSource ( } else{ write-verbose "IntegratedSecurity Missing" + + $Definition.CredentialRetrieval = 'Store' + $Definition.UserName = $connectionString['User ID'] + $Definition.Password = $connectionString['Password'] } $DataSource = New-Object -TypeName PSObject -Property @{ diff --git a/ssrs-powershell-deploy/SSRS/New-SSRSFolder.ps1 b/ssrs-powershell-deploy/SSRS/New-SSRSFolder.ps1 index 6e34983..7e19bce 100644 --- a/ssrs-powershell-deploy/SSRS/New-SSRSFolder.ps1 +++ b/ssrs-powershell-deploy/SSRS/New-SSRSFolder.ps1 @@ -32,4 +32,82 @@ function New-SSRSFolder ( Write-Verbose " - skipped, already exists" } } + + $type = $Proxy.GetType().Namespace; + $policyType = "{0}.Policy" -f $type; + $roleType = "{0}.Role" -f $type; + + $InheritParent = $true + + if($Name -eq '/Core' -or $Name -eq '/Client_Data' -or $Name -eq '/Import' -or $Name -eq '/Datasets') + { + Write-Verbose "Setting Policies for Subscribers..." + + $Policies = $Proxy.GetPolicies($Name, [ref]$InheritParent) + + $GroupUserName = 'Subscribers' + $RoleName = 'Browser' + + #Return all policies that contain the user/group we want to add + $Policy = $Policies | + Where-Object { $_.GroupUserName -eq $GroupUserName } | + Select-Object -First 1 + #Add a new policy if doesnt exist + if (-not $Policy) + { + $Policy = New-Object ($policyType) + $Policy.GroupUserName = $GroupUserName + $Policy.Roles = @() + #Add new policy to the folder's policies + $Policies += $Policy + } + #Add the role to the new Policy + $r = $Policy.Roles | + Where-Object { $_.Name -eq $RoleName } | + Select-Object -First 1 + if (-not $r) + { + $r = New-Object ($roleType) + $r.Name = $RoleName + $Policy.Roles += $r + } + + #Set folder policies + $Proxy.SetPolicies($Name, $Policies); + } + + Write-Verbose "Setting Policies for Administrators..." + + $Policies = $Proxy.GetPolicies('/', [ref]$InheritParent) + + #Admin + $GroupUserName = 'Administrators' + $RoleName = 'Content Manager' + + #Return all policies that contain the user/group we want to add + $Policy = $Policies | + Where-Object { $_.GroupUserName -eq $GroupUserName } | + Select-Object -First 1 + #Add a new policy if doesnt exist + if (-not $Policy) + { + $Policy = New-Object ($policyType) + $Policy.GroupUserName = $GroupUserName + $Policy.Roles = @() + #Add new policy to the folder's policies + $Policies += $Policy + } + #Add the role to the new Policy + $r = $Policy.Roles | + Where-Object { $_.Name -eq $RoleName } | + Select-Object -First 1 + if (-not $r) + { + $r = New-Object ($roleType) + $r.Name = $RoleName + $Policy.Roles += $r + } + + #Set folder policies + $Proxy.SetPolicies('/', $Policies); } diff --git a/ssrs-powershell-deploy/SSRS/New-SSRSWebServiceProxy.ps1 b/ssrs-powershell-deploy/SSRS/New-SSRSWebServiceProxy.ps1 index 2b9d804..d313366 100644 --- a/ssrs-powershell-deploy/SSRS/New-SSRSWebServiceProxy.ps1 +++ b/ssrs-powershell-deploy/SSRS/New-SSRSWebServiceProxy.ps1 @@ -9,7 +9,11 @@ $Uri, [System.Management.Automation.PSCredential] - $Credential + $Credential, + + [parameter(Mandatory=$false)] + [switch] + $CustomAuthentication ) $script:ErrorActionPreference = 'Stop' @@ -51,5 +55,25 @@ } $Proxy.Url = $Uri + + Write-Verbose "Custom Authentication: $CustomAuthentication" + + if ($CustomAuthentication) + { + if (!$Credential) + { + $Credential = Get-Credential + } + + $NetworkCredential = $Credential.GetNetworkCredential() + $proxy.CookieContainer = New-Object System.Net.CookieContainer + + Write-Verbose "Logging in..." + + $Proxy.LogonUser($NetworkCredential.UserName, $NetworkCredential.Password, $NetworkCredential.Domain); + + Write-Verbose "Authenticated!" + } + return $Proxy } diff --git a/ssrs-powershell-deploy/SSRS/Publish-SSRSProject.ps1 b/ssrs-powershell-deploy/SSRS/Publish-SSRSProject.ps1 index 77d64ef..fd5eb9b 100644 --- a/ssrs-powershell-deploy/SSRS/Publish-SSRSProject.ps1 +++ b/ssrs-powershell-deploy/SSRS/Publish-SSRSProject.ps1 @@ -42,9 +42,12 @@ [bool] $OverwriteDatasets, #THESE ARE NOW OVERRRIDES IF $Configuration is specified - [System.Management.Automation.PSCredential] - $Credential + $Credential, + + [parameter(Mandatory=$false)] + [switch] + $CustomAuthentication ) @@ -55,7 +58,8 @@ $ProjectRoot = $Path | Split-Path [xml]$Project = Get-Content -Path $Path - + $Namespace = New-Object Xml.XmlNamespaceManager $Project.NameTable + $Namespace.AddNamespace('ns', $Project.DocumentElement.NamespaceURI) #Argument validation if(![string]::IsNullOrEmpty($Configuration)) @@ -107,10 +111,11 @@ } - $Project.SelectNodes('Project/Reports/ProjectItem') | + $Project.SelectNodes('//ns:Report', $Namespace) | ForEach-Object { - $CompiledRdlPath = $ProjectRoot | Join-Path -ChildPath $OutputPath | join-path -ChildPath $_.FullPath - $RdlPath = $ProjectRoot | join-path -ChildPath $_.FullPath + $Name = $_.Include + $CompiledRdlPath = $ProjectRoot | Join-Path -ChildPath $OutputPath | join-path -ChildPath $Name + $RdlPath = $ProjectRoot | join-path -ChildPath $Name if ((test-path $CompiledRdlPath) -eq $false) { @@ -130,27 +135,36 @@ $Folder = Normalize-SSRSFolder -Folder $Folder $DataSourceFolder = Normalize-SSRSFolder -Folder $DataSourceFolder - $Proxy = New-SSRSWebServiceProxy -Uri $ServerUrl -Credential $Credential + $ProxyParameters = @{ + Uri = $ServerUrl + Credential = $Credential + CustomAuthentication = $CustomAuthentication + } + + Write-Verbose "Connecting to: $ServerUrl" + $Proxy = New-SSRSWebServiceProxy @ProxyParameters $FullServerPath = $Proxy.Url - Write-Verbose "Connecting to: $FullServerPath" New-SSRSFolder -Proxy $Proxy -Name $Folder New-SSRSFolder -Proxy $Proxy -Name $DataSourceFolder New-SSRSFolder -Proxy $Proxy -Name $DataSetFolder $DataSourcePaths = @{} - for($i = 0; $i -lt $Project.Project.ItemGroup[0].DataSource.Count; $i++) { - $RdsPath = $ProjectRoot | Join-Path -ChildPath $Project.Project.ItemGroup[0].DataSource[$i].Include + $Project.SelectNodes('//ns:DataSource', $Namespace) | + ForEach-Object { + $Name = $_.Include + $RdsPath = $ProjectRoot | Join-Path -ChildPath $Name - $DataSource = New-SSRSDataSource -Proxy $Proxy -RdsPath $RdsPath -Folder $DataSourceFolder -Overwrite $OverwriteDataSources - $DataSourcePaths.Add($DataSource.Name, $DataSource.Path) - } + $DataSource = New-SSRSDataSource -Proxy $Proxy -RdsPath $RdsPath -Folder $DataSourceFolder -Overwrite $OverwriteDataSources + $DataSourcePaths.Add($DataSource.Name, $DataSource.Path) + } $DataSetPaths = @{} - $Project.SelectNodes('Project/DataSets/ProjectItem') | + $Project.SelectNodes('//ns:DataSet', $Namespace) | ForEach-Object { - $RsdPath = $ProjectRoot | Join-Path -ChildPath $_.FullPath + $Name = $_.Include + $RsdPath = $ProjectRoot | Join-Path -ChildPath $Name $DataSet = New-SSRSDataSet -Proxy $Proxy -RsdPath $RsdPath -Folder $DataSetFolder -DataSourcePaths $DataSourcePaths -Overwrite $OverwriteDatasets if(-not $DataSetPaths.Contains($DataSet.Name)) { @@ -158,13 +172,14 @@ } } - for($i = 0; $i -lt $Project.Project.ItemGroup[1].Report.Count; $i++) { - - $extension = $Project.Project.ItemGroup[1].Report[$i].Include.Substring($Project.Project.ItemGroup[1].Report[$i].Include.length - 3 , 3) + $Project.SelectNodes('//ns:Report', $Namespace) | + ForEach-Object { + $Name = $_.Include + $MimeType = $_.SelectSingleNode('ns:MimeType', $Namespace) - if(ImageExtensionValid -ext $extension){ + if($MimeType){ - $PathImage = $ProjectRoot | Join-Path -ChildPath $Project.Project.ItemGroup[1].Report[$i].Include + $PathImage = $ProjectRoot | Join-Path -ChildPath $Name $RawDefinition = Get-Content -Encoding Byte -Path $PathImage $DescProp = New-Object -TypeName SSRS.ReportingService2010.Property @@ -175,37 +190,21 @@ $HiddenProp.Value = 'false' $MimeProp = New-Object -TypeName SSRS.ReportingService2010.Property $MimeProp.Name = 'MimeType' - $MimeProp.Value = 'image/' + $extension + $MimeProp.Value = $MimeType $Properties = @($DescProp, $HiddenProp, $MimeProp) - $Name = $Project.Project.ItemGroup[1].Report[$i].Include + $Name = $Name Write-Verbose "Creating resource $Name" $warnings = $null - $Results = $Proxy.CreateCatalogItem("Resource", $Project.Project.ItemGroup[1].Report[$i].Include, $Folder, $true, $RawDefinition, $Properties, [ref]$warnings) + $Results = $Proxy.CreateCatalogItem("Resource", $Name, $Folder, $true, $RawDefinition, $Properties, [ref]$warnings) + } + + if($Name.EndsWith('.rdl')){ + $CompiledRdlPath = $ProjectRoot | Join-Path -ChildPath $OutputPath | join-path -ChildPath $Name + New-SSRSReport -Proxy $Proxy -RdlPath $CompiledRdlPath -RdlName $Name } } - for($i = 0; $i -lt $Project.Project.ItemGroup[1].Report.Count; $i++) { - if($Project.Project.ItemGroup[1].Report[$i].Include.EndsWith('.rdl')){ - $CompiledRdlPath = $ProjectRoot | Join-Path -ChildPath $OutputPath | join-path -ChildPath $Project.Project.ItemGroup[1].Report[$i].Include - New-SSRSReport -Proxy $Proxy -RdlPath $CompiledRdlPath -RdlName $Project.Project.ItemGroup[1].Report[$i].Include - } - } - - Write-host "Completed." -} - -function ImageExtensionValid($ext){ - $valid = 0; - - Switch($ext) - { - 'png' { $valid = 1; } - 'bmp' { $valid = 1; } - 'gif' { $valid = 1; } - 'jpg' { $valid = 1; } - } - - return $valid; + Write-host "Completed: $Path" } diff --git a/ssrs-powershell-deploy/SSRS/Publish-SSRSSolution.ps1 b/ssrs-powershell-deploy/SSRS/Publish-SSRSSolution.ps1 index ea83f51..064816e 100644 --- a/ssrs-powershell-deploy/SSRS/Publish-SSRSSolution.ps1 +++ b/ssrs-powershell-deploy/SSRS/Publish-SSRSSolution.ps1 @@ -16,7 +16,11 @@ function Publish-SSRSSolution{ $Configuration, [System.Management.Automation.PSCredential] - $credentials + $credentials, + + [parameter(Mandatory=$false)] + [switch] + $CustomAuthentication ) $ErrorActionPreference = 'Stop' @@ -48,7 +52,15 @@ function Publish-SSRSSolution{ $ProjectPath = ($ProjectPath | Resolve-Path).ProviderPath #"$ProjectPath" = full path to the project file - & Publish-SSRSProject -path $ProjectPath -configuration $configuration -verbose -credential $credentials + $ProjectParameters = @{ + Path = $ProjectPath + Configuration = $configuration + Credential = $credentials + Verbose = $true + CustomAuthentication = $CustomAuthentication + } + + & Publish-SSRSProject @ProjectParameters } }