Process SOAP request from powershell - powershell

I try to utilise the code example. But I am unsuscessful. Can any one pick up an error? (I know about New-WebServiceProxy cmdlet.)
function Execute-SOAPRequest
(
[Xml] $SOAPRequest,
[String] $URL
)
{
write-host “Sending SOAP Request To Server: $URL”
$soapWebRequest = [System.Net.WebRequest]::Create($URL)
$soapWebRequest.Headers.Add("SOAPAction" ,"http://www.webservicex.net/globalweather.asmx?WSDL/GetWeather")
$soapWebRequest.ContentType = 'text/xml;charset="utf-8"'
$soapWebRequest.Accept = “text/xml”
$soapWebRequest.Method = “POST”
write-host “Initiating Send.”
$requestStream = $soapWebRequest.GetRequestStream()
$SOAPRequest.Save($requestStream)
$requestStream.Close()
write-host “Send Complete, Waiting For Response.”
$resp = $soapWebRequest.GetResponse()
$responseStream = $resp.GetResponseStream()
$soapReader = [System.IO.StreamReader]($responseStream)
$ReturnXml = [Xml] $soapReader.ReadToEnd()
$responseStream.Close()
write-host “Response Received.”
return $ReturnXml
}
function Execute-SOAPRequestFromFile
(
[String] $SOAPRequestFile,
[String] $URL
)
{
write-host “Reading and converting file to XmlDocument: $SOAPRequestFile”
$SOAPRequest = [Xml](Get-Content $SOAPRequestFile)
return $(Execute-SOAPRequest $SOAPRequest $URL)
}
$x = Execute-SOAPRequestFromFile -SOAPRequestFile soap-W.txt -URL "http://www.webservicex.net/globalweather.asmx?WSDL"
The file soap-W.txt:
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:http="http://schemas.xmlsoap.org/wsdl/http/" xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/" xmlns:s="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="http://www.webserviceX.NET" xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:tm="http://microsoft.com/wsdl/mime/textMatching/" xmlns:SOAP-ENV="http://www.w3.org/2003/05/soap-envelope">
<SOAP-ENV:Body>
<tns:GetWeather xmlns:tns="http://www.webserviceX.NET">
<tns:CityName>Tampa</tns:CityName>
<tns:CountryName>United States</tns:CountryName>
</tns:GetWeather>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
Server return error 500. Query via New-WebServiceProxy is successfull.

You should try New-WebServiceProxy CmdLet.
$svc = New-WebServiceProxy -Uri "http://www.webservicex.net/globalweather.asmx?WSDL"
$svc.GetWeather("Aurillac", "France")

Related

Having difficultly mocking Invoke-WebRequest's BasicHtmlWebResponseObject

I'm attempting to test this section of a PowerShell function:
# post
$Response = Invoke-WebRequest -Method POST -Uri $Uri -Body $Body -ContentType 'application/xml'
# parse Response.Content; return as System.Xml.XmlDocument
[xml]$Response.Content
by mocking the BasicHtmlWebResponseObject that is returned by Invoke-WebRequest:
Mock Invoke-WebRequest {
$WebResponse = [System.Net.HttpWebResponse]::new()
[System.Net.HttpWebResponse].GetField('m_StatusCode', 'NonPublic, Instance').SetValue(
$WebResponse,
200,
'NonPublic,SetField',
$null,
(Get-Culture)
)
$Content = '<?xml version="1.0" encoding="UTF-8"?><response><control>failure<status></status></control><operation><result><status>failure</status></result></operation></response>'
$Response = [Microsoft.PowerShell.Commands.BasicHtmlWebResponseObject]::new($WebResponse,$Content)
return $Response
}
This assertion fails because I'm not creating the HttpWebResponse or BasicHtmlWebResponseObject correctly:
It "returns the response's Content object" {
# act
$Content = Send-Request -Session $Session
# assert
Assert-MockCalled Invoke-WebRequest
$Content | Should -BeOfType [xml]
$Content.response.control.status | Should -Be 'success'
$Content.response.operation.result.status | Should -Be 'success'
}
** edit **
I thought about using New-MockObject:
Mock Invoke-WebRequest {
$Response = New‐MockObject -Type Microsoft.PowerShell.Commands.BasicHtmlWebResponseObject
$Response.Content = '<?xml version="1.0" encoding="...'
}
but, the Content property is read-only.
** /edit **
What am I missing?
A slightly simpler alternative might be to wrap your invoke-webrequest in a function and just mock that instead. E.g.
function Get-XmlFromUri
{
param( $Uri, $Method, $Body )
$Response = Invoke-WebRequest -Method $Method -Uri $Uri -Body $Body -ContentType 'application/xml’
[xml]$Response.Content
}
Now you can mock Get-XmlFromUri and just return a System.Xml.XmlDocument object from hard-coded xml, which is much easier to create than a BasicHtmlWebResponseObject that needs reflection calls spin up.
Mock Get-XmlFromUri {
[xml] '<?xml version="1.0" encoding="UTF-8"?>
<response>
<control><status>success</status></control>
<operation><result><status>success</status></result></operation>
</response>'
}
Or, depending on how much like BasicHtmlWebResponseObject your code needs it to be, you can just return a hashtable from your invoke-webrequest mock that has the properties you need:
Mock Invoke-WebRequest {
new-object pscustomobject -property #{
Content = '<?xml version="1.0" encoding="UTF-8"?>
<response>
<control><status>success</status></control>
<operation><result><status>success</status></result></operation>
</response>’
}
}
(apologies for code formatting - currently typing one handed on an iPhone at 4 AM holding a not-very-sleepy baby :-S)
On PowerShell Core this doesn't work for me:
[System.Net.HttpWebResponse].GetField('m_StatusCode', 'NonPublic, Instance')
And thats why your Mock isn't returning what you expect. That line does work on Windows PowerShell however. Not sure what the right equivalent is on PSCore, needs research but thought i'd get you this far in the meantime.
This works:
Mock Invoke-WebRequest {
$Response = New-MockObject -Type Microsoft.PowerShell.Commands.BasicHtmlWebResponseObject
$Content = `
'<?xml version="1.0" encoding="UTF-8"?>
<response>
<control><status>success</status></control>
<operation><result><status>success</status></result></operation>
</response>'
$Response | Add-Member -NotePropertyName Content -NotePropertyValue $Content -Force
$Response
}

using Invoke-RestMethod to post to a cosmosDB Returns a 400

I am trying to post a document to cosmosdb using powershell, I have followed the steps in this post https://www.systemcenterautomation.com/2018/06/cosmos-db-rest-api-powershell/ and I am still getting a 400 error everytime
Add-Type -AssemblyName System.Web
# generate authorization key
Function Generate-MasterKeyAuthorizationSignature
{
[CmdletBinding()]
Param
(
[Parameter(Mandatory=$true)][String]$verb,
[Parameter(Mandatory=$true)][String]$resourceLink,
[Parameter(Mandatory=$true)][String]$resourceType,
[Parameter(Mandatory=$true)][String]$dateTime,
[Parameter(Mandatory=$true)][String]$key,
[Parameter(Mandatory=$true)][String]$keyType,
[Parameter(Mandatory=$true)][String]$tokenVersion
)
$hmacSha256 = New-Object System.Security.Cryptography.HMACSHA256
$hmacSha256.Key = [System.Convert]::FromBase64String($key)
$payLoad = "$($verb.ToLowerInvariant())`n$($resourceType.ToLowerInvariant())`n$resourceLink`n$($dateTime.ToLowerInvariant())`n`n"
$hashPayLoad = $hmacSha256.ComputeHash([System.Text.Encoding]::UTF8.GetBytes($payLoad))
$signature = [System.Convert]::ToBase64String($hashPayLoad);
[System.Web.HttpUtility]::UrlEncode("type=$keyType&ver=$tokenVersion&sig=$signature")
}
Function Post-CosmosDocuments{
[CmdletBinding()]
Param
(
[Parameter(Mandatory=$true)][String]$EndPoint,
[Parameter(Mandatory=$true)][String]$DBName,
[Parameter(Mandatory=$true)][String]$CollectionName,
[Parameter(Mandatory=$true)][String]$MasterKey,
[String]$Verb="POST",
[Parameter(Mandatory=$true)][String]$JSON
)
$Verb = "POST"
$ResourceType = "docs";
$ResourceLink = "dbs/$DBName/colls/$CollectionName"
$dateTime = [DateTime]::UtcNow.ToString("r")
$authHeader = Generate-MasterKeyAuthorizationSignature -verb $Verb -resourceLink $ResourceLink -resourceType $ResourceType -key $MasterKey -keyType "master" -tokenVersion "1.0" -dateTime $dateTime
$header = #{authorization=$authHeader;"x-ms-version"="2017-02-22";"x-ms-date"=$dateTime}
$contentType= "application/json"
$queryUri = "$EndPoint$ResourceLink/docs"
$result = Invoke-RestMethod -Method $Verb -ContentType $contentType -Uri $queryUri -Headers $header -Body $JSON
return $result.statuscode
}
$CosmosDBEndPoint = "https://<omitted>.documents.azure.com:443/"
$DBName = "database"
$CollectionName = "container"
$MasterKey = "<omitted>=="
$SomeObject = [PSObject]#{ id = 1 ; Application = "Ops"; Environment = "Dev"; adKey = "555-555-5555"; }
Post-CosmosDocuments -EndPoint $CosmosDBEndPoint -MasterKey $MasterKey -DBName $DBName -CollectionName $CollectionName -JSON ($SomeObject | ConvertTo-Json)
returns a 400 every time, I am not sure what is wrong with the request.
Based on the Powershell script samples, I see you are missing the headers:
x-ms-documentdb-partitionkey
User-Agent
2018-12-31 as x-ms-version
Adding the response body that you are getting would also help.
it is working now
I am not sure why I was getting a 400. perhaps I the timing on when I created the collection was off.

Unable to print inner XML values using PowerShell

I am trying to retrieve data from a SOAP web service using PowerShell. I am having issues retrieving values from the inner XML. The code is listed below.
In the [XML]$body2 variable if I pass the $queryid variable then the values in the else condition of the Response function does not print. I debugged the code and $queryid is getting the correct value. If I remove $queryid and replace it with a number then the values print fine.
Edit: The $queryid should be set to a number which I then want to use in $body2.
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
$id1 = "1"
$id2 = "2"
$global:queryid = ""
$array = #()
function Main() {
$uri = "https://mywebsite/CatalogTasks.asmx?WSDL"
[XML]$body = #"
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope">
<soap:Body>
<Request xmlns="http://mywebsite.com">
<user>user_id</user>
<pwd>password</pwd>
<fields>[Number],Tech name],[Description],[State]</fields>
<condition>[State]='Open'</condition>
<orderBy>[Number]</orderBy>
</Request>
</soap:Body>
</soap:Envelope>
"#
Response $uri $body $id1
Write-Host "Id: $global:queryid"
$queryid = $global:queryid
[XML]$body2 = #"
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope">
<soap:Body>
<RetrieveXML xmlns="http://mywebsite.com">
<user>user_id</user>
<pwd>password</pwd>
<queryId>$queryid</queryId>
</RetrieveXML>
</soap:Body>
</soap:Envelope>
"#
Response $uri $body2 $id2
}
function Response ($url, $bodyy, $id) {
$resp = (Invoke-WebRequest -Uri $url -Body $bodyy -ContentType "text/xml" -Proxy "http://proxy" -ProxyUseDefaultCredentials -Method POST)
if ($id -eq 1) {
$soap = $resp.Content
$xpathfilter = "//*[local-name()='QueryId']"
$Element = Select-Xml -Content $soap -XPath $xpathfilter
$global:queryid = $Element.Node.'#text'
} else {
$soap2 = $resp.Content
$filter = "//*[local-name()='Number']"
$Element2 = Select-Xml -Content $soap2 -XPath $filter
$number = $Element2.Node.'#text'
[array]$array = ($number)
foreach ($i in $array){
Write-Host $i
}
}
}
Main

powershell soaprequest with username and password

I need to make a Soap Request from Powershell, I am on Powershell 2.0, I can find lots of examples but I also need to include a username and password to get through the api.
I get a response of
Exception calling "GetResponse" with "0" argument(s): "The underlying connectio
n was closed: An unexpected error occurred on a send."
My Powershell code (I have redacted some sensitive stuff) is
function Execute-SOAPRequest
(
[Xml] $SOAPRequest,
[String] $URL
)
{
write-host "Sending SOAP Request To Server: $URL"
$soapWebRequest = [System.Net.WebRequest]::Create($URL)
$soapWebRequest.Headers.Add("SOAPAction","`"`"")
$soapWebRequest.ContentType = "text/xml;charset=`"utf-8`""
$soapWebRequest.Accept = "text/xml"
$soapWebRequest.Method = "POST"
$username = "USERNAME"
$password = "Password" | ConvertTo-SecureString -asPlainText -Force
$cred = New-Object System.Management.Automation.PSCredential($username,$password)
$soapWebRequest.Credentials = $cred
#$soapWebRequest.Proxy.Credentials = [System.Net.CredentialCache]::DefaultNetworkCredentials
#$soapWebRequest.UseDefaultCredentials = $true
write-host $soapWebRequest
write-host "Initiating Send."
$requestStream = $soapWebRequest.GetRequestStream()
write-host $requestStream
$SOAPRequest.Save($requestStream)
$requestStream.Close()
write-host "Send Complete, Waiting For Response."
$resp = $soapWebRequest.GetResponse()
$responseStream = $resp.GetResponseStream()
$soapReader = [System.IO.StreamReader]($responseStream)
$ReturnXml = [Xml] $soapReader.ReadToEnd()
$responseStream.Close()
write-host "Response Received."
return $ReturnXml
}
$url = 'https://zkncsavia049.via.novonet:7180/ws/activeservices/pmspapi_nomination'
$soap = [xml]#'
<?xml version="1.0" encoding="utf-8"?>
<soapenv:Envelope xmlns:pms="http://www.mydomain.co.uk/pmsapi_nomination" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:wssu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
<soapenv:Header><wsse:Security><wsse:UsernameToken wssu:Id="UsernameToken-4B81F4838BB6D8A60715299310629901"><wsse:Username>igyadmin</wsse:Username>
<wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">V3rm0nt</wsse:Password>
<wsse:Nonce EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary">x9DSipKzGHLbvyCOXKIY6A==</wsse:Nonce>
<wssu:Created>2018-06-25T12:51:02.986Z</wssu:Created></wsse:UsernameToken></wsse:Security>
</soapenv:Header>
<soapenv:Body>
<pms:pmsapi_nomination.getlist.ApiRequest xmlns:ns2="http://www.mydomain.co.uk/pmsapi_nomination">
<ApiRequest>
<LogonInfo>
<BusinessGroup>GMP</BusinessGroup>
<AdminGroup>ADMN</AdminGroup>
</LogonInfo>
<BUSINESS_GROUP>
<value>GMP</value>
</BUSINESS_GROUP>
<CONTEXT>
<value>F</value>
</CONTEXT>
<REFNO>
<value>0039760</value>
</REFNO>
</ApiRequest>
</pms:pmsapi_nomination.getlist.ApiRequest>
</soapenv:Body>
</soapenv:Envelope>
'#
$ret = Execute-SOAPRequest $soap $url
I can get the call to work through SOAPUI the raw XML is
POST http://zkncsavia049.via.novonet:7180/ws/activeservices/pmsapi_nomination/HTTP/1.1
Accept-Encoding: gzip,deflate
Content-Type: text/xml;charset=UTF-8
SOAPAction: ""
Content-Length: 1541
Host: zkncsavia049.via.novonet:7180
Connection: Keep-Alive
User-Agent: Apache-HttpClient/4.1.1 (java 1.5)
<soapenv:Envelope xmlns:pms="http://www.mydomain.co.uk/pmsapi_nomination" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:wssu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
<soapenv:Header><wsse:Security><wsse:UsernameToken wssu:Id="UsernameToken-78C15367B2B1287BB3153000735070610"><wsse:Username>USERNAME</wsse:Username><wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">password</wsse:Password><wsse:Nonce EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary">q5B6XRmHsecmHouCqH03qA==</wsse:Nonce><wssu:Created>2018-06-26T10:02:30.696Z</wssu:Created></wsse:UsernameToken></wsse:Security>
</soapenv:Header>
<soapenv:Body>
<pms:pmsapi_nomination.getlist.ApiRequest xmlns:ns2="http://www.aquilauk.co.uk/pmsapi_nomination">
<ApiRequest>
<LogonInfo>
<BusinessGroup>GMP</BusinessGroup>
<AdminGroup>ADMN</AdminGroup>
</LogonInfo>
<BUSINESS_GROUP>
<value>GMP</value>
</BUSINESS_GROUP>
<CONTEXT>
<value>F</value>
</CONTEXT>
<REFNO>
<value>0039761</value>
</REFNO>
</ApiRequest>
</pms:pmsapi_nomination.getlist.ApiRequest>
</soapenv:Body>
</soapenv:Envelope>
There is an SSL certificate on the system but not for port 7180.
I'm also very much a powershell novice, I only write it a couple of times a year.
So the fail is on
$resp = $soapWebRequest.GetResponse()
but I guess that the setting up of $soapWebRequest may be the problem

powershell -> SOAP request with additional Headers

Hi i need a help with proper soap request. I tried few ways do it but no luck.
Need to generate such soap request:
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope"><soap:Header><Action xmlns="http://schemas.xmlsoap.org/ws/2004/08/addressing" xmlns:env="http://www.w3.org/2003/05/soap-envelope" env:mustUnderstand="true"/><MessageID xmlns="http://schemas.xmlsoap.org/ws/2004/08/addressing">uuid:..............</MessageID><ReplyTo xmlns="http://schemas.xmlsoap.org/ws/2004/08/addressing"><Address>http://www.w3.org/2004/08/addressing/anonymous</Address></ReplyTo><To xmlns="http://schemas.xmlsoap.org/ws/2004/08/addressing" xmlns:env="http://www.w3.org/2003/05/soap-envelope" env:mustUnderstand="true">host_url</To><wsse:Security xmlns:env="http://www.w3.org/2003/05/soap-envelope" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" env:mustUnderstand="true"><wsse:UsernameToken><wsse:Username xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">$login</wsse:Username><wsse:Password xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" wsse:Type="http://docs.oas
is-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">$password</wsse:Password></wsse:UsernameToken></wsse:Security></soap:Header>
<soap:Body>
................
</soap:Body>
</soap:Envelope>
i stucked on this getting iis internal error 500:
(...)
write-host "Sending SOAP Request To Server: $URL"
$soapWebRequest = [System.Net.WebRequest]::Create($URL)
$soapWebRequest.Headers.Add("SOAPAction","`"MethodName`"")
$soapWebRequest.ContentType = "application/soap+xml;charset=`"utf-8`";action=`"host/MethodName`""
$soapWebRequest.Method = "POST"
write-host "Initiating Send."
$requestStream = $soapWebRequest.GetRequestStream()
$SOAPRequest.Save($requestStream)
$requestStream.Close()
write-host "Send Complete, Waiting For Response."
$resp = $soapWebRequest.GetResponse()
$responseStream = $resp.GetResponseStream()
$soapReader = [System.IO.StreamReader]($responseStream)
$ReturnXml = [Xml] $soapReader.ReadToEnd()
$responseStream.Close()
write-host "Response Received."
return $ReturnXml
}
$url = 'host.asmx'
$soap = [xml]#"
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:flow="host">
<soap:Header/>
<soap:Body>
.....
</soap:Body>
</soap:Envelope>
"#
$ret = Execute-SOAPRequest $soap $url; $ret | Export-Clixml "test-$(Get-date -f yyyy-MM-dd-mm-ss).xml";
Your headers seem odd mixing up escaped quotes you actually don't need.
Try replacing
$soapWebRequest.Headers.Add("SOAPAction","`"MethodName`"")
by
$soapWebRequest.Headers.Add("SOAPAction","MethodName")
as well as
$soapWebRequest.ContentType = "application/soap+xml;charset=`"utf-8`";action=`"host/MethodName`""
by
$soapWebRequest.ContentType = "application/soap+xml; charset=utf-8";