rvr.connectivityanalysis.psm1

Function Get-LogAnalyticsSignature {

    <#
    .SYNOPSIS
        Returns a shared key
    .DESCRIPTION
        This function returns a shared key that is needed by the Export-LogAnalytics function.
        You should not use this function manually.

    .NOTES
        This code was copied from https://docs.microsoft.com/en-us/azure/log-analytics/log-analytics-data-collector-api
        I've modified it here and there.
    #>


    [cmdletbinding()]
    Param (
        $customerId,
        $sharedKey,
        $date,
        $contentLength,
        $method,
        $contentType,
        $resource
    )
    $xHeaders = "x-ms-date:" + $date
    $stringToHash = $method + "`n" + $contentLength + "`n" + $contentType + "`n" + $xHeaders + "`n" + $resource

    $bytesToHash = [Text.Encoding]::UTF8.GetBytes($stringToHash)
    $keyBytes = [Convert]::FromBase64String($sharedKey)

    $sha256 = New-Object System.Security.Cryptography.HMACSHA256
    $sha256.Key = $keyBytes
    $calculatedHash = $sha256.ComputeHash($bytesToHash)
    $encodedHash = [Convert]::ToBase64String($calculatedHash)
    $authorization = 'SharedKey {0}:{1}' -f $customerId,$encodedHash
    return $authorization
}

Function Export-LogAnalytics {
    <#
    .SYNOPSIS
        Exports a record to Azure Log Analytics
    .DESCRIPTION
        This function exports a record to Azure Log Analytics. You should not use this function manually as
        it's being used by the function 'Start-RVRConectionAnalysis'.

    .NOTES
        This code was copied from https://docs.microsoft.com/en-us/azure/log-analytics/log-analytics-data-collector-api
        I've modified it here and there.
    #>


    [cmdletbinding()]
    Param(
        $customerId,
        $sharedKey,
        $object,
        $logType,
        $TimeStampField
    )
    $bodyAsJson = ConvertTo-Json $object
    $body = [System.Text.Encoding]::UTF8.GetBytes($bodyAsJson)

    $method = "POST"
    $contentType = "application/json"
    $resource = "/api/logs"
    $rfc1123date = [DateTime]::UtcNow.ToString("r")
    $contentLength = $body.Length

    $signatureArguments = @{
        CustomerId = $customerId
        SharedKey = $sharedKey
        Date = $rfc1123date
        ContentLength = $contentLength
        Method = $method
        ContentType = $contentType
        Resource = $resource
    }

    $signature = Get-LogAnalyticsSignature @signatureArguments

    $uri = "https://" + $customerId + ".ods.opinsights.azure.com" + $resource + "?api-version=2016-04-01"

    $headers = @{
        "Authorization" = $signature;
        "Log-Type" = $logType;
        "x-ms-date" = $rfc1123date;
        "time-generated-field" = $TimeStampField;
    }

    $response = Invoke-WebRequest -Uri $uri -Method $method -ContentType $contentType -Headers $headers -Body $body -UseBasicParsing
    return $response.StatusCode
}

Function Start-RVRConectionAnalysis {

    <#
    .SYNOPSIS
        Pings a node and exports the ping result to Azure Log Analytics.
    .DESCRIPTION
        Pings a node and exports the ping result to Azure Log Analytics.
    .EXAMPLE
        PS > Start-RVRConectionAnalysis -WorkspaceID 33720c95-e898-4900-XXX-XXX -SharedKey xoDpWNb...

        Destination: nu.nl

        Ping Source Address Latency BufferSize Status
                                                        (ms) (B)
        ---- ------ ------- ------- ---------- ------
        1 ubuntu-dida99v7… 99.84.11.113 19 32 Success
        2 ubuntu-dida99v7… 99.84.11.113 19 32 Success
        3 ubuntu-dida99v7… 99.84.11.113 19 32 Success
        4 ubuntu-dida99v7… 99.84.11.113 22 32 Success
    .PARAMETER WorkspaceID
        The unique ID of the Azure Workspace.
    .PARAMETER SharedKey
        The shared key of the Workspace.

    .PARAMETER pingCount
        The count of pings to perform
    #>


    [cmdletbinding(SupportsShouldProcess)]

    param(
        [parameter(Mandatory)]
        [string]
        $WorkspaceID,

        [parameter(Mandatory)]
        [string]
        $SharedKey,

        [int]
        $pingCount = 5,

        [string]
        $pingTarget = 'nu.nl'
    )

    Begin{
        Write-Verbose "$($MyInvocation.InvocationName) $( Get-date -Format dd-MM-yyyy_hh:mm ): Starting "

        # LogAnalytics splashed arguments
        $logAnalyticsParams = @{
            CustomerId = $WorkspaceID
            SharedKey = $SharedKey
            TimeStampField = "CollectionTime"
            LogType = "PingTest"
        }
    }

    Process {

        # Perform the actual ping
        Test-Connection -ComputerName $pingTarget -Count $pingCount | ForEach-Object {

            # Return result to default stream (display in your console)
            $_

            # The properties to export to Azure LogAnalytics
            $recordProperty = [ordered]@{

                Source              = $_.Source
                Destination         = $_.Destination
                Address             = $_.Address
                DisplayAddress      = $_.DisplayAddress
                Latency             = $_.Latency
                Status              = $_.Status
                IsLinux             = $IsLinux
                IsWindows           = $IsWindows
                IsMacos             = $IsMacOS
                uptime              = ( Get-RVRUptime ).hours
            }

            $record = New-Object -TypeName psobject -Property $recordProperty

            # Add the results to Azure log analytics
            Export-LogAnalytics @logAnalyticsParams $record -ErrorAction Continue | Out-Null

            <#
                This part still requires a bit of love and labor (I'm told by my ex there is no difference between the two ;-) ).

                Errors thrown by the Export-LogAnalytics should be caught and handled. I'll leave this to your expertise or add
                this later on.
            #>

        }
    }

    End{
        Write-Verbose "$($MyInvocation.InvocationName) $( get-date -Format dd-MM-yyyy_hh:mm ): Ending "
    }
}