Forum Discussion

Cole_McDonald's avatar
Cole_McDonald
Icon for Professor rankProfessor
6 years ago

REST API full resource path listings in powershell

#!!! Requires Credential Manager 2.0 from the repository !!!#

Import-Module     CredentialManager

function          Send-Request               {
    param (
        $cred,
        $accessid    = $null,
        $accesskey   = $null,
        $URL                ,
        $data        = $null,
        $version     = '2'  ,
        $httpVerb    = "GET"
    )

    if ( $accessId -eq $null) {
        $accessId    = $cred.UserName
        $accessKey   = $cred.GetNetworkCredential().Password
    }

    <# Use TLS 1.2 #>
    [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12

    <# Get current time in milliseconds #>
    $epoch           = [Math]::Round(
        ( New-TimeSpan `
            -start (Get-Date -Date "1/1/1970") `
            -end (Get-Date).ToUniversalTime()).TotalMilliseconds
        )

    <# Concatenate Request Details #>
    $requestVars     = $httpVerb + $epoch + $data + $resourcePath

    <# Construct Signature #>
    $hmac            = New-Object System.Security.Cryptography.HMACSHA256
    $hmac.Key        = [Text.Encoding]::UTF8.GetBytes( $accessKey )
    $signatureBytes  = $hmac.ComputeHash( [Text.Encoding]::UTF8.GetBytes( $requestVars ) )
    $signatureHex    = [System.BitConverter]::ToString( $signatureBytes ) -replace '-'
    $signature       = [System.Convert]::ToBase64String( [System.Text.Encoding]::UTF8.GetBytes( $signatureHex.ToLower() ) )

    <# Construct Headers #>
    $auth            = 'LMv1 ' + $accessId + ':' + $signature + ':' + $epoch
    $headers         = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"
    $headers.Add(      "Authorization", $auth              )
    $headers.Add(      "Content-Type" , 'application/json' )

    # uses version 2 of the API
    $headers.Add(      "X-version"    , $version           )

    <# Make Request #>
    $response        = Invoke-RestMethod `
        -Uri           $URL      `
        -Method        $httpVerb `
        -Body          $data     `
        -Header        $headers

    $result          = $response

    Return $result
}
function          Get-LMRestAPIObjectListing {
    param (
        $URLBase          ,
        $resourcePathRoot , # "/device/devices"
        $size = 1000      ,
        $accessKey        ,
        $accessId
    )

    $output  = @()
    $looping = $true
    $counter = 0

    while ($looping) {
        #re-calc offset based on iteration
        $offset = ($counter * $size) + 1

        $resourcePath    = $resourcePathRoot
        $queryParam      = "?size=$size&offset=$offset"
        $url             = $URLBase + $resourcePath + $queryParam

        # Make Request
        $response        = Send-Request `
            -accesskey    $accessKey    `
            -accessid     $accessId     `
            -URL          $url

        if ( $response.items.count -eq $size ) {
            # Return set is full, more items to retrieve
            $output     += $response.items
            $counter++

        } elseif ( $response.items.count -gt 0 ) {
            # Return set is not full, store date, end loop
            $output     += $response.items
            $looping     = $false

        } else {
            # Return set is empty, no data to store, end loop
            $looping     = $false

        }
    }

    write-output $output
}

#!!! Change to your company name !!!#
$company        = "yourCompanyHere"
$URLBase        = "https://$company.logicmonitor.com/santaba/rest"

# This will resolve to proper values if it's being run from inside LM
$accessID       = "##Logicmonitor.AccessID.key##"
$accessKey      = "##Logicmonitor.AccessKey.key##"

if ( $accessID -like "##*" )       {
    # Not being run from inside LM - populate manually for testing
    Import-Module     CredentialManager

    $Cred       = Get-StoredCredential -Target LogicMonitor
    $accessID   = $cred.UserName
    $accessKey  = $Cred.GetNetworkCredential().Password
}

#region Get collectors
$resourcePath   = "/setting/collector/collectors"

$collectors     = Get-LMRestAPIObjectListing `
    -resourcePathRoot $resourcePath          `
    -accessKey        $accessKey             `
    -accessId         $accessID              `
    -URLBase          $URLBase

#endregion

As always, code provided without warranty by myself nor Beyond Impact 2.0, LLC, use with caution.

Just change the resource path to the piece you want and it'll dump the whole list to your variable... in this case, $collectors.

  • I have an error in the Get-LMRestAPIObjectListing function.  I'm calculating the offset as:

    $offset = ($counter * $size) + 1

    it should be:

    $offset = $counter * $size

    Adding 1 at the outset was skipping item 0 - rookie mistake ;)