PowerShell DownloadFile() not working for Nexus artifact download - powershell

I am trying to download the latest artifact from a Nexus repository. If I give the exact zip file name, it is working fine. When I try to download using a generic URL (REST URI) its giving me 401 Unauthorized. I have tried Invoke-WebRequest, WebClient and Invoke-RestMethod as well.
$wc = New-Object System.Net.WebClient
$URL = "http://nexusrepo/nexus/service/local/artifact/maven/redirect?r=my-snapshot&g=my.group.id&a=my.artifact.id&v=1.10.0-SNAPSHOT&c=win32.win32.x86_64&p=zip"
$username = "nexus"
$password = "nexus"
$auth = $username + ":" + $password
[System.Net.ServicePointManager]::ServerCertificateValidationCallback = {$true}
$Encoded = [System.Text.Encoding]::UTF8.GetBytes($auth)
$EncodedPassword = [System.Convert]::ToBase64String($Encoded)
$wc.Headers.Add("Accept-Encoding", "gzip,deflate")
$wc.Credentials = New-Object System.Net.NetworkCredential($username, $password)
$wc.Headers.Add("Authorization", "Basic " + $EncodedPassword)
$wc.UseDefaultCredentials = $false
$wc.DownloadFile($URL, "MyApp.zip")
Exception calling "DownloadString" with "1" argument(s): "The remote server
returned an error: (401) Unauthorized."
At C:\temp\NexusDownloadTest\Nexus-Download.ps1:39 char:1
+ $weburl = $wc.DownloadString($URL)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : WebException
Can someone please help me on this?

As an workaround, I went back to Invoke-WebRequest and first got the redirected URL by using MaximumRedirection 0 and then submitted that URL as a request. The below code works.
$URL = "http://nexusrepo/nexus/service/local/artifact/maven/redirect?r=my-snapshot&g=my.group.id&a=my.artifact.id&v=1.10.0-SNAPSHOT&c=win32.win32.x86_64&p=zip"
$username = "nexus"
$password = "nexus"
$auth=$username+":"+$password
$Encoded = [System.Text.Encoding]::UTF8.GetBytes($auth)
$EncodedPassword = [System.Convert]::ToBase64String($Encoded)
$latestArtifactURL = Invoke-WebRequest $url -Headers #{Authorization = "Basic $EncodedPassword"} -MaximumRedirection 0
$redirectedMessage = "$latestArtifactURL".IndexOf('http:')
$targetURL = "$latestArtifactURL".SubString("$redirectedMessage")
Invoke-WebRequest $targetURL -Headers #{Authorization = "Basic $EncodedPassword"} -OutFile "MyApp.zip"

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"

Changed authentication flow and now receiving ERROR: Invoke-RestMethod : The underlying connection was closed: An unexpected error occurred on a send

EDIT:
I am trying to read a token value from a text file to build a header that can be used for a REST API call.
If I request a temporary token using a credential (option T) the subsequent REST method works but if I read the permanent token in from text file (option P) on the local file system the method that worked before with the temp token fails.
ERROR: Invoke-RestMethod : The underlying connection was closed: An
unexpected error occurred on a send.
Invoke-Test.ps1 (41, 13): ERROR: At Line: 41
char: 13 ERROR: + $response = Invoke-RestMethod -Method Get -Headers
$headers -Uri "$ap ... ERROR: +
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ERROR: +
CategoryInfo : InvalidOperation:
(System.Net.HttpWebRequest:HttpWebRequest) [Invoke-RestMethod],
WebException ERROR: + FullyQualifiedErrorId :
WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeRestMethodCommand
Code:
# Allow the use of self-signed SSL certificates, TLS
[System.Net.ServicePointManager]::ServerCertificateValidationCallback = { $True }
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
$server = "https://192.168.1.1"
$app_rest = "$server/api/v1"
$choice = Read-Host "Enter T or P"
If($choice -eq "T") {
Write-Host "Try and obtain temp token"
$Username = Read-Host "Enter Username"
$Password = Read-Host "Enter Password" -AsSecureString
$BSTR = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($Password)
$Password = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($BSTR)
$creds = #{
username = $Username
password = $Password
grant_type = "password"
};
$response = Invoke-RestMethod -Method Post -Uri "$server/api/token" -Body $creds
$token = $response.access_token
Write-Host $token
}
ElseIf($choice = "P") {
Write-Host "Try and use perm token"
#$token = [IO.File]::ReadAllText("C:\temp\SBXtoken.txt")
$token = Get-Content "C:\temp\SBXtoken.txt" -Raw
Write-Host $token
}
Else {Break;}
$headers = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"
$headers.Add("Authorization", "Bearer $token")
$response = Invoke-RestMethod -Method Get -Headers $headers -Uri "$app_rest/status"
$status = $response.status;
Write-Host $status
Make sure you're running as administrator
Change your code because powershell doesn't respond to operators the same as formal programming languages.
ElseIf($choice -eq "P") {
Write-Host "Try and use perm token"
#$token = [IO.File]::ReadAllText("C:\temp\SBXtoken.txt")
$token = Get-Content "C:\temp\SBXtoken.txt" -Raw
Write-Host $token
}

Invoke-RestMethod with PowerShell

I am trying to post data to a URL using PowerShells Invoke-RestMethod however I constantly keep getting this message:
+ $response.RawContent​
+ ~
Unexpected token '​' in expression or statement.
+ CategoryInfo : ParserError: (:) [], ParentContainsErrorRecordException
+ FullyQualifiedErrorId : UnexpectedToken
Am I missing an escape of a string literal somewhere or malformed quote mark?
$user = "username"
$pass = "password"
$base64AuthInfo = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f $user, $pass)))
$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')
$uri = "http://myurl.com"
$params = #{
message = "hello world"
}
$response = Invoke-RestMethod -Method Post -Headers $headers -Uri $uri -Body $params
$response.RawContent​
Removed $response.RawContent and it works. Changed it to echo $response to see output.

Trying to use getElementById in Powershell with IE 11, error Exception from HRESULT: 0x800A01B6

I'm trying to automate logging in on a website, but I can't seem to use getElementById. getElementsByClassName("whatever")[0] seems to work, but the elements I need don't have class names and I can't change that.
I'm using PS 5, IE 11. Here's an example of my code, and the resulting exception.
$url = "https://google.com"
$ie = New-Object -com "InternetExplorer.Application"
$ie.visible = $true
$ie.navigate($url)
while ($ie.Busy){Start-Sleep -Milliseconds 1000}
$ie.document.getElementById("lst-ib").value = "test"
Error:
Exception from HRESULT: 0x800A01B6
At C:\gtest.ps1:6 char:1
+ $ie.document.getElementById("lst-ib").value = "test"
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : OperationStopped: (:) [], NotSupportedException
+ FullyQualifiedErrorId : System.NotSupportedException
logging into google
$r = Invoke-WebRequest "https://google.bg" -SessionVariable g
$r = Invoke-WebRequest 'https://accounts.google.bg/' -WebSession $g
$r.Forms['gaia_loginform'].Fields.Email = 'someuser#gmail.com'
$r.Forms['gaia_loginform'].Fields.Passwd = 'somepass'
$r = Invoke-RestMethod $r.Forms['gaia_loginform'].Action -Body $r.Forms['gaia_loginform'] -Method $r.Forms['gaia_loginform'].Method -WebSession $g
$r = Invoke-WebRequest https://google.bg -WebSession $g
$r.Content > tmp2.html
hope that helps
Try using
$ie.Document.documentElement.getElementByClassName();
$ie.Document.documentElement.getElementByTagName();
$ie.Document.documentElement.getAttribute();
and for id name tagname use this
$ie.Document.IHTML3_getElementById();
$ie.Document.IHTML3_getElementByName();
$ie.Document.IHTML3_getElementByTagName();

Download artifact from Jenkins using PowerShell

I try download artifact from Jenkins using PowerShell, like this:
$webClient = new-object System.Net.WebClient
$webClient.Credentials = New-Object System.Net.NetworkCredential ("username", "password")
$url = "http://jenkins/job/jobName/lastSuccessfulBuild/artifact/*zip*/archive.zip"
$localfilename = "C:\Test\archive.zip"
$webClient.DownloadFile($url, $localfilename)
I get exception:
Exception calling "DownloadFile" with "2" argument(s): "The remote
server retur ned an error: (403) Forbidden." At C:\ps2.ps1:20 char:28
+ $webclient.DownloadFile <<<< ($url, $localfilename)
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : DotNetMethodException
If I try download artifact using wget it works:
wget --auth-no-challenge --http-user=username --http-password=password http://jenkins/job/jobName/lastSuccessfulBuild/artifact/*zip*/archive.zip
If I using wget without parameter --auth-no-challenge I get the same error - Forbidden.
Using this authorization in request header is working great:
# Create web client with authorization header
$webClient = new-object System.Net.WebClient
$credentialAsBytes = [System.Text.Encoding]::ASCII.GetBytes($userName + ":" + $password)
$credentialAsBase64String = [System.Convert]::ToBase64String($credentialAsBytes);
$webClient.Headers[[System.Net.HttpRequestHeader]::Authorization] = "Basic " + $credentialAsBase64String;
Do you have basic auth set up on your Jenkins box? If so try this
$webClient = new-object System.Net.WebClient
$creds = New-Object System.Net.NetworkCredential ("username", "password")
$url = "http://jenkins/job/jobName/lastSuccessfulBuild/artifact/*zip*/archive.zip"
$localfilename = "C:\Test\archive.zip"
$cache = new-object System.Net.CredentialCache
$cache.Add($url, "Basic", $creds)
$webclient.Credentials = $cache
$webClient.DownloadFile($url, $localfilename)
I have not tried this on Jenkins yet, but this is what I am using to download a file attached to an issue in Jira (https):
Invoke-WebRequest -uri "https://jira.xyz.com/login.jsp?os_username=$username&os_password=$jiraPassword&os_cookie=true" -UserAgent ([Microsoft.PowerShell.Commands.PSUserAgent]::InternetExplorer) -SessionVariable myWebSession
Invoke-WebRequest -uri $fileUrlPath -LocalOutFilePath $file -method get -UserAgent ([Microsoft.PowerShell.Commands.PSUserAgent]::InternetExplorer) -WebSession $myWebSession
Since Jenkins 2.0, CSRF is enabled by default which requires a session cookie to be provided. In this case you need additional step:
$crumbParams = #{
Headers = #{'Authorization' = 'Basic ' + [System.Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes("$($credentials.UserName):$($credentials.GetNetworkCredential().Password)"))}
Uri = "$baseUri/crumbIssuer/api/json"
SessionVariable = 'crumbSession'
}
[void] (Invoke-RestMethod #crumbParams)
Note that if you provide your credentials with domain, you might have to use $credentials.GetNetworkCredential().UserName if Jenkins expects only username without the domain. The $baseUri is the Jenkins address including http(s)://.
The previous command will save the session state in $crumbSession, from which you can extract the required cookie header:
$webClient = New-Object System.Net.WebClient
$webClient.Headers.Add([System.Net.HttpRequestHeader]::Cookie, $crumbSession.Cookies.GetCookieHeader($baseUri))
$webClient.Headers.Add([System.Net.HttpRequestHeader]::Authorization, 'Basic ' + [System.Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes("$($credentials.UserName):$($credentials.GetNetworkCredential().Password)")))
$webClient.DownloadFile($url, $localfilename)