Invoke-RestMethod and Fiddler, can't get 200 code in return - rest

I am trying to replicate a POST call that can be send from GUI using Invoke-RestMethod. I would like to automate it and have been trying to use powershell to do it.
It alwasy returns 202 code, have been trying it for a few hours now but can't progress. This is really the first time I am playing with invoke-restmedod and Rest so please be detailed what's wrong. Any help is highly appreciated.
So the successful call captured by Fiddler is this:
The powershell code is:
$WfManDirUserPass = "Password"
$secpasswd = ConvertTo-SecureString $WfManDirUserPass -AsPlainText -Force
$cred = New-Object System.Management.Automation.PSCredential ("admin", $secpasswd)
$active = #{
ipaddress="192.168.100.116"
Port="62805"
status="0"
}
$json = $active | ConvertTo-Json
try{
$response = invoke-restmethod -uri https://myhost/MAM/wfservice/workers/?ip="&"port="&"newStatus=Deactivating -Method POST -Body $json -Credential $cred -ContentType 'application/json'
} catch {
write-host("Sorry, it does not work")
}
This powershell code in Fiddler returns:
I can see that the JSON is not exactly the same on the attached images. However I stuck now and would really appreciate some help now.

This is a reply from 1RedOne (Reddit) user that helped me out:
For one, let's wrap your whole -URI in single quotes and remove the double quotes. Your URL is probably messed up, which isn't helping things.
$uri = 'https://myhost/MAM/wfservice/workers/?ip=&port=&newStatus=Deactivating'
$response = invoke-restmethod -uri $uri-Method POST -Body $json -Credential $cred -ContentType 'application/json'
2.
Furthermore, your call from fiddler uses basic authentication, and is probably incompatible with using a -Credential object. Try replacing your credentials with this format.
$user = "yourusername"
$pass = 'yourPassWord'
# Build auth header
$base64AuthInfo = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f $user, $pass)))
# Set proper headers
$headers = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"
$headers.Add('Authorization',('Basic {0}' -f $base64AuthInfo))
Then, reference the $header object within your Invoke-RestMethod, like so.
$response = invoke-restmethod -uri $uri- Method POST `
-Body $json -Header $headers -ContentType 'application/json'
That's it. It worked like a charm!

Related

Invoke-Webrequest with UseBasicParsing fails to pass SecureString password

I am trying to upload a file [path] to [uri] with Invoke-WebRequest with the following:
$Uri = [uri]
$Body = #{
username = $Credentials.UserName
password = $Credentials.Password
file = Get-Item -Path [path]
}
Invoke-WebRequest -Uri $Uri -Method 'POST' -Body $Body -UseBasicParsing
(As I'm stuck with Powershell 5.1 I include -UseBasicParsing).
This leads to a failed login response, and inspecting the server response, I see that it interprets the password string as "System.Security.SecureString" instead of the actual password.
I assume that this happens because -UseBasicParsing changes how SecureString objects are passed? I am a complete novice in Powershell and HTTP and so would greatly appreciate any suggestions for workarounds that don't compromise on security, and/or any explanations for why this happens.
You can try decoding the password inline, like this:
$Uri = [uri]
$Body = #{
username = $Credentials.UserName
password = ($Credentials.Password.GetNetworkCredential().Password)
file = Get-Item -Path [path]
}
Invoke-WebRequest -Uri $Uri -Method 'POST' -Body $Body -UseBasicParsing
and here's the result:

Unable to ingest JSON data into Azure Event Hub

I wrote the below Powershell script to get the JSON data from an API endpoint (https://data.melbourne.vic.gov.au/resource/vh2v-4nfs) and then write this data in JSON format to Azure Event hub. I am able to successfully get the data from the endpoint however the data is not getting ingested into Azure Event Hub.
Can anyone please let me know what's wrong with the below code:
$url = "https://data.melbourne.vic.gov.au/resource/vh2v-4nfs"
$apptoken = "k7lQcUCVFoROv7rQh9fSSXMkZ"
# Set header to accept JSON
$headers = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"
$headers.Add("Accept","application/json")
$headers.Add("X-App-Token",$apptoken)
$results = Invoke-RestMethod -Uri $url -Method get -Headers $headers
$results
$method = "POST"
$URI = "https://YOURNS.servicebus.windows.net/eh-streetparking/messages"
$signature = "SharedAccessSignature sr=YOURNS.servicebus.windows.net%2feh-streetparking&sig=K6bfL1VjW9FUcL0B5xaI%3d&se=16722&skn=eh-sap-streetparking"
#$authInfo = [System.Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes("$signature"))
# API headers
$headers = #{
"Authorization"=$signature;
# "Content-Type"="application/json;type=entry;charset=utf-8";
"Content-Type"="application/json";
}
# execute the Azure REST API
foreach ( $result in $results)
{
Invoke-RestMethod -Uri $URI -Method $method -Headers $headers -Body $result
}
The value you have presented as the return result from your Invoke-RestMethod is actually a deserialized PowerShell object, not JSON. It appears to be having its quotes removed at some point too.
PSObject ($results) looks like this: $x = #{account_id="12345"; username="12345"; is_locked="False"; employee_id="12345"; first_name="John"; middle_initial="Roger"; last_name="Doe"; full_name="John Roger Doe"}
You can do this to access individual values:
$x.full_name
Finally, follow this syntax to send POST request:
$Cred = Get-Credential
$Url = "https://server.contoso.com:8089/services/search/jobs/export"
$Body = #{
search = "search index=_internal | reverse | table index,host,source,sourcetype,_raw"
output_mode = "csv"
earliest_time = "-2d#d"
latest_time = "-1d#d"
}
Invoke-RestMethod -Method 'Post' -Uri $url -Credential $Cred -Body $body -OutFile output.csv

Message Body for Invoke-RestMethod for Content Type of application/xml

I want to pass an XML document as part of a REST method call:
$url = 'https:foobar/get/jars/2/cookies/chocolate-chip'
[xml]$message = #'
<Cookie>
<Password auto="false">Eat</Password>
</Cookie>
'#
$method = 'Put'
$credential = Get-Credential $env:username
$return_message = Invoke-RestMethod -Uri $url -Body $message -Method $method -ContentType 'application/xml'
It's blowing up with the following:
"Invoke-RestMethod : The underlying connection was closed: An unexpected error occurred on a send."
How the &$#* do you pass an XML document in the Body of the request. I've tried passing a string with XML markup.
You people are no help.
My URL was wrong (at least in my example). The following code will work:
$me = Get-Credential $env:username
Invoke-RestMethod -Credential $me `
-Method Put `
-Uri 'https://deezNutz.myCompany.com/pfft/users/billy `
-Body [xml]'<User><Enable>False</Enable></User>' `
-ContentType 'application/xml'

Powershell Invoke-RestMethod missing cookie values

I'm trying to access a Swagger based API using powershell invoke-restmethod with websession to (hopefully) capture the cookies/session information I'd need to do a post method.
I start by requesting a CSRF
$CSRF = Invoke-RestMethod -Uri ($Uri+'csrf-token') -Method Get -Credential $Creds -ContentType 'application/json'-SessionVariable websession
and I can see the correct token value without any issues. Looking at the websession variable I do have some data, but I don't get any cookie values at all. Thus if I submit a second request using the session variable:
Invoke-RestMethod -Method Post -Uri ($Uri+'post') -Headers $Header -Body $Body -Credential $creds -WebSession $websession
it fails due to the missing cookie values. If I do a normal request via Firefox I see cookies with a jsessionid, etc but I don't know how to get these values somewhere where I can use them (please excuse me ignorance here- I'm relatively new to the invoke-restmethod in PS)
I've sussed it out (at last- very painful) - I had to build my own cookie:
$CSRF = Invoke-RestMethod -Uri ($Uri+'csrf-token') -Method Get -Credential $Creds -ContentType 'application/json' -SessionVariable websession -MaximumRedirection 0
$CSRFToken = $CSRF.tokenValue
# Capture cookie
$cookiejar = New-Object System.Net.CookieContainer
$cookieUrl = $uri +'csrf-token'
$cookieheader = ""
$webrequest = [System.Net.HTTPWebRequest]::Create($cookieUrl);
$webrequest.Credentials = $creds
$webrequest.CookieContainer = $cookiejar
$response = $webrequest.GetResponse()
$cookies = $cookiejar.GetCookies($cookieUrl)
# add cookie to websession
foreach ($cookie in $cookies) {$websession.Cookies.Add((Create-Cookie -name $($cookie.name) -value $($cookie.value) -domain $apiserverhost))}
# Finally, I can post:
Invoke-RestMethod -Method Post -Uri ($Uri+'versions/createVersionRequests') -Headers $Header -Body $Body -Credential $creds -WebSession $websession
Hope that helps someone else (I've spent hours pulling my hair out over this!)

How can I correct Invalid CSRF token errors when calling a rest API?

I've got a script that will query a web rest service to find the ID for a specific object. I've gotten the query working fine under Powershell for a single query, but I need to run several hundred queries. It's really slow (And bad practice) to login for every single query.
I have the script logon to the server first and save the session. The I run the rest query using a post operation. First one works fine. Second one bombs out saying:
Invoke-RestMethod : Invalid CSRF Token
Invalid CSRF Token
An invalid cross-site request forgery token was detected in the request.
The code looks like this:
$secpasswd = ConvertTo-SecureString "password" -AsPlainText -Force
$cred = New-Object System.Management.Automation.PSCredential ("user", $secpasswd)
$headers = "Content-Type: text/plain","Accept: text/plain"
#Login it the server to store the session to WebSession.
$login = Invoke-WebRequest -Uri "https://devrhapapp01:8444" -Credential $cred -SessionVariable websesssion
#This one returns correctly.
$Results = Invoke-RestMethod -Uri "https://devrhapapp01:8444/api/components/find" -ContentType "text/plain" -Method Post -Body "Search1" -WebSession $websesssion
write-host $Results
#This one will give an error.
$Results = Invoke-RestMethod -Uri "https://devrhapapp01:8444/api/components/find" -ContentType "text/plain" -Method Post -Body "Search1" -WebSession $websesssion
write-host $Results
Not sure what is going on, but try submitting the correct anti-forgery token:
$forgeryToken = ($login.InputFields |
Where { $_.name -eq "__RequestVerificationToken" }).value
$forgeryTokenPostData = "__RequestVerificationToken=$forgeryToken"
Invoke-WebRequest .... -Body $forgeryTokenPostData