1
votes

I'm trying to implement a solution which automatically calls someone when a certain event occurs, based on Twilio, Azure Automation and SCOM. Furthermore, it shall be possible for someone to call a number, and the same process is triggered.

The Twilio Account/Phonenumber is set up and works fine. When I do a call to the Twilio Number I successfully receive HTTP POST on my Azure Automation Webhook and the Runbook is fired.

The only problem I'm facing right now, is that I cannot make use of the cmdlet ConvertFrom-Json to extract the WebhookBody.

This is the error I get when using the cmdlet:

ConvertFrom-JSON : Invalid JSON primitive: Called. At line:13 char:11 + $Inputs = ConvertFrom-JSON $webhookdata.RequestBody + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : NotSpecified: (:) [ConvertFrom-Json], ArgumentException + FullyQualifiedErrorId : System.ArgumentException,Microsoft.PowerShell.Commands.ConvertFromJsonCommand

And this is the Input arriving on the Azure Automation Webhook from Twilio:

{"WebhookName":"Twilio Endpoint","RequestBody":"Called=%2B41815880262&ToState=Chur&CallerCountry=CH&Direction=inbound&Timestamp=Fri%2C%2010%20Feb%202017%2009%3A07%3A35%20%2B0000&CallbackSource=call-progress-events&CallerState=&ToZip=&SequenceNumber=0&CallSid=CA7c152287d945595fe600614fe7778f8a&To=%2B41815880262&CallerZip=&ToCountry=CH&ApiVersion=2010-04-01&CalledZip=&CalledCity=&CallStatus=completed&Duration=1&From=%2BMYTELNUZMBER&CallDuration=8&AccountSid=MYSID&CalledCountry=CH&CallerCity=&Caller=%2Bmybnumber&FromCountry=CH&ToCity=&FromCity=&CalledState=Chur&FromZip=&FromState=","RequestHeader":{"Cache-Control":"max-age=259200","Connection":"close","Accept":"/","Host":"s2events.azure-automation.net","User-Agent":"TwilioProxy/1.1","X-Twilio-Signature":"pq2jYVGN3H5LmanwId0xCvp69tM=","x-ms-request-id":"bc1cf55a-33b2-4046-a343-199d1a7fac4a"}}

When I simply output the WebHook Data with this cmd, I can see that the Twilio Repsonse looks somewhat strange (Heade looks good though):

$WebhookName = $WebhookData.WebhookName
$WebhookHeaders = $WebhookData.RequestHeader
$WebhookBody = $WebhookData.RequestBody

Write-Output $WebhookHeaders
Write-Output $WebhookBody

Output:

Cache-Control : max-age=259200 Connection : close Accept : / Host : s2events.azure-automation.net User-Agent
: TwilioProxy/1.1 X-Twilio-Signature : xmEbt23prT+W8zJrRZE5pdKullE= x-ms-request-id : bdca412c-584e-42ba-acbb-969cdf9c1ec0

Called=%2B41815880262&ToState=Chur&CallerCountry=CH&Direction=inbound&Timestamp=Wed%2C%2008%20Feb%202017%2013%3A18%3A27%20%2B0000&CallbackSource=call-progress-events&CallerState=&ToZip=&SequenceNumber=0&CallSid=CALLSID&To=%2B41815880262&CallerZip=&ToCountry=CH&ApiVersion=2010-04-01&CalledZip=&CalledCity=&CallStatus=completed&Duration=1&From=%2BMYNUMBER&CallDuration=7&AccountSid=MYSID&CalledCountry=CH&CallerCity=&Caller=%2BMYBNUMBER&FromCountry=CH&ToCity=&FromCity=&CalledState=Chur&FromZip=&FromState=

Does anybody have an idea what I could do instead of writing my own "Converter" to get the values from the TWILIO HTTP POST? Or may I be doing something horribly wrong?

2

2 Answers

3
votes

So, I think I understood your problem. You are doing it slightly wrong: $webhook data is already an object, which has everything you need:

$WebhookData.WebhookName
$WebhookData.RequestHeader
$WebhookData.RequestBody

You just need to parse RequestBody into something meaningful:

$data = @{ };

foreach ($item in $WebhookData.RequestBody.Split('&')) {
    try {
        $item = $item.Split('=');
        $data.Add($item[0], [System.Net.WebUtility]::UrlDecode($item[1]))           
    }
    catch {
        Write-Warning -Message ('Possible null parameter value for {0}' -f $item[0]);
    }
}
1
votes

Twilio developer evangelist here.

When Twilio sends a webhook request to your URL it is not encoded as JSON. This is why your JSON conversion is failing.

Twilio sends the data as either URL encoded parameters in the body of a POST request or URL query parameters for GET requests. This is the same as if the request were made by the submission of a form in a browser.

I'm not familiar with Azure cmdlets but if there is one for parsing URL encoded data, then you'll want to use that instead. Alternatively, @4c74356b41 has provided a decent implementation.