Azure Runbook Webhook with parameters from httpClient - json

looked at a few examples of how to execute a webhook with parameters but can't seem to make the connection on what I am missing. Any advice on what I am doing wrong would be appreciated.
please consider:
my Powershell runbook
[CmdletBinding()]
Param([object]$WebhookData) #this parameter name needs to be called
WebHookData otherwise the webhook does not work as expected.
$VerbosePreference = 'continue'
Write-Output "hello"
"in the inline"
if($WebhookData -ne $null)
{
"using webhookdata"
$WebhookName = $WebhookData.WebhookName
$WebhookBody = $WebhookData.RequestBody
$webhookBodyObject = $WebhookBody | ConvertFrom-JSON
line 15 'The parameter created was ' $webhookBodyObject.strYear
My httpclient post request looks like this (warning..its vb)
dim WebHookData as new StringContent("{'strYear'='2018'}",Encoding.UTF8,"application/json")
Dim resp as Task(Of HttpResponseMessage)
resp = _client.PostAsync(webhook,WebHookData)
status = resp.Result.Content.ReadAsStringAsync().Result
if(status.Contains("JobId"))
status = "Scheduled!"
End If
My Webhook data is being posted to my webhook as this.
{"WebhookName":"myimportjob","RequestBody":"{'strYear'='2018'}","RequestHeader":{"Connection":"Keep-Alive","Expect":"100-continue","Host":"xxx.azure-automation.net","x-ms-request-id":"xxx"}}
I am getting this error
At line:15 char:42
+ 'The parameter created was ' $webhookBodyObject.strYear
+ ~~~~~~~~~~~~~~~~~~ Unexpected token '$webhookBodyObject' in expression or
statement.

I discovered the devil is in the details.
Firstly I had
$webhookBodyObject = $WebhookBody | ConvertFrom-JSON
which is not the same as
$webhookBodyObject = $WebhookBody | ConvertFrom-Json <---this is the correct syntax
The other was that the json I was sending had a single quote like this '{"key":"value"}'
For some reason, even though it passed regular powershell, the runbook didn't like it. It wants it's Json like this {"key":"value"}. I never tested complex objects so I can't speak to that.

Related

How to send a .json file from Flow to Azure Function and return results?

I want to send a serialized .json file to a PowerShell Azure Function, prettify it, then return the file to Flow for further processing. I cannot figure out how to do this.
In Flow:
Trigger: Button push
Action1: Get file content from OneDrive
Output:
{
"$content-type": "application/octet-stream",
"$content": "eyJUb3BQYXJlbnQiOns...<truncated for this post>"
}
Action2: Send HTTP Request
URI: https://test.azurewebsites.net/api/prettifyJson?code=<api key>
Method: POST
Body: body('Get_file_content') (output from Action1)
In Azure Function:
Default PowerShell run.ps1:
using namespace System.Net
# Input bindings are passed in via param block.
param($Request, $TriggerMetadata)
# Write to the Azure Functions log stream.
Write-Host "PowerShell HTTP trigger function processed a request."
# Interact with body of the request.
$content = $Request.Query.baz
if (-not $name) {
$name = $Request.Body.baz
}
if ($name) {
$status = [HttpStatusCode]::OK
$body = "Hello $name"
}
else {
$status = [HttpStatusCode]::BadRequest
$body = "Please pass a name on the query string or in the request body."
}
# Associate values to output bindings by calling 'Push-OutputBinding'.
Push-OutputBinding -Name Response -Value ([HttpResponseContext]#{
StatusCode = $status
Body = $content
})
Issues:
A call to the function fails with Please pass a name on the query string or in the request body. I can see why, but do not know what syntax to replace in run.ps1
I have no idea what syntax to use to:
a. Receive the .json file
b. Convert it to pretty json
c. Repackage the .json file
d. Send it back to Flow
Looking for guidance.
About number one, seems you're missing the name in the url.
try to replace from this:
https://test.azurewebsites.net/api/prettifyJson?code=
to this:
https://test.azurewebsites.net/api/prettifyJson?name=test&code=
about your second question, the you'll need to parse the body content as Hashtable. try to combine:
$hash = $Request.Body | ConvertFrom-Json -AsHashtable
then all the variables will be available using $hash[]
e.g: $hash["$content"]

JSON Prettifier Using Azure Function w/ PowerShell and HTTP Trigger

Thought this would be pretty simple, but alas, I can't figure it out. It appears that PowerShell will prettify JSON with a single cmdlet.
Goal: Prettify JSON using a PowerShell Azure Function app
Using Microsoft Flow, send an HTTP request (POST) to an Azure Function w/ "ugly", serialized JSON file in body
Azure Function reads file in (then uses ConvertToJson cmdlet to prettify?) and outputs the file back to Flow
Questions:
What do I put in the run.ps1 area of the Azure Function to make this happen?
What do I put in the functions.json area of the Azure Function to make this happen?
I have taken below serialize string
'{ "baz": "quuz", "cow": [ "moo", "cud" ], "foo": "bar" }'
which was mentioned in Prettify json in powershell 3
Here is my function which i used with HttpPost and send the request:
using namespace System.Net
# Input bindings are passed in via param block.
param($Request, $TriggerMetadata)
# Write to the Azure Functions log stream.
Write-Host "PowerShell HTTP trigger function processed a request."
# Interact with query parameters or the body of the request.
$name = $Request.Query.baz
if (-not $name) {
$name = $Request.Body.baz
}
if ($name) {
$status = [HttpStatusCode]::OK
$body = "Hello $name"
}
else {
$status = [HttpStatusCode]::BadRequest
$body = "Please pass a name on the query string or in the request body."
}
# Associate values to output bindings by calling 'Push-OutputBinding'.
Push-OutputBinding -Name Response -Value ([HttpResponseContext]#{
StatusCode = $status
Body = $body
})
and below you can see , i am able to read it from the string which i posted.
You can use ConvertFrom-Json to convert it but i wondering if you even need it as you can access it by doing below:
$name = $Request.Query.baz
my binding is same as yours. Hope it helps.
Let me know if you still need any help.
Are you looking for something like this?
using namespace System.Net
param($Request, $TriggerMetadata)
Push-OutputBinding -Name Response -Value ([HttpResponseContext]#{
StatusCode = [HttpStatusCode]::OK
Body = $Request.RawBody | ConvertFrom-Json | ConvertTo-Json
})

Add windows env variables to json object using powershell

I'm quite new to powershell and just need it for a small task so please excuse my complete and utter ineptitude for the language. I was wondering if it were possible to form a json object based off environment variables and a variable that has already been declared earlier in my script. The variable that was already declared is based off a json config named optionsConfig.json and the contents of that file are here.
{"test1": ["options_size", "options_connection", "options_object"],
"test2":["options_customArgs", "options_noUDP", "options_noName"]}
The purpose of the $Options variable in the code below is to take each element in the list value for the respective test and assume that those elements are environment variables in the system, then find their values and form a dictionary object that will be used in the json.
Here is what I have so far.
# Read the JSON file into a custom object.
$configObj = Get-Content -Raw optionsConfig.json |
ConvertFrom-Json
# Retrieve the environment variables whose
# names are listed in the $env:test property
# as name-value pairs.
Get-Item -Path env:* -Include $configObj.$env:testTool
$Options = Get-Item -Path env:* -Include $configObj.$env:testTool |
% {$hash = #{}} {$hash[$_.Name]=$_.Value} {$hash}
The $Options variable looks like so when converted to json
{
"options_size": "default",
"options_object": "forward open",
"options_connection": "connected"
}
I have a few other environment variable values that I would like to be a part of the json object. Those 3 other environment variables I would like the value of are listed below.
$Env.testTool = "test1"
$Env.RecordName = "Record1"
$Env.Target = "Target1"
How would I construct a powershell statement to get the json object to be formatted like this? -
data = {"test": $Env.testTool, "target": "$Env.Target",
"options": "$Options", "RecordName': "$Env.RecordName"}
The keys are all predefined strings and $Options is the dict object from up above. Am I able to form a Json object like this in powershell and how would it be done? Any help would be appreciated. This appears to be the last step in my struggle with powershell.
Here is what I have done.
$jObj = [ordered]#{test= $Env:testTool}
When I change this variable to $jObj = [ordered]#{test= $Env:testTool,options= $Options} I get an error saying missing expression after ','
When I change this variable to $jObj = [ordered]#{test= $Env:testTool,options= $Options} I get an error saying missing expression after ','
Entries of a hashtable literal (#{ ... } or, in its ordered form, [ordered] #{ ... }) must be separated:
either by newlines (each entry on its own line)
or by ; if placed on the same line.
Thus, the following literals are equivalent:
# Multiline form
#{
test= $env:testTool
RecordName= $env:RecordName
Target= $env.Target
options=$Options
}
# Single-line form; separator is ";"
#{ test= $env:testTool; RecordName= $env:RecordName; Target= $env.Target; options=$Options }
Get-Help about_Hashtables has more information.
$jObj = #{test= $env:testTool
RecordName= $env:RecordName
Target= $env.Target
options=$Options}
$jObj | ConvertTo-Json | Set-Content jsonStuff.json
JsonStuff.json is the new json file for the new json object. This syntax for forming $jObj seems to have done the trick.

Powershell: How to throw an error if a CSV entry is blank

I've written an extensive script that runs through an AD termination process, and the script can obtain the necessary information from a CSV. How do I make it so that it errors out if the entry is blank in the CSV? I've tried putting in Try-Catch, If-Else, everything that I know how to do. I've tried changing the error action, and I can get it to throw system generated errors (ex. "Cannot bind parameter "Identity" to the target..."), but I cannot get it to do what I want. Please see the code example below:
(Yes, I know that I'm duplicating values. This of importance later on in the script, and not the part I'm having issues with)
$owner = $user.'Network User ID'}
$loginID = $user.'Network User ID'
$Identity = Get-ADUser -Identity $owner -Properties Displayname |Select-Object -ExpandProperty Displayname
$manager = $user.'Provide Inbox Access To'
$NewOwner = $user.'Provide users email group ownership to'
$NewOwnerID = $User.'Provide users email group ownership To'
What I need it to do is throw an error if ANY entry in the CSV is blank, and terminate. The most promising idea that I tried was:
If ($Owner -eq $Null)
{
Write-Host "Invalid entry, the Network User ID field cannot be blank"
Write-Host "Press Enter to Exit..."
Exit
}
Else
{
#Do everything else
}
But even that still fails.
In summary, what I need to do is throw a custom terminating error if an entry in the CSV is blank.
Any help is greatly appreciated!
EDIT
If this helps, here is more of the real code...
$Confirmation = Read-Host "Please double check the information in the file. Are you sure you want to continue? (Y/N)"
If($Confirmation -eq "Y")
{
Write-Host "You have chosen to proceed. Processing Termination" -BackgroundColor DarkCyan
#Import file
$file = "C:\TerminateUsers.csv"
$data = Import-Csv $file
#Set disabled OU
$disabledOU = "OU=Users,OU=Disabled Accounts, OU=Corporate"
$colOutput = #()
foreach ($user in $data)
{
#Grab variables from CSV
$owner = $user.'Terminated Network User ID'}
$loginID = $user.'Terminated Network User ID'
#Displayname required for Outlook functions
$Identity = Get-ADUser -Identity $owner -Properties Displayname |Select-Object -ExpandProperty Displayname
$manager = $user.'Provide Inbox Access To'
$NewOwner = $user.'Provide users email group ownership to'
$NewOwnerID = $User.'Provide users email group ownership To'
If (Get-ADUser -LDAPFilter "(sAMAccountName=$loginID)")
{
$date = Get-Date -Format d
#Disable account, change description, disable dialin, remove group memberships
Set-ADUser -Identity $loginID -Enabled $false
Set-ADUser -Identity $loginID -Replace #{Description = "Terminated $date"}
Set-ADUser -Identity $loginID -Replace #{msNPAllowDialin = $False}
RemoveMemberships $loginID
This isn't all of it, but this is the part we're working with...
There's a number of issues you're going to run into here.
First, $Owner -eq $Null isn't going to do what you likely want to do. Mainly, the issue is that an empty string is not a null value. They're different. Instead, your test should be:
if ([string]::IsNullOrEmpty($owner)) { ... }
Or:
if ([string]::IsNullOrWhiteSpace($owner)) { ... }
This second one returns true if the string includes only tabs, spaces, or other whitespace characters, or is an empty string, or is null.
Second, to throw an exception, you need to use the throw keyword. See Get-Help about_Throw. For example:
if ([string]::IsNullOrWhiteSpace($owner)) {
throw "Owner is null or empty.";
}
If you have this embedded in a try block, you can catch the exception with the associated catch blocks. See Get-Help about_Try_Catch_Finally. You can also use Trap, I believe (See Get-Help about_Trap).
Finally, the default action when an error is encountered is controlled by the $ErrorActionPreference variable. That variable's default value is Continue, so error messages will be displayed but the script will continue executing as though no error happened at all. I'm not entirely sure how this works with manually thrown exceptions and try/catch blocks, but unless I know that I want my script to ignore errors, I start just about every script with:
$ErrorActionPreference = Stop;
See Get-Help about_Preference_Variables and Get-Help about_CommonParameters for more about this one.
Consider the following dataset. Note the null for Last_Name for one of the columns.
user_name first_name last_name
--------- ---------- ---------
lrivera0 Lawrence Rivera
tlawrence1 Theresa Lawrence
rboyd2 Roy
cperry3 Christine Perry
jmartin4 Jessica Martin
So if we want to be sure to only process full rows then a simple If would cover that.
Import-Csv .\text.csv | ForEach-Object{
If($_.Psobject.Properties.Value -contains ""){
# There is a null here somewhere
Throw "Null encountered. Stopping"
} else {
# process as normal
}
}
Problem is that Import-CSV treats nulls as zero length strings. I tried using -contains on just $_ but it did not work as $_ is not an array but an object with properties. So I used the object properties value to perform the comparison against.
Bacon brought up an interesting point in that this code would not account for whitespace only empty values.
We use throw so processing stops if a null is encountered. Using that if block you can do whatever action you want.

Reading json response in windows power shell

I am using power shell code as:
$web_client = new-object system.net.webclient
$build_info=web_client.DownloadString("http://<URL>")
$suitevm_build_number=
$suitevmCLN=
$webapp_build=
$stats_build=
Output in browser while hitting http:// is:
{"message":null,"changeset":"340718","branch":"main","product":"productname","buildNumber":"1775951","todaysDate":"28-4-2014"}
What should I write the power shell code to get:
$suitevm_build_number=
$suitevmCLN=
$webapp_build=
$stats_build=
Your question is very unclear. If you have Powershell 3 or later, you can use ConvertFrom-JSON to convert the JSON response to an object.
$build_info=$web_client.DownloadString("http://<URL>") | ConvertFrom-Json
Ex of output:
$build_info
message :
changeset : 340718
branch : main
product : productname
buildNumber : 1775951
todaysDate : 28-4-2014
With PS 3+ you could also replace the WebClient with Invoke-RestMethod as shown by #RickH.
$build_info = Invoke-RestMethod -Uri "http://<URL>"