Forum Discussion

Mark_Hensler's avatar
4 years ago

PowerShell SDK

I am requesting a PowerShell SDK to compliment the current list of SDKs offered for Python and GO.

3 Replies

  • Here's a bit of PS that goes at the head of my scripts for RESTAPI work... uses Credential Manager 2.0 with the restAPI user/key stored in  the windows cred store:

    Import-Module     CredentialManager
    
    function          Send-Request               {
        param (
            $cred               ,
            $URL                ,
            $accessid    = $null,
            $accesskey   = $null,
            $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
        try {
            $response        = Invoke-RestMethod  `
                -Uri             $URL             `
                -Method          $httpVerb        `
                -Body            $data            `
                -Header          $headers         `
                -erroraction     stop `
                -warningaction   SilentlyContinue
        } catch {
            $response    = -1
        }
        Return $response
    }
    
    function          Get-LMRestAPIObjectListing {
        param (
            $URLBase          ,
            $resourcePathRoot , # "/device/devices"
            $size = 1000      ,
            $accessKey        ,
            $accessId         ,
            $version = '2'
        )
    
        write-host "Gathering $resourcePathRoot"
    
        $output  = @()
        $looping = $true
        $counter = 0
    
        # write-host "Gathering data from $resourcePathRoot"
        while ($looping) {
    
            # Re-calc offset based on iteration
            $offset = $counter * $size
            $resourcePath    = $resourcePathRoot
            $queryParam      = "?size=$size&offset=$offset"
            $url             = $URLBase + $resourcePath + $queryParam
    
            # Make Request
            $response        = Send-Request `
                -accesskey    $accessKey    `
                -accessid     $accessId     `
                -URL          $url          `
                -version      $version
            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
        }
    
    $company        = "<CompanyName>"
    $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
    }
    
    # Get Devices
    $resourcePath         = "/device/devices"
    $Devices              = Get-LMRestAPIObjectListing `
        -resourcePathRoot $resourcePath                `
        -accessKey        $accessKey                   `
        -accessId         $accessID                    `
        -URLBase          $URLBase

    I wrote most of it using the standard "Send-Request" piece from LM's docs and the posts here... but added a bit to work around the request limit to allow me to fill a variable with all of the specific piece I'm looking for.  It also allows for storing creds for dev that are also in LM properties for deployment.  They're stored in a generic windows credential named "LogicMonitor" locally.

    To expand what it does, change or duplicate the "Get Devices" section to target a different $resourcePath from the swagger doc for the restAPI.

    DISCLAIMER: this code comes with no guarantees from myself or my employers past and present that it is safe in your environment.  Use it with caution as you always should.

Recent Discussions