Public/Invoke-nbApi.ps1
<#
.SYNOPSIS Invokes the Netbox API .DESCRIPTION This wraps the netbox API to make it a little simpler to work with in powershell. .EXAMPLE #Get devices from site 1 Invoke-nbApi -Resource dcim/racks -Query @{site_id=1} -APIurl https://nb.contoso.com/ -token asd1239asd13lsdfs #> function Invoke-nbApi { [CmdletBinding(DefaultParameterSetName = 'resource')] [Alias("inb")] Param ( # The resource path to connect to [Parameter(Mandatory = $true, Position = 0, ParameterSetName = 'resource')] [String] $Resource, # The HTTP verb to use for this request [Parameter(ParameterSetName = 'resource')] [Alias("Verb")] [Microsoft.PowerShell.Commands.WebRequestMethod] $HttpVerb = "Get", #Dictionary to be constructed into a QueryString [Parameter(ParameterSetName = 'resource')] [hashtable] $Query, #Body of the request [Parameter(ParameterSetName = 'resource')] [Parameter(ParameterSetName = 'rawurl')] [Object] $Body, # URL to run it against (for unauthenticated get requests) [Parameter(ParameterSetName = 'resource')] [uri] $APIUrl, [Parameter(ParameterSetName = 'rawurl')] [uri] $rawUrl ) begin { if ($PSCmdlet.ParameterSetName -eq 'resource') { #make this easier to refer to (eventually we'll use using statements) $get = $HttpVerb -eq [Microsoft.PowerShell.Commands.WebRequestMethod]::Get #allow overriding the connection for unauthenticated get requests $_apiurl = if ($Script:APIUrl) { $Script:APIUrl } elseif ($get -and $APIUrl) { $APIUrl } else { $False } if (!$get -and (!$_apiurl -or !$Script:Token)) { $errorRecord = New-Object System.Management.Automation.ErrorRecord( (New-Object Exception "You must connect (using Connect-nbApi) before using this module"), 'Not.Connected', [System.Management.Automation.ErrorCategory]::ConnectionError, $Resource ) $PSCmdlet.ThrowTerminatingError($errorRecord) } if ($get -and !$_apiurl) { $errorRecord = New-Object System.Management.Automation.ErrorRecord( (New-Object Exception "You must specify APIUrl or connect (using Connect-nbApi)"), 'No.Url', [System.Management.Automation.ErrorCategory]::ConnectionError, $Resource ) $PSCmdlet.ThrowTerminatingError($errorRecord) } if ($null -ne $Body -and $Body.GetType().FullName -eq [hashtable].FullName) { Write-Verbose -Message "Converting the hashtable body into an object" $Body = [PSCustomObject]$Body } } } process { if ($PSCmdlet.ParameterSetName -eq 'resource') { if (-not $Query) { $Query = @{} } $Query["format"] = "json" $QueryString = "" #Format a hashtable to key=value&key2=value2 format. $QueryString = ( $Query.Keys | ForEach-Object { "{0}={1}" -f $_, $Query[$_] } ) -join '&' $Resource = "$($Resource.Trim('/'))/" #construct the uri $URI = new-Object UriBuilder -Property @{ Scheme = $_APIUrl.Scheme Host = $_APIUrl.DnsSafeHost Path = $_APIUrl.LocalPath.TrimEnd('/') + '/' + $Resource Query = $QueryString Port = $_APIUrl.Port } } else { $URI = [UriBuilder]::new($rawUrl) } #make this easier to refer to $marshal = [System.Runtime.InteropServices.Marshal] try { <# Code for SecureString to String https://blogs.msdn.microsoft.com/fpintos/2009/06/12/how-to-properly-convert-securestring-to-string/ #> $Params = @{ Uri = $URI.Uri Method = $HttpVerb UserAgent = "NB-{0}-PowerShell" -f $ENV:USERNAME ContentType = 'application/json' Body = $Body ###TimeoutSec ###MaximumRedirection ###TransferEncoding } Write-Debug -Message ($params | ConvertTo-Json) if ($Script:Token) { $unmanagedString = $marshal::SecureStringToGlobalAllocUnicode($Script:Token) $Params['Headers'] = @{ Authorization = "token {0}" -f $marshal::PtrToStringUni($unmanagedString) } } #splat the paramaters into Invoke-Restmethod $Response = Invoke-RestMethod @Params ###Write-Verbose "Status $($Response.status)" ###if ($Response.status -ne 200) ###{ ### Write-Error -Message "Call to NB failed! $($Response.errmsg)" -ErrorId $Response.status ###} $Response } catch { ## I'm going to stop trying to be fancy. ## The error that irm throws is better then what I was trying to do. $PSCmdlet.ThrowTerminatingError($_) } finally { if ($null -ne $unmanagedString) { # Clean up the insecure stuff $marshal::ZeroFreeGlobalAllocUnicode($unmanagedString) Remove-Variable unmanagedString -Force -ErrorAction SilentlyContinue Remove-Variable Params -Force -ErrorAction SilentlyContinue } } } end { } } |