Problems when calling an API - windows

We have two APIs that does a POST and GET requests. Both of them used to work perfectly fine but the API that does POST started giving an error:
Invoke-WebRequest : The underlying connection was: An unexpected error occurred on a receive.`
I have been trying to research for few days and all the KBs pointing to some sort of SSL/TLS and adding this piece of code:
[Net.ServicePointManager]::SecurityProtocol = "SystemDefault,Tls12, Tls11, Tls, Ssl3"
but I already had this code from the start. However, I cannot find a solution to my problem.
OS : Windows 2012
PowerShell Version: 4.0
function funName ($Val1, $Val2) {
[Net.ServicePointManager]::SecurityProtocol = "SystemDefault,Tls12, Tls11, Tls, Ssl3"
#[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
#[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls -bor [Net.SecurityProtocolType]::Tls11 -bor [Net.SecurityProtocolType]::Tls12
$url = "https://someAPI/post.request/do-something"
$user = "username"
$pass = "password"
$pair = "$($user):$($pass)"
$encodedCreds = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes($pair))
$basicAuthValue = "Basic $encodedCreds "
$Headers = #{
"Accept"="application/json"
Authorization = $basicAuthValue
}
$Body = #{
'#type' ='x'
parm1 = $Val1
parm2 = $Val2
}
#[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
Invoke-WebRequest -Uri $url -Headers $Headers -Method Post -Body $Body | Out-Null
}
## Deactivation Request ffffffff##
funName -RequestID Val1 adID Val2
As stated earlier, this used to work up until last week.

Set this to the top of your script:
Add-Type #"
using System.Net;
using System.Security.Cryptography.X509Certificates;
namespace myTrust
{
public class TrustAllCertsPolicy : ICertificatePolicy
{
public bool CheckValidationResult( ServicePoint srvPoint, X509Certificate certificate, WebRequest request, int certificateProblem)
{
return true;
}
}
}
"#
$AllProtocols = [System.Net.SecurityProtocolType]'Ssl3,Tls,Tls11,Tls12'
[System.Net.ServicePointManager]::SecurityProtocol = $AllProtocols
[System.Net.ServicePointManager]::CertificatePolicy = New-Object myTrust.TrustAllCertsPolicy

I was working on a similar request to retrieve data from API and I found out that I was calling my function as funName -val1 1234 val2 9999 where I was missing "-" on my seconda parameter. As soon as I fixed that it starting working again funName -val1 1234 -val2 9999 . Thanks Stackoverflow community for the help on this.

Related

PowerShell to download Zip file from GitHub API

I would like to write a PowerShell script to download the GitHub repo in ZIP format by following this instruction:
https://docs.github.com/en/rest/reference/repos#contents
$Token = 'MyUserName:MyPAT'
$Base64Token = [System.Convert]::ToBase64String([char[]]$Token)
$Headers = #{
"Authorization" = 'Basic {0}' -f $Base64Token;
"accept" = "application/vnd.github.v3+json"
}
$Uri = "https://api.github.com/repos/{owner}/{repo}/zipball"
$r = Invoke-WebRequest -Headers $Headers -Uri $Uri -Method Get | Out-File "D:\MyRepo.zip"
The code did download the zip file but I got this error message when I tried to open the zip file:
D:\MyRepo.zip
The archive is either in unknown format or damaged
I am very new to PowerShell, any help is appreciated!
You may need to look more closely at download-a-repository-archive-zip instructions. It says the response will have a 302 redirect to the URL for downloading. Invoke-WebRequest will not automatically redirect, but it will provide the response headers.
If you change your last line to be:
$response = Invoke-WebRequest -Headers $Headers -Uri $Uri -Method Get
you can review the $response object's Headers and issue another Invoke-WebRequest with the same headers and the 302 Uri:
$RedirectedResponse = Invoke-WebRequest -Headers $Headers -Uri $RedirectedURI -Method Get
$RedirectedResponse.Content will have the encoded file contents that you can decode and write to your local filesystem.
EDIT: I got to a system where I had GitHub access and tested the script. I found that the first response had a byte array with the zip file contents. This functionality is too useful not to share! Here's a script that works to download a repo:
$user = 'bjorkstromm'
$repo = 'depends'
$uri = "https://api.github.com/repos/$user/$repo/zipball/"
if(!$cred){$cred = Get-Credential -Message 'Provide GitHub credentials' -UserName $user}
$headers = #{
"Authorization" = "Basic " + [convert]::ToBase64String([char[]] ($cred.GetNetworkCredential().UserName + ':' + $cred.GetNetworkCredential().Password))
"Accept" = "application/vnd.github.v3+json"
}
$response = Invoke-WebRequest -Method Get -Headers $headers -Uri $uri
$filename = $response.headers['content-disposition'].Split('=')[1]
Set-Content -Path (join-path "$HOME\Desktop" $filename) -Encoding byte -Value $response.Content

How to update configuration in any environments in urban code using rest call?

I am trying to create rest api to update configuration in all environments in urban code.
Is there any rest client or do we need write any custom code.?
How do I start? Your kind suggestions please
Are you asking about updating environment properties? If so. I do this with Powershell.
$webUrl = "https://ibm-ucd.myCompany.com"
$ucdApiUserName = "yourCLIAccount"
$ucdApiPass = "yourCLIpassword"
$appName = "MyApplication"
$environment = "ADT"
$propertyNewValue = "myNewValue"
$credential = New-Object System.Management.Automation.PSCredential ($ucdApiUserName,(ConvertTo-SecureString $ucdApiPass -AsPlainText -Force))
####################################################################
## Bypass Cert Issues with connecting to HTTPS API
####################################################################
$certData = [string][System.Net.ServicePointManager]::CertificatePolicy
if ($certData -ne "TrustAllCertsPolicy")
{
add-type #"
using System.Net;
using System.Security.Cryptography.X509Certificates;
public class TrustAllCertsPolicy : ICertificatePolicy {
public bool CheckValidationResult(
ServicePoint srvPoint, X509Certificate certificate,
WebRequest request, int certificateProblem) {
return true;
}
}
"#
[System.Net.ServicePointManager]::CertificatePolicy = New-Object TrustAllCertsPolicy
}
$hash = [ordered] #{
"application" = "$AppName";
"environment" = "$environment";
"isSecure" = "false";
"name" = "myEnvProperty";
"value" = "$propertyNewValue"
}
$newValuesJson = $hash | ConvertTo-Json
Write-Host "Updating uDeploy environment properties for $environment"
$uri = "$WebUrl/cli/environment/propValue?"
Invoke-RestMethod -Method 'PUT' -ContentType "application/json" -Credential
$credential -uri $uri -Body $newValuesJson | Out-Null

why is no data being returned in my PowerShell script

add-type -AssemblyName System.Data.OracleClient
$username = "SYSTEM"
$password = "password"
$data_source = "production"
$connection_string = "User Id=$username;Password=$password;Data Source=$data_source"
try{
$statement = "SELECT SYSDATE FROM DUAL"
$con = New-Object System.Data.OracleClient.OracleConnection($connection_string)
$con.Open()
$cmd = $con.CreateCommand()
$cmd.CommandText = $statement
$result = $cmd.ExecuteReader()
# Do something with the results...
Write-Host $result + "data"
If($result.HasRows) {
try {
while ($result.Read())
{
"[0] : " + $result.GetValue(0)
}
}
catch
{
#log error
}
finally
{
$con.Close()
}
}
} catch {
Write-Error (“Database Exception: {0}`n{1}” -f `
$con.ConnectionString, $_.Exception.ToString())
} finally{
if ($con.State -eq ‘Open’) { $con.close() }
}
I am executing SELECT SYSDATE FROM DUAL
I am expecting 21-MAY-19
However no data is returned. (no error is presented either)
As mentioned in the above comments, you've to send the content of $result to PowerShells output stream. The output stream is used to realize the pipeline feature of Powershell. If you wrap your code in e.g. "myCode.ps1" and invoke it via:
.\myCode.ps1
The content of $result is pushed in the output stream (pipeline). Since no other cmdlet is attached to the call of myCode.ps1 the Powershell host (= your command line) will receive the content. The default behavior of the host is to dump the content.
So add the following to your code:
$result = $cmd.ExecuteReader()
# Return $result to the pipeline
$result
Read more about pipelines here and more about streams here.
UPDATE1: This link describes more or less the code sample of the question. Maybe the Orcale .NET data provider is missing. Add it via:
Add-Type -Path "PathToDll\Oracle.ManagedDataAccess.dll"
Hope that helps.

Adding a deployment step to call a http endpoint in Octopus Deploy

I am trying to create a new Octopus deploy step, which will call a http endpoint.
I have found the following step type that seems promising, but can get any documentation on it:
"Http Json Value Check
Gets json from http endpoint, looks-up a value by key and checks that it matches a predefined value. If value matches then script exists with a success code, if value does not match then script exists with a failure code."
I am not sure what to enter for the:
"Json Key" and the "Expected Value"
Has anyone done this? have an example or suggest a different method to achieve what I am trying?
Here is a PowerShell script I use to get the JSON from an endpoint and check for a valid Value. If I could remember where I got the code base before I modified it a little I would give credit to the original author. It will work with either a string or a regex.
#-------------------------------------------------------------------------
# Warmup.ps1
#-------------------------------------------------------------------------
[int]$returnme = 0
[int]$SleepTime = 5
[string]$regex = '[>"]?[aA]vailable["<]?'
[string]$strContains = $regex
# [string]$strContains = "log in"
[string]$hostName = hostname
[string]$domainName = (Get-WmiObject -Class Win32_NetworkAdapterConfiguration -Filter IPEnabled=TRUE -ComputerName .).DNSDomain
[string]$warmMeUp = "http://$hostName.$domainName/endpoint"
[string]$html = "Will Be Set Later"
#-------------------------------------------------------------------------
# Get-WebPage
#-------------------------------------------------------------------------
function Get-WebPage([string]$url)
{
try
{
$wc = new-object net.webclient;
$wc.credentials = [System.Net.CredentialCache]::DefaultCredentials;
[string]$pageContents = $wc.DownloadString($url);
$wc.Dispose();
}
catch
{
Write-Host "First Try Failed. Second Try in $SleepTime Seconds."
try
{
Start-Sleep -s $SleepTime
$wc = new-object net.webclient;
$wc.credentials = [System.Net.CredentialCache]::DefaultCredentials;
$pageContents = $wc.DownloadString($url);
$wc.Dispose();
}
catch
{
$pageContents = GetWebSiteStatusCode($url)
}
}
return $pageContents;
}
#-------------------------------------------------------------------------
# GetWebSiteStatusCode
#-------------------------------------------------------------------------
function GetWebSiteStatusCode
{
param (
[string] $testUri,
[int] $maximumRedirection = 5
)
$request = $null
try {
$request = Invoke-WebRequest -Uri $testUri -MaximumRedirection $maximumRedirection -ErrorAction SilentlyContinue
}
catch [System.Net.WebException] {
$request = $_.ErrorDetails.Message
}
catch {
Write-Error $_.Exception
return $null
}
return $request
}
#-------------------------------------------------------------------------
# Main Application Logic
#-------------------------------------------------------------------------
"Warming up '{0}'..." -F $warmMeUp;
$html = Get-WebPage -url $warmMeUp;
Write-Host "Looking for Pattern $strContains"
if ($html.ToLower().Contains("unavailable") -or !($html -match $strContains))
{
$returnme = -1
Write-Host "Warm Up Failed. html returned:`n" + $html
}
exit $returnme

Ruby and SOAP creating a web service proxy and namespace

I am SOAP novice, but I have been struggling with this for days and can't figure out where I'm going wrong. I'm trying to use Ruby to talk to VMware Site Recovery Manager
I have a powershell script that can successfully use to login. I want to take this powershell script and re-write it in ruby.
Here are the wsdl files:
https://srm-vcenter-a:8095/srm?wsdl
http://pastebin.com/xJ6AwLaC
https://srm-vcenter-a:8095/srm-Service?wsdl
http://pastebin.com/nmH5mzdH
The powershell code
$Server = "srm-vcenter-a"
$UserName = "administrator"
$Password = "mypw"
[System.Net.ServicePointManager]::ServerCertificateValidationCallback = {$true}
Write-Host "Connecting to SRM"
$webSvc = New-WebServiceProxy ("https://" + $Server + ":8095/srm-Service?wsdl") -Namespace SRM
$srm = New-Object SRM.SrmService
$srm.Url = "Https://" + $Server + ":9007"
$srm.Timeout = 600000
$srm.CookieContainer = New-Object System.Net.CookieContainer
$srmSvcRef = New-Object SRM.ManagedObjectReference
$srmSvcRef.Type = "SrmServiceInstance"
$srmSvcRef.Value = $srmSvcRef.Type
$srmSvcContent = $srm.RetrieveContent($srmSvcRef)
$srm.SrmLoginLocale($srmSvcRef, $UserName, $Password, $null)
$srmObject = New-Object System.Object
$srmObject | Add-Member -Type NoteProperty -value $Server -Name SRMServer
$srmObject | Add-Member -Type NoteProperty -value $srm -Name SRMService
$srmObject | Add-Member -Type NoteProperty -value $srmSvcContent -Name SRMContent
...
I have tried using Savon, soap4r, and handsoap and I don't know what I'm missing.
Here is the Savon code that doesn't work.
require 'savon'
require 'rubygems'
client = Savon.client do
wsdl "https://srm-vcenter-a:8095/srm?wsdl"
#endpoint "https://srm-vcenter-a:8095/srm-Service?wsdl"
endpoint "http://srm5-vcenter-a:9007"
namespace "https://srm-vcenter-a/sdk/srm"
#proxy "https://srm-vcenter-a:8095/srm-Service?wsdl"
ssl_version :TLSv1
ssl_verify_mode :none
convert_request_keys_to :lower_camelcase
end
message = { username: 'administrator', password: 'mypw' }
response = client.call(:srm_login_locale, message: message)
Thanks in advance for all help
Having taken a brief look at your code it appears that in PowerShell you have
$srm.SrmLoginLocale($srmSvcRef, $UserName, $Password, $null)
While in Ruby you have
message = { username: 'administrator', password: 'mypw' }
response = client.call(:srm_login_locale, message: message)
In the PowerShell code there are 4 values passed to the SrmLoginLocale method:
$srmSvcRef
$UserName
$Password
$null
In the ruby code you are missing the first parameter and the fourth parameter in your call. Try creating the equivalent of $srmSvcRef in ruby. I am not a ruby programmer but I think the code would look something like:
srm_svc_ref = { value: 'SrmServiceInstance', type: 'SrmServiceInstance'}
message = { _this: srm_svc_ref, username: 'administrator', password: 'mypw', locale: nil}
response = client.call(:srm_login_locale, message: message)

Resources