HornbillAPI.psm1
############################## # Hornbill XMLMC API Azure Powershell Module # #.DESCRIPTION # This module includes functions to allow your Powershell scripts to make and send API calls # to your Hornbill instance, and process responses accordingly. # # Requires Powershell 4.0 or above. # #.NOTES # See example scripts and function documentation for guidance on usage. ############################## # Initialise the module-level variables [string]$script:InstanceName = "" [string]$script:InstanceZone = "" [string]$script:APIKey = "" [string]$script:XMLMCParams = "" [string]$script:InstanceURL = "" ############################## # .SYNOPSIS # Allows you to define the Hornbill instance # #.DESCRIPTION # MANDATORY - Allows your Powershell script to define the Hornbill instance to connect # to, the zone in which it resides, and the API key to use for session generation. # #.PARAMETER Instance # The (case-sensitive) instance name that you wish to connect to. # #.PARAMETER Zone # The (case-sensitive) zone in which the Hornbill instance resides. # If not supplied, script will work out endpoint from zoneinfo # #.PARAMETER Key # The API key to use to generate authenticate against the Hornbill instance with. # #.EXAMPLE # Set-HB-Instance "yourinstancename" "eur" "yourapikeygoeshere" ############################## function Set-HB-Instance { Param( [Parameter(Mandatory = $True, HelpMessage = "Specify the name of the Instance to connect to (case sensitive)")] [ValidateNotNullOrEmpty()] [string]$Instance, [Parameter(Mandatory = $False, HelpMessage = "Specify the Zone in which the Instance is run. Defaults to 'eur' (case sensitive)")] [string]$Zone = "", [Parameter(Mandatory = $True, HelpMessage = "Specify the API Key to authenticate the session against")] [ValidateNotNullOrEmpty()] [string]$Key ) $script:InstanceName = $Instance $script:APIKey = $Key if ($Zone -ne "") { $script:InstanceZone = $Zone $script:InstanceURL = "https://" + $script:InstanceZone + "api.hornbill.com/" + $script:InstanceName + "/xmlmc/" } else { $script:InstanceURL = Get-HB-Endpoint $script:InstanceName } } ############################## # .SYNOPSIS # Returns the API endpoint information for a Hornbill instance # #.DESCRIPTION # Allows your Powershell script to retrieve zone information for your Hornbill instance # #.PARAMETER InstanceID # The (case-sensitive) Instance ID to retrieve zone information from. # #.EXAMPLE # Get-HB-Endpoint "yourinstanceid" ############################## function Get-HB-Endpoint { Param( [Parameter(Mandatory = $True, HelpMessage = "Specify the Instance ID (case sensitive)")] [ValidateNotNullOrEmpty()] [string]$InstanceID ) $ZoneInfoURL = "https://files.hornbill.com/instances/" + $InstanceID + "/zoneinfo" $InstanceZoneInfo = Get-HB-Request-Endpoint $ZoneInfoURL if ($InstanceZoneInfo.Status -eq "ok") { $Endpoint = $InstanceZoneInfo.Endpoint + "xmlmc/" return $Endpoint } else { $ZoneInfoURL = "https://files.hornbill.co/instances/" + $InstanceID + "/zoneinfo" $InstanceZoneInfo = Get-HB-Request-Endpoint $ZoneInfoURL if ($InstanceZoneInfo.Status -eq "ok") { $Endpoint = $InstanceZoneInfo.Endpoint + "xmlmc/" return $Endpoint } } } ############################## # .SYNOPSIS # Returns zone information for a Hornbill instance # #.DESCRIPTION # Allows your Powershell script to retrieve zone information for your Hornbill instance # #.PARAMETER FilesURL # The (case-sensitive) URL to retrieve zone information from. # #.EXAMPLE # Get-HB-ZoneInfo "https://files.hornbill.co/instances/yourinstanceid/zoneinfo" ############################## function Get-HB-Request-Endpoint { Param( [Parameter(Mandatory = $True, HelpMessage = "Specify the Files URL of the Instance to retrieve zone information from (case sensitive)")] [ValidateNotNullOrEmpty()] [string]$FilesURL ) $ResultObject = New-Object PSObject -Property @{ Status = "" Error = "" Endpoint = "" } try { # Build HTTP request headers $headers = @{} $headers["Accept"] = "application/json" # Invoke HTTP request if ($script:ProxyURI -and $script:ProxyURI -ne "") { if ($script:ProxyCreds) { $script:ProxyCreds $r = Invoke-RestMethod -Uri $FilesURL -UseBasicParsing -Method Get -Headers $headers -ErrorAction:Stop -Proxy $script:ProxyURI -ProxyCredential $script:ProxyCreds } else { $r = Invoke-RestMethod -Uri $FilesURL -UseBasicParsing -Method Get -Headers $headers -Proxy $script:ProxyURI -ProxyUseDefaultCredentials } } else { $r = Invoke-RestMethod -Uri $FilesURL -UseBasicParsing -Method Get -Headers $script:headers } # Read and process response $ResultObject.Endpoint = $r.zoneinfo.endpoint $ResultObject.Status = "ok" } catch { # HTTP request failed - return exception in response $ResultObject.Error = $_.Exception $ResultObject.Status = "fail" } return $ResultObject } ############################## # .SYNOPSIS # Define proxy details to connect through # #.DESCRIPTION # If you are using a proxy to connect to the internet, then this function allows you to define # the proxy address and authentication details (where applicable) # #.PARAMETER ProxyAddress # Mandatory - URI of the Proxy server to connect through # #.PARAMETER ProxyCredentials # Either: # - String containing the username to authenticate against the proxy with (will prompt for password) # - A PSCredential object, such as one generated by the Get-Credential cmdlet. # # By not providing this parameter, the module will use the credentials of the current Windows user # #.EXAMPLE # Set-HB-Proxy "http://yourproxyaddress:80/" # The above will route the requests through your proxy, and will authenticate using the current user details # # Set-HB-Proxy "http://yourproxyaddress:80/" "DOMAIN01\User01" # The above will route the requests through your proxy, and will authenticate using "DOMAIN01\User01" account ############################## function Set-HB-Proxy { Param( [Parameter(Mandatory = $True, HelpMessage = "Specify the address of your Proxy")] [ValidateNotNullOrEmpty()] [string]$ProxyAddress, [Parameter(Mandatory = $False, HelpMessage = "Specify the credentials to authenticate against your Proxy")] [System.Management.Automation.PSCredential] [System.Management.Automation.CredentialAttribute()] $ProxyCredentials ) $script:ProxyURI = $ProxyAddress if ($ProxyCredentials) { $script:ProxyCreds = $ProxyCredentials } } ############################## # .SYNOPSIS # Add a parameter to the XMLMC request # #.DESCRIPTION # Add a parameter to the XMLMC request # #.PARAMETER ParamName # Mandatory - the name of the parameter # #.PARAMETER ParamValue # Mandatory - the [string] value of the parameter # #.PARAMETER ParamAllowEmpty # Boolean, allow empty string to be passed as a parameter value # #.PARAMETER ParamAttribs # Any attributes to add to the XMLMC request # #.EXAMPLE # Add-HB-Param "application" "com.hornbill.servicemanager" # Add-HB-Param "h_class" "computer" "onError=""omitElement"" " # # Note the escaped double-quotes in the ParamAttribs string. ############################## function Add-HB-Param { Param( [Parameter(Mandatory = $True, HelpMessage = "Specify the name of the Parameter to add")] [ValidateNotNullOrEmpty()] [string]$ParamName, [Parameter(Mandatory = $False, HelpMessage = "Specify the Value of the Parameter")] [string]$ParamValue = "", [Parameter(Mandatory = $False, HelpMessage = "Specify attributes to add to the Parameter XML node")] [boolean]$ParamAllowEmpty = $False, [Parameter(Mandatory = $False, HelpMessage = "Specify attributes to add to the Parameter XML node")] [string]$ParamAttribs = "" ) if ($ParamName.length -eq 0) { return "Parameter name length needs to be greater than zero" } if (-not $ParamAllowEmpty -And $ParamValue -eq "") { return } $EncodedParamVal = "" if ($ParamValue -ne "") { $EncodedParamVal = [System.Security.SecurityElement]::Escape($ParamValue) } $CurrentParam = "<" + $ParamName if ($ParamAttribs -and $ParamAttribs.length -gt 0) { $CurrentParam = $CurrentParam + " " + $ParamAttribs } $CurrentParam = $CurrentParam + ">" + $EncodedParamVal + "</" + $ParamName + ">" $script:XMLMCParams = $script:XMLMCParams + $CurrentParam } ############################## # .SYNOPSIS # Open a new XML element # #.DESCRIPTION # Allows for the building of complex XML # #.PARAMETER Element # The name of the complex element to open # #.EXAMPLE # Open-HB-Element "primaryEntityData" ############################## function Open-HB-Element { Param( [Parameter(Mandatory = $True, HelpMessage = "Specify the name of the Parameter to add")] [ValidateNotNullOrEmpty()] [string]$Element ) $script:XMLMCParams = $script:XMLMCParams + "<" + $Element + ">" } ############################## # .SYNOPSIS # Close an already open XML element # #.DESCRIPTION # Allows for the building of complex XML # #.PARAMETER Element # The name of the complex element to close # #.EXAMPLE # Close-HB-Element "primaryEntityData" ############################## function Close-HB-Element { Param( [Parameter(Mandatory = $True, HelpMessage = "Specify the name of the Parameter to add")] [ValidateNotNullOrEmpty()] [string]$Element ) $script:XMLMCParams = $script:XMLMCParams + "</" + $Element + ">" } ############################## # .SYNOPSIS # Return XML parameters # #.DESCRIPTION # Returns XML string of parameters that have been added by Add-HB-Params, Open-HB-Element or Close-HB-Element # #.EXAMPLE # Get-HB-Params ############################## function Get-HB-Params { if ($script:XMLMCParams.length -gt 0) { return "<params>" + $script:XMLMCParams + "</params>" } return "" } ############################## # .SYNOPSIS # Clear existing XML parameters # #.DESCRIPTION # Clears any existing XMLMC parameters that have been added # #.EXAMPLE # Clear-HB-Params ############################## function Clear-HB-Params { $script:XMLMCParams = "" } ############################## # .SYNOPSIS # Base64 encode a string # #.DESCRIPTION # Returns a Base64 encoded string from a given UTF8 string # #.PARAMETER StringVal # The string to encode # #.EXAMPLE # ConvertTo-HB-B64Encode "encode this please" ############################## function ConvertTo-HB-B64Encode { Param( [Parameter(Mandatory = $True, HelpMessage = "Specify the string to Base-64 encode")] [ValidateNotNullOrEmpty()] [string]$StringVal ) $UnencodedBytes = [System.Text.Encoding]::UTF8.GetBytes($StringVal) $EncodedText = [Convert]::ToBase64String($UnencodedBytes) return $EncodedText } ############################## # .SYNOPSIS # Decode a Base64 encoded string # #.DESCRIPTION # Returns a UTF8 string from a given Base64 endcoded string # #.PARAMETER StringVal # The string to decode # #.EXAMPLE # ConvertTo-HB-B64Decode "ZW5jb2RlIHRoaXMgcGxlYXNl" ############################## function ConvertTo-HB-B64Decode { Param( [Parameter(Mandatory = $True, HelpMessage = "Specify the Base-64 string to decode")] [ValidateNotNullOrEmpty()] [string]$B64Val ) $DecodedString = [System.Text.Encoding]::UTF8.GetString([Convert]::FromBase64String($B64Val)) return $DecodedString } ############################## # .SYNOPSIS # Invokes the XMLMC API call # #.DESCRIPTION # Takes the API Service and Method as inputs to this function, and any parameters # added with Add-HB-Param, Open-HB-Element or Close-HB-Element, and invokes an API call using # the instance details defined with the Set-Instance function. # # Returns a Powershell Object containing: # .status - the status of the API call or HTTP response # .params - any returned parameters from the API # .error - any returned errors if the HTTP request or API call fails # #.PARAMETER XMLMCService # The Service that contains the API on the Hornbill instance # #.PARAMETER XMLMCMethod # The API Method # #.EXAMPLE # $xmlmcCall = Invoke-HB-XMLMC "session" "getSessionInfo" # # If successful This would return: # $xmlmcCall.status = "ok" # $xmlmcCall.params = A PSObject containing all output parameters returned by the # session::getSessionInfo API ############################## function Invoke-HB-XMLMC { Param( [Parameter(Mandatory = $True, HelpMessage = "Specify the XMLMC Service")] [ValidateNotNullOrEmpty()] [string]$XMLMCService, [Parameter(Mandatory = $True, HelpMessage = "Specify the XMLMC Method")] [ValidateNotNullOrEmpty()] [string]$XMLMCMethod ) $responseStatus = "" $responseParams = "" $responseError = "" try { # Build XMLMC call $mcParamsXML = Get-HB-Params $bodyString = '<methodCall service="' + $XMLMCService + '" method="' + $XMLMCMethod + '">' + $mcParamsXML + '</methodCall>' $body = [XML]$bodyString # Build HTTP request headers $headers = @{} $headers["Content-Type"] = "text/xmlmc" $headers["Cache-control"] = "no-cache" $headers["Authorization"] = "ESP-APIKEY " + $script:APIKey $headers["Accept"] = "application/json" # Build URI for HTTP request $URI = $script:InstanceURL + $XMLMCService + "/?method=" + $XMLMCMethod # Invoke HTTP request if ($script:ProxyURI -and $script:ProxyURI -ne "") { if ($script:ProxyCreds) { $script:ProxyCreds $r = Invoke-RestMethod -Uri $URI -UseBasicParsing -Method Post -Headers $headers -ContentType "text/xmlmc" -Body $body -ErrorAction:Stop -Proxy $script:ProxyURI -ProxyCredential $script:ProxyCreds } else { $r = Invoke-RestMethod -Uri $URI -UseBasicParsing -Method Post -Headers $headers -ContentType "text/xmlmc" -Body $body -ErrorAction:Stop -Proxy $script:ProxyURI -ProxyUseDefaultCredentials } } else { $r = Invoke-RestMethod -Uri $URI -UseBasicParsing -Method Post -Headers $headers -ContentType "text/xmlmc" -Body $body -ErrorAction:Stop } # Read and process response $responseStatus = $r | Select-Object -ExpandProperty '@status' if ($responseStatus -eq $False) { $responseError = $r.state.error } else { $responseParams = $r.params } } catch { # HTTP request failed - return exception in response $responseError = $_.Exception $responseStatus = $False } # Clear the XMLMC parameters now ready for the next API call Clear-HB-Params # Return an object of the results. $resultObject = New-Object PSObject -Property @{ Status = $responseStatus Params = $responseParams Error = $responseError } # Return result object return $resultObject } # Export the functions available to the script importing this module Export-ModuleMember -Function '*' |