Deploy Sitecore Connect for Content Hub in an existing PaaS environment

Abstract

How to deploy the Sitecore Connect for Content Hub connector in an existing Azure PaaS environment.

This topic explains how to install Sitecore Connect for Content Hub in an existing Azure PaaS Environment.

Note

If you are deploying a new Sitecore Azure PaaS environment, use the instructions in Deploy Sitecore Connect for Content Hub in a new PaaS environment instead.

To use this method you must have:

To prepare an installation folder:

  1. Create a local folder in your file system, for example, C:\Temp\SCCHInstallation.

  2. Download the Sitecore Connect for Content Hub WDP Package from the Sitecore download page and store it in the local folder you created.

  3. In the local folder, create a new file and name it Deploy.ps1.

  4. Open the new file with an editor such as notepad or VS Code and paste the following script inside:

    [CmdletBinding(DefaultParameterSetName = "no-arguments")]
    param(
        [Parameter(HelpMessage = "Name of the resource group in Azure to target.")]
        [string]$ResourceGroupName,
    
        [Parameter(HelpMessage = "Name of the web app in Azure to target.")]
        [string]$WebAppName,
    
        [Parameter(HelpMessage = "Path to the WDP to deploy to the target.")]
        [string]$WdpPackagePath,
    
        [Parameter(HelpMessage = "Content Hub Client Id.")]
        [string]$CHClientId,
    
        [Parameter(HelpMessage = "Content Hub Client Secret.")]
        [string]$CHClientSecret,
    
        [Parameter(HelpMessage = "Content Hub Username.")]
        [string]$CHUserName,
    
        [Parameter(HelpMessage = "Content Hub Password.")]
        [string]$CHPassword,
    
        [Parameter(HelpMessage = "Content Hub URI.")]
        [string]$CHUri,
    
        [Parameter(HelpMessage = "Content Hub Azure Service Bus connection string path in.")]
        [string]$CHServiceBusEntityPathIn,
    
        [Parameter(HelpMessage = "Content Hub Subscription name. (must be unique per Sitecore CM deployment)")]
        [string]$CHServiceBusSubscription,
    
        [Parameter(HelpMessage = "Content Hub Azure Service Bus connection string path out.")]
        [string]$CHServiceBusEntityPathOut,
    
        [Parameter(HelpMessage = "Content Hub Search Page Uri.")]
        [string]$CHSearchPage,
    
        [Parameter(HelpMessage = "Content Hub External Redirect Key.")]
        [string]$CHExternalRedirectKey = "Sitecore",
    
        [Parameter(HelpMessage = "Path to MSDeploy.")]
        [string]$MsDeployPath = "C:\Program Files\IIS\Microsoft Web Deploy V3\msdeploy.exe",
    
        [Parameter(HelpMessage = "Skips Azure Login when True.")]
        [switch]$SkipAzureLogin = $False,
    
        [Parameter(HelpMessage = "Amount of retry attempts. 6 by default which with default retryinterval would come down to 1 minute.")]
        [int]$RetryAttempts = 6,
    
        [Parameter(HelpMessage = "Amount of time to wait between retries in milliseconds. 10000 by default which is 10 seconds which adds up to 1 minute with default retry attempts.")]
        [int]$RetryInterval = 10000
    )
    
    Add-Type -AssemblyName "System.IO.Compression.FileSystem"
    
    function PreparePath($path) {
        if(-Not (Test-Path $path)) {
            $result = New-Item -Path $path -Type Directory -Force
        } else {
            $result = Resolve-Path $path
        }
    
        return $result
    }
    
    function UnzipFolder($zipfile, $folder, $dst) {
        [IO.Compression.ZipFile]::OpenRead($zipfile).Entries | Where-Object {
            ($_.FullName -like "$folder/*") -and ($_.Length -gt 0)
        } | ForEach-Object {
            $parent = Split-Path ($_.FullName -replace $folder, '')
            $parent = PreparePath (Join-Path $dst $parent)
            $file = Join-Path $parent $_.Name
            [IO.Compression.ZipFileExtensions]::ExtractToFile($_, $file, $true)
        }
    }
    
    function DownloadWebsiteFile($filePath, $downloadFolderName) {
        $basePath = Split-Path ".\$downloadFolderName\$filePath"
        $fileName = Split-Path $filePath -Leaf
        if(-Not (Test-Path ".\$downloadFolderName\$filePath")) {
            New-Item -Path $basePath -Type Directory -Force
        }
        $outFilePath = Join-Path (Resolve-Path "$basePath") $fileName
        Invoke-WebRequest -Uri "https://$WebAppName.scm.azurewebsites.net/api/vfs/site/wwwroot/$filePath" -Headers @{"Authorization"=("Basic {0}" -f $base64AuthInfo)} -Method GET -OutFile $outFilePath
    }
    
    function UploadWebsiteFile($filePath, $uploadFilePath) {
        Invoke-WebRequest -Uri "https://$WebAppName.scm.azurewebsites.net/api/vfs/site/wwwroot/$filePath" -Headers @{"Authorization"=("Basic {0}" -f $base64AuthInfo);"If-Match"="*"} -Method PUT -InFile $uploadFilePath
    }
    
    function ApplyTransform($filePath, $xdtFilePath) {
        Write-Verbose "Applying XDT transformation '$xdtFilePath' on '$filePath'..."
    
        $target = New-Object Microsoft.Web.XmlTransform.XmlTransformableDocument;
        $target.PreserveWhitespace = $true
        $target.Load($filePath);
        
        $transformation = New-Object Microsoft.Web.XmlTransform.XmlTransformation($xdtFilePath);
        
        if ($transformation.Apply($target) -eq $false)
        {
            throw "XDT transformation failed."
        }
        
        $target.Save($filePath);
    }
    
    if(-Not (Test-Path $MsDeployPath)) {
        Write-Host "MS Deploy was not found at `"$MsDeployPath`"!" -ForegroundColor Red
        return
    }
    
    if(-Not $SkipAzureLogin) {
        Write-Host "Logging into Azure..." -ForegroundColor Green
        & az login
    }
    
    
    Write-Host "Fetching Publish Profile..." -ForegroundColor Green
    $publishProfile = az webapp deployment list-publishing-profiles --resource-group $ResourceGroupName --name $WebAppName --query "[?publishMethod=='MSDeploy']" | ConvertFrom-Json
    $userName = $publishProfile.userName
    $password = $publishProfile.userPWD
    $base64AuthInfo = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f $userName, $password)))
    
    
    Write-Host "Preparing configuration..." -ForegroundColor Green
    $xdtsPath = (PreparePath ".\xdts")
    UnzipFolder $WdpPackagePath "Content/Website/App_Data/Transforms/scch/xdts" $xdtsPath
    Get-ChildItem $xdtsPath -File -Include "*.xdt" -Recurse | ForEach-Object {
        $targetWebsiteFile = $_.FullName.Replace("$xdtsPath\", "").Replace("\", "/").Replace(".xdt", "")
        DownloadWebsiteFile $targetWebsiteFile "Configuration"
    }
    $configurationPath = (PreparePath ".\Configuration")
    $currentDateTime = (Get-Date).ToString("dd-MM-yyyy-hh-mm-ss")
    $backupPath = (PreparePath ".\Backup-$currentDateTime")
    robocopy $configurationPath $backupPath /s
    
    
    Write-Host "Preparing transformations..." -ForegroundColor Green
    $nupkgPath = Join-Path (Resolve-Path ".") "microsoft.web.xdt.3.1.0.nupkg"
    $xdtDllBinPath = PreparePath ".\bin"
    Invoke-WebRequest -Uri "https://www.nuget.org/api/v2/package/Microsoft.Web.Xdt/3.1.0" -OutFile $nupkgPath
    UnzipFolder $nupkgPath "lib/netstandard2.0" $xdtDllBinPath
    Add-Type -Path (Resolve-Path ".\bin\Microsoft.Web.XmlTransform.dll")
    
    
    Write-Host "Fill ConnectionStrings..." -ForegroundColor Green
    $connectionStringsXdtPath = Join-Path $xdtsPath "App_Config\ConnectionStrings.config.xdt"
    ((Get-Content -Path $connectionStringsXdtPath -Raw).Replace("{client_id}", $CHClientId).Replace("{client_secret}", $CHClientSecret).Replace("{username}", $CHUserName).Replace("{password}", $CHPassword).Replace("{uri}", $CHUri).Replace("{Azure Service Bus connection string with incoming topic}", $CHServiceBusEntityPathIn).Replace("{Subscription name}", $CHServiceBusSubscription).Replace("{Azure Service Bus connection string with outcoming topic}", $CHServiceBusEntityPathOut).Replace("{Content Hub search page URI}", $CHSearchPage).Replace("{External redirect key}", $CHExternalRedirectKey)) | Set-Content -Path $connectionStringsXdtPath
    
    
    Write-Host "Running transformations..." -ForegroundColor Green
    Get-ChildItem $xdtsPath -File -Include "*.xdt" -Recurse | ForEach-Object {
        $targetFilePath = $_.FullName.Replace($xdtsPath, $configurationPath).Replace(".xdt", "")
        if (-not(Test-Path $targetFilePath -PathType Leaf)) {
            Write-Verbose "No matching file '$targetFilePath' for transformation '$($_.FullName)'. Skipping..."
        } else {
            ApplyTransform $targetFilePath $_.FullName
        }
    }
    
    
    Write-Host "Starting MSDeploy..." -ForegroundColor Green
    $verb = "-verb:sync"
    $source = "-source:package=`"$WdpPackagePath`""
    $dest = "-dest:auto,ComputerName=`"https://$WebAppName.scm.azurewebsites.net/msdeploy.axd?site=$WebAppName`",UserName=`"$userName`",Password=`"$password`",AuthType=`"Basic`""
    $iisWebAppParam = "-setParam:name=`"IIS Web Application Name`",value=`"$WebAppName`""
    $coreParam = "-setParam:name=`"Core Admin Connection String`",value=`"notUsed`""
    $masterParam = "-setParam:name=`"Master Admin Connection String`",value=`"notUsed`""
    $skipDbFullSql = "-skip:objectName=dbFullSql"
    $skipDbDacFx = "-skip:objectName=dbDacFx"
    $doNotDeleteRule = "-enableRule:DoNotDeleteRule"
    $appOfflineRule = "-enableRule:AppOffline"
    $retryAttemptsParam = "-retryAttempts:$RetryAttempts"
    $retryIntervalParam = "-retryInterval:$RetryInterval"
    $verboseParam = "-verbose"
    Invoke-Expression "& '$MsDeployPath' --% $verb $source $dest $iisWebAppParam $coreParam $masterParam $skipDbFullSql $skipDbDacFx $doNotDeleteRule $appOfflineRule $retryAttemptsParam $retryIntervalParam $verboseParam"
    
    
    Write-Host "Uploading configuration..." -ForegroundColor Green
    Get-ChildItem $configurationPath -File -Recurse | ForEach-Object {
        $targetWebsiteFile = $_.FullName.Replace("$configurationPath\", "").Replace("\", "/")
        UploadWebsiteFile $targetWebsiteFile $_.FullName
    }
    
  5. Save and close the file.

To successfully run the script and install and configure the connector you must prepare the following information:

  • Resource Group Name - the resource group name in Azure you want to install to.

  • Web App Name - the name of the Web App in Azure you want to install to.

  • Content Hub Client ID and Client Secret - a Content Hub OAuth Client ID and Client Secret. (See Create an OAuth client for how to create these).

  • Content Hub Username and Password - a Content Hub username and password that is used as the identification of Sitecore to access Content Hub.

  • Content Hub Instance URI - the URI to your Content Hub instance, for example, https://mysandbox.stylelabs.io/.

  • Content Hub Service Bus ConnectionStrings - to find these, in Content Hub, create a new action of the type M Azure Service Bus. Make a note of the connection strings in Hub in and Hub out. For example:

    The Edit action dialog box showing the Hub in and Hub out connection strings
  • Content Hub Search Page URI - the URI to the Search Page you want to use to select DAM Assets, for example, https://mysandbox.stylelabs.io/en-us/sitecore-damconnect/approved-assets.

To run the installation of the connector and apply the configuration:

  1. Open a PowerShell window with administrator access.

  2. Navigate to your local folder. For example:

    cd "C:\Temp\SCCHInstallation"
  3. .\Deploy.ps1 -ResourceGroupName "<MyResourceGroup>" -WebAppName "<MyWebApp>" -WdpPackagePath "C:\Temp\SCCHInstallation\Sitecore.Connector.ContentHub.WDP.5.0.0-r00328.4145.scwdp.zip" -CHClientId "<ClientId>" -CHClientSecret "<ClientSecret>" -CHUserName "<UserName>" -CHPassword "<Password>" -CHUri "https://mysandbox.stylelabs.io/" -CHServiceBusEntityPathIn "<Hub out connectionstring>" -CHServiceBusSubscription "<MySitecoreSubscription>" -CHServiceBusEntityPathOut "<Hub in connectionstring>" -CHSearchPage "https://mysandbox.stylelabs.io/en-us/sitecore-damconnect/approved-assets"

Note

You must run this command against both your CM and your CD Azure PaaS Web Applications.

If you use the DAM functionality in SCCH, you must adjust the Content-Security-Policy tag to allow the connector to select assets from Content Hub. For information on how to do this, see the Configure the DAM connector in Sitecore section in the SCCH installation guide, which you can download from the Sitecore download page.