tools/unicorn/Unicorn.psm1 (106 lines of code) (raw):
$ErrorActionPreference = 'Stop'
$ScriptPath = Split-Path $MyInvocation.MyCommand.Path
$MicroCHAP = $ScriptPath + '\MicroCHAP.dll'
Add-Type -Path $MicroCHAP
Function Sync-Unicorn {
Param(
[Parameter(Mandatory=$True)]
[string]$ControlPanelUrl,
[Parameter(Mandatory=$True)]
[string]$SharedSecret,
[string[]]$Configurations,
[string]$Verb = 'Sync',
[string]$basicAuth,
[switch]$SkipTransparentConfigs,
[switch]$DebugSecurity = $True
)
# PARSE THE URL TO REQUEST
$parsedConfigurations = '' # blank/default = all
if($Configurations) {
$parsedConfigurations = ($Configurations) -join "^"
}
$skipValue = 0
if($SkipTransparentConfigs) {
$skipValue = 1
}
$url = "{0}?verb={1}&configuration={2}&skipTransparentConfigs={3}" -f $ControlPanelUrl, $Verb, $parsedConfigurations, $skipValue
if($DebugSecurity) {
Write-Host "Sync-Unicorn: Preparing authorization for $url"
}
# GET AN AUTH CHALLENGE
$challenge = Get-Challenge -ControlPanelUrl $ControlPanelUrl -BasicAuth $basicAuth
if($DebugSecurity) {
Write-Host "Sync-Unicorn: Received challenge from remote server: $challenge"
}
# CREATE A SIGNATURE WITH THE SHARED SECRET AND CHALLENGE
$signatureService = New-Object MicroCHAP.SignatureService -ArgumentList $SharedSecret
$signature = $signatureService.CreateSignature($challenge, $url, $null)
if($DebugSecurity) {
Write-Host "Sync-Unicorn: MAC '$($signature.SignatureSource)'"
Write-Host "Sync-Unicorn: HMAC '$($signature.SignatureHash)'"
Write-Host "Sync-Unicorn: If you get authorization failures compare the values above to the Sitecore logs."
}
Write-Host "Sync-Unicorn: Executing $Verb..."
# USING THE SIGNATURE, EXECUTE UNICORN
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
$result = Invoke-StreamingWebRequest -Uri $url -Mac $signature.SignatureHash -Nonce $challenge -BasicAuth $basicAuth
if($result.TrimEnd().EndsWith('****ERROR OCCURRED****')) {
throw "Unicorn $Verb to $url returned an error. See the preceding log for details."
}
# Uncomment this if you want the console results to be returned by the function
$result
}
Function Get-Challenge {
Param(
[Parameter(Mandatory=$True)]
[string]$ControlPanelUrl,
[Parameter(Mandatory=$False)]
[string]$BasicAuth = ""
)
$url = "$($ControlPanelUrl)?verb=Challenge"
$headers = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"
if (![string]::IsNullOrEmpty($BasicAuth)) {
$encodedCreds = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes($BasicAuth))
$headers.Add("Authorization", "Basic $encodedCreds")
}
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
$result = Invoke-WebRequest -Uri $url -TimeoutSec 360 -UseBasicParsing -Headers $headers
$result.Content
}
Function Invoke-StreamingWebRequest($Uri, $MAC, $Nonce, $BasicAuth) {
$responseText = new-object -TypeName "System.Text.StringBuilder"
$request = [System.Net.WebRequest]::Create($Uri)
$request.Headers["X-MC-MAC"] = $MAC
$request.Headers["X-MC-Nonce"] = $Nonce
if (![string]::IsNullOrEmpty($BasicAuth)) {
$encodedCreds = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes($BasicAuth))
$request.Headers.Add("Authorization", "Basic $encodedCreds")
Write-Host($Uri)
Write-Host($request.Headers["Authorization"].Replace($encodedCreds, "*"*$encodedCreds.Length))
}
$request.Timeout = 10800000
$response = $request.GetResponse()
$responseStream = $response.GetResponseStream()
$responseStreamReader = new-object System.IO.StreamReader $responseStream
while(-not $responseStreamReader.EndOfStream) {
$line = $responseStreamReader.ReadLine()
if($line.StartsWith('Error:')) {
Write-Host $line.Substring(7) -ForegroundColor Red
}
elseif($line.StartsWith('Warning:')) {
Write-Host $line.Substring(9) -ForegroundColor Yellow
}
elseif($line.StartsWith('Debug:')) {
Write-Host $line.Substring(7) -ForegroundColor Gray
}
elseif($line.StartsWith('Info:')) {
Write-Host $line.Substring(6) -ForegroundColor White
}
else {
Write-Host $line -ForegroundColor White
}
[void]$responseText.AppendLine($line)
}
return $responseText.ToString()
}
Export-ModuleMember -Function Sync-Unicorn