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:
Related
I need to attach the file either xlsx or CSV to a particular incident via SNOW REST API using PowerShell script. I have tried with the below code:
if (!$script:ServiceNowCreds) {
$script:ServiceNowCreds = Get-Credential
}
$snow_url = 'https://dev652xx.service-now.com/api/now/table/incident'
$Body = #{
'number' = 'INC00xx059'
}
$result = Invoke-RestMethod -Uri $snow_url -Credential $script:ServiceNowCreds -Body $Body -ContentType "application/json"
$result.result | select sys_id, number | ForEach-Object {
$Upload_snow_url ='https://dev652xx.servicenow.com/api/now/attachment/upload'
$headers = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"
$headers.Add('Content-Type','text/csv')
$headers.Add('Accept','*/*')
$sys_id = $_.sys_id
$incident_number = $_.number
$UploadBody = #{
'table_name'='incident';
'table_sys_id'=$sys_id;
'file_name' = 'C:\Users\suganthanraj.p\Documents\Servers.csv'
}
$uploadParam = $UploadBody | ConvertTo-JSon
Write-Host $sys_id
Write-Host $incident_number
$UploadResult = Invoke-RestMethod -Uri $Upload_snow_url -Credential $script:ServiceNowCreds -Body $uploadParam -Method Post -Headers $headers
$UploadResult
}
When I execute the above script I am getting the below error:
Invoke-RestMethod : The remote server returned an error: (415) Unsupported
Media Type.
At C:\Users\suganthanraj.p\Desktop\SNOW-UploadAttachment.ps1:39 char:21
+ ... oadResult = Invoke-RestMethod -Uri $Upload_snow_url -Credential $scr ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-RestMethod], WebException
+ FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeRestMethodCommand
Try changing you content type to "multipart/form-data"
$headers.Add('Content-Type','multipart/form-data')
$UploadBody = #{
'table_name'='incident';
'record_sys_id'=$sys_id;
'uploadFile' = 'C:\Users\suganthanraj.p\Documents\Servers.csv'
}
The error says "The remote server returned an error: (415) Unsupported
Media Type."
Doco on the api can be found here:
https://docs.servicenow.com/bundle/geneva-servicenow-platform/page/integrate/inbound_rest/reference/r_AttachmentAPI-POSTmultipart.html
Your best option would be leverage the OOB Attachment API in ServiceNow. You will need to make a post call from powershell. Powershell has two options for this Invoke-RestMethod and Invoke-WebRequest. I have had better luck with the latter when trying to POST. You might also first build your rest call in Postman make sure you can get the attachment into ServiceNow, then worry about writing your PS.
$Body = #{
User = 'jdoe'
password = 'P#S$w0rd!'
}
$LoginResponse = Invoke-WebRequest 'http://www.contoso.com/login/' - SessionVariable 'Session' -Body $Body -Method 'POST'
$Session
$ProfileResponse = Invoke-WebRequest 'http://www.contoso.com/profile/' -`WebSession $Session $ProfileResponse`
Finally i found answer from the below link
https://community.servicenow.com/community?id=community_question&sys_id=d3707023dbaceb8023f4a345ca961949 and below is the code:
# Eg. User name="admin", Password="admin" for this code sample.
$user = "admin"
$pass = "XXX"
# 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))
$headers.Add('Accept','application/json')
$headers.Add('Content-Type','application/json')
# Specify endpoint uri
$uri = "https://dev652XX.service-now.com/api/now/attachment/file?table_name=incident&table_sys_id=850XXXXX2200e0ef563dbb9a71c1&file_name=TreeSizeReport.csv"
# Specifiy file to attach
$fileToAttach = "C:\Users\suganthanraj.p\Desktop\TreeSizeReport.csv"
# Specify HTTP method (POST, PATCH, PUT)
$method = "POST"
# Send HTTP request
$response = Invoke-WebRequest -Headers $headers -Method $method -Uri $uri -InFile $fileToAttach
# Print response
$response.RawContent
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'
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!
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!)
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