PowerShell Error: The Underlying connection was closed - powershell

I am trying to use the Invoke-WebRequest cmdlet (for the first time) to connect to the web interface for a Sharp printer. So far, the code I have is the following:
$cred = Get-Credential
$url = 'http://<IP address of printer>/login.html?/main.html'
$login = Invoke-WebRequest $url -SessionVariable printer -Method Get
$login.Forms[0].Fields.element10002 = $cred.UserName
$login.Forms[0].Fields.element10002 =
$cred.GetNetworkCredential().Password
$mainPage = Invoke-WebRequest -Uri ($url + $login.Forms[0].Action) `
-WebSession $printer -Body $login -Method Post
...but I keep getting this error:
Invoke-WebRequest : The underlying connection was closed: The connection
was closed unexpectedly.
At line:6 char:13
+ $mainPage = Invoke-WebRequest -Uri ($url + $login.Forms[0].Action) -W
...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation:
(System.Net.HttpWebRequest
:HttpWebRequest) [Invoke-WebRequest], WebException
+ FullyQualifiedErrorId :
WebCmdletWebResponseException,Microsoft.Powe
rShell.Commands.InvokeWebRequestCommand
This line of code does not cause an error:
$login = Invoke-WebRequest $url -SessionVariable printer -Method Get
But this line does:
$mainPage = Invoke-WebRequest -Uri ($url + $login.Forms[0].Action) `
-WebSession $printer -Body $login -Method Post
I am using PS version 5.1, and Tls12 on a Windows 7 box. After some Googling, it seems like this problem might have something to do with the version of Tls. but I'm not sure what to change it to.
Does anybody have any ideas? - #leah_cyberpadawan

The following two solutions have worked for me when working with endpoints that may have self-signed certificates or TLS 1.2-only supported:
[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor [System.Net.SecurityProtocolType]::Tls12
Add-Type -TypeDefinition #'
using System.Net;
using System.Security.Cryptography.X509Certificates;
public class TrustAllCertsPolicy : ICertificatePolicy
{
public bool CheckValidationResult(ServicePoint sp, X509Certificate cert, WebRequest req, int certProblem)
{
return true;
}
}
'#
[System.Net.ServicePointManager]::CertificatePolicy = New-Object -TypeName TrustAllCertsPolicy
[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor [System.Net.SecurityProtocolType]::Tls12
[System.Net.ServicePointManager]::ServerCertificateValidationCallback = {$true}

Related

Unable to ingest JSON stream data to Azure Event Hub

I would like to post the JSON results which I am getting from an API endpoint to the Azure Event Hub $default consumer group but I am getting the below error:
Invoke-RestMethod : The remote server returned an error: (401) Unauthorized.
At H:\Users\User1 - scripts\get_mel_streetparking_data.ps1:34 char:1
+ Invoke-RestMethod -Uri $URI -Method $method -Headers $headers -Body $res ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke- RestMethod], WebException
+ FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeRestMethodCommand
I wrote the below piece of powershell script where the following piece of get code runs fine:
$url = "https://data.melbourne.vic.gov.au/resource/vh2v-4nfs"
$apptoken = "abcdasdadaaf"
# 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
but below piece of code fails with the above given error:
$method = "POST"
$URI = "https://[servicebusNamespace].servicebus.windows.net/[eventHubPath]/messages"
$signature = "SharedAccessSignature sr=[servicebusNamespace].servicebus.windows.net%2feventhub- streetparking&sig=%3dgZfDHEGN8lVEGgqu4N64TW70BLuSKARSKgMPeRByc%5d&se=604985&skn=RootManageSharedAccessKe"
# API headers
$headers = #{
"Authorization"=$signature;
"Content-Type"="application/json";
}
# create Request Body
#$body = "$results"
# execute the Azure REST API
Invoke-RestMethod -Uri $URI -Method $method -Headers $headers -Body $results
I generated SAS token with the help of the below code:
[Reflection.Assembly]::LoadWithPartialName("System.Web")| out-null
$URI="[servicebusNamespace].servicebus.windows.net/[eventHubPath]"
$Access_Policy_Name="RootManageSharedAccessKey"
$Access_Policy_Key="Root key value"
#Token expires now+3000
$Expires=([DateTimeOffset]::Now.ToUnixTimeSeconds())+3000
$SignatureString=[System.Web.HttpUtility]::UrlEncode($URI)+ "`n" + [string]$Expires
$HMAC = New-Object System.Security.Cryptography.HMACSHA256
$HMAC.key = [Text.Encoding]::ASCII.GetBytes($Access_Policy_Key)
$Signature = $HMAC.ComputeHash([Text.Encoding]::ASCII.GetBytes($SignatureString))
$Signature = [Convert]::ToBase64String($Signature)
$SASToken = "SharedAccessSignature sr=" + [System.Web.HttpUtility]::UrlEncode($URI) + "&sig=" + [System.Web.HttpUtility]::UrlEncode($Signature) + "&se=" + $Expires + "&skn=" + $Access_Policy_Name
$SASToken
Please help me why am I seeing unauthorized error
It was my bad that I did not replace the below values before the SAS token generation.
$Access_Policy_Name="RootManageSharedAccessKey"
$Access_Policy_Key="Root key value"

Team City build step with Powershell Invoke-RestMethod fails if URI contains URL encoded value

I have a build step in TeamCity which sends an HTTP request, like this:
$headers = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"
$headers.Add("Token", "%TOKEN%")
$uri = 'https://host/apps/branches/%BRANCH_NAME%/builds'
$response = Invoke-RestMethod $uri -Method 'GET' -Headers $headers
Write-Host "##teamcity[setParameter name='url' value='$uri']"
It works perfectly when %BRANCH_NAME% actually contains simple branch names, like ' master', 'beta', 'dev'.
But it works not so good when %BRANCH_NAME% is release%2F2019-DEC (URL encoded value of release/2019-DEC)
I tried the same script on local Powershell, and it worked flawlessly, but when I run it as TeamCity build step I receive the following error:
Invoke-RestMethod : The remote server returned an error: (404) Not Found.
At C:\TeamCityBuildAgent4\temp\buildTmp\powershell7367326510068615884.ps1:5 char:13
+ $response = Invoke-RestMethod $uri -Method 'GET' -Headers $headers
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-RestMethod], WebExc
eption
+ FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeRestMethodCommand
##teamcity[setParameter name='url' value='https://host/app/branches/release%2F2019-DEC/']
I tried to escape the percent sign using the extra % sign as in Using the percent sign in TeamCity build scripts, but unfortunately, it returns the same error.
Any ideas?
Solved:
Seemingly issue was caused by the old version of PowerShell on Agent, which caused the behavior described in Team City build step with Powershell Invoke-RestMethod fails if URI contains URL encoded value
That means that no extra percent signs are actually needed, we can URL encode value inside the script.
So the final version will look like:
function fixuri($uri){
$UnEscapeDotsAndSlashes = 0x2000000;
$SimpleUserSyntax = 0x20000;
$type = $uri.GetType();
$fieldInfo = $type.GetField("m_Syntax", ([System.Reflection.BindingFlags]::Instance -bor [System.Reflection.BindingFlags]::NonPublic));
$uriParser = $fieldInfo.GetValue($uri);
$typeUriParser = $uriParser.GetType().BaseType;
$fieldInfo = $typeUriParser.GetField("m_Flags", ([System.Reflection.BindingFlags]::Instance -bor [System.Reflection.BindingFlags]::NonPublic -bor [System.Reflection.BindingFlags]::FlattenHierarchy));
$uriSyntaxFlags = $fieldInfo.GetValue($uriParser);
$uriSyntaxFlags = $uriSyntaxFlags -band (-bnot $UnEscapeDotsAndSlashes);
$uriSyntaxFlags = $uriSyntaxFlags -band (-bnot $SimpleUserSyntax);
$fieldInfo.SetValue($uriParser, $uriSyntaxFlags);
}
$headers = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"
$headers.Add("X-API-Token", "%TOKEN%")
$branch = [System.Web.HttpUtility]::UrlEncode('release/2019-DEC1')
$uri = New-Object System.Uri -ArgumentList ("https://host/apps/branches/$branch")
fixuri $uri
$response = Invoke-RestMethod $uri -Method 'GET' -Headers $headers
Special thanks to #Peska

Using power shell to right a put method for SSRS API deployment for setting shareddataset

I want to use PowerShell to set shareddataset for a report using SSRS API.
I have already tried to use PowerShell to get shareddataset using SSRS API successfully. But failed to use put method.
Success using get method:
$Cred = Get-Credential
$Url = "http://localhost/Reports/api/v2.0/DataSets"
`
`$Body = #{
Path ="/Shared_data_sets/P_Calculate_date_Default_key";
output_mode = "csv";
earliest_time = "-2d#d";
latest_time = "-1d#d";
}
Invoke-RestMethod -Method 'GET' -Uri $url -Credential $Cred -Body $body -OutFile output.csv
failed using put method:
$Cred = Get-Credential
$Url = "http://localhost/Reports/api/v2.0/Reports(23a6af79-9de3-49cb-b66b-625d3ff3909b)/SharedDataSets"
$Body = #{
Id = "935be257-5a65-4c0d-b372-d5a6a188daf6";
Name = "P_Calculate_Date_Default_Key";
Path = "/Shared_data_sets/P_Calculate_date_Default_key";
Type = "DataSet" ;
}
Invoke-RestMethod -Uri $Url -Credential $Cred -Body $body -Method 'PUT'
Error returned is
The remote server returned an error: (400) Bad Request
detailed error:
Invoke-RestMethod : The remote server returned an error: (400) Bad Request. At line:12 char:1 + Invoke-RestMethod -Uri $Url -Credential $Cred -Body $body -Method 'PU ... + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-RestMethod], WebException + FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeRestMethodCommand
I hope the put method could be working. I thought I was using the same way as the get method but it still failed.
I tried another way but still failed :
$Cred = Get-Credential
$Url = "http://localhost/Reports/api/v2.0/Reports(23a6af79-9de3-49cb-b66b-625d3ff3909b)/SharedDataSets"
$Body = #{
Id = "935be257-5a65-4c0d-b372-d5a6a188daf6"
Name = "P_Calculate_Date_Default_Key"
Path = "/Shared_data_sets/P_Calculate_date_Default_key"
Type = "DataSet"
}| ConvertTo-Json
Invoke-RestMethod -Uri $Url -Credential $Cred -Body $body -Method PUT -ContentType "application/json" | Out-Null
Just for you to know that for the put method, i have already tested on postman and it works. So I guess currently it is only due to some logic in powershell side inconsistent.
in postman I put the link as :
http://localhost/Reports/api/v2.0/Reports(23a6af79-9de3-49cb-b66b-625d3ff3909b)/SharedDataSets
Body as :
[
{
"Id": "935be257-5a65-4c0d-b372-d5a6a188daf6",
"Name": "P_Calculate_Date_Default_Key",
"Path": "/Shared_data_sets/P_Calculate_date_Default_key",
"Type": "DataSet"
}
]
I tried your recommendation and it shows below , I have added it below all:
PS C:\Users\dkx42a8adm> $Cred = Get-Credential
$Url = "http://localhost/Reports/api/v2.0/Reports(23a6af79-9de3-49cb-b66b-625d3ff3909b)/SharedDataSets"
$Body = #{
Id = "935be257-5a65-4c0d-b372-d5a6a188daf6"
Name = "P_Calculate_Date_Default_Key"
Path = "/Shared_data_sets/P_Calculate_date_Default_key"
Type = "DataSet"
}| ConvertTo-Json
Write-Output $Body
Invoke-RestMethod -Uri $Url -Credential $Cred -Body $body -Method PUT -ContentType "application/json"
$error[0]|format-list -force
cmdlet Get-Credential at command pipeline position 1
Supply values for the following parameters:
{
"Path": "/Shared_data_sets/P_Calculate_date_Default_key",
"Name": "P_Calculate_Date_Default_Key",
"Id": "935be257-5a65-4c0d-b372-d5a6a188daf6",
"Type": "DataSet"
}
Invoke-RestMethod : The remote server returned an error: (400) Bad Request.
At line:14 char:1
+ Invoke-RestMethod -Uri $Url -Credential $Cred -Body $body -Method PUT ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-RestMethod], WebException
+ FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeRestMethodCommand
Exception : System.Net.WebException: The remote server returned an error: (400) Bad Request.
at Microsoft.PowerShell.Commands.WebRequestPSCmdlet.GetResponse(WebRequest request)
at Microsoft.PowerShell.Commands.WebRequestPSCmdlet.ProcessRecord()
TargetObject : System.Net.HttpWebRequest
CategoryInfo : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-RestMethod], WebException
FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeRestMethodCommand
ErrorDetails :
InvocationInfo : System.Management.Automation.InvocationInfo
ScriptStackTrace : at , : line 14
PipelineIterationInfo : {}
PSMessageDetails :

Powershell WebRequest GET Succeeds but DELETE fails w/ 404

Very confused on this issue. Here is what I am dealing with currently.
I have an API endpoint which looks like this /subscriptions/:id. This endpoint serves as both a GET & a DELETE endpoint. When I run a GET, it returns the object as it normally does, but changing the action to a DELETE gives me back a 404 for the very same resource which was just returned in the GET, I don't know why.
Here is my Powershell code.
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
$user = '*********'
$pass = ConvertTo-SecureString '*********' -AsPlainText -Force
$cred = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $user, $pass
$base = "https://*********.hosted.xmatters.com/api/xm/1"
$del_path = "$base/subscriptions/********uuid***********"
$path = "$base/subscriptions"
$payload = #{
id = '********uuid***********'
description = '**** NEW DESCRIPTION ****'
}
$params = $payload | ConvertTo-Json
// **** SUCCESS
$thing = Invoke-WebRequest -Credential $cred -Uri $del_path -Method GET
// **** FAILS
$thing = Invoke-WebRequest -Credential $cred -Uri $del_path -Method DELETE
// **** FAILS
$thing = Invoke-WebRequest -Credential $cred -Uri $path -Method POST -Body $params -ContentType 'application/json'
So, like mentioned previously, I am POSITIVE that the resource exists from the API. I am able to get it when running a GET but both POST (to update) & DELETE throw 404 errors. Here is the error I get.
Invoke-WebRequest : The remote server returned an error: (404) Not Found.
At \\mmfile\ct32373$\Appsense\Desktop\Line of Business Revisions.ps1:24 char:10
+ $thing = Invoke-WebRequest -Credential $cred -Uri $del_path -Method D ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (System.Net.HttpWebRequest:HttpWebReque
st) [Invoke-WebRequest], WebException
+ FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Comman
ds.InvokeWebRequestCommand
The strange thing is that I am able to run the DELETE request successfully using POSTMAN, however because of the volume of data I need to process, this is not a good option

How to attach CSV file to Service Now incident via REST API using PowerShell?

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