My PowerShell script:
$Params = #{
uri = "http://${API_URL}:${API_Port}/crumbIssuer/api/json";
Method = 'Get';
Headers = #{
Authorization = 'Basic ' + [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes("$(${API_User}):$(${API_Pass})"));
}
}
$API_Crumb = Invoke-RestMethod #Params
$headers = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"
$headers.Add("Jenkins-Crumb", $API_Crumb.Crumb)
$Params = #{
uri = "http://${API_URL}:${API_Port}/job/${API_Job}/build";
Method = 'Post';
Headers = $headers;
}
Invoke-RestMethod #Params
Error:
No valid crumb was included in the request
I modified the code as follows and it worked. Not sure though why previous code was throwing error.
$API_User = "admin"
$API_Pass = "password"
$API_URL = "localhost"
$API_Port = "8080"
$API_Job = "test01"
$h = #{}
$h.Add('Authorization', 'Basic ' + [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes("$(${API_User}):$(${API_Pass})")))
$Params = #{uri = "http://${API_URL}:${API_Port}/crumbIssuer/api/json";
Method = 'Get';
Headers = $h;}
$API_Crumb = Invoke-RestMethod #Params
$h.Add('Jenkins-Crumb', $API_Crumb.crumb)
$Params['uri'] = "http://${API_URL}:${API_Port}/job/${API_Job}/build"
$Params['Method'] = 'Post'
$Params['Headers'] = $h
Invoke-RestMethod #Params
Related
$Auth = "admin:password"
$JenkinsURL = "http://$Auth#172.24.235.27:8080/"
$JobName = "TestItem1"
$JobToken = "token"
$FullURL = "$JenkinsURL/job/$JobName/build?token=$JobToken"
Invoke-WebRequest -UseBasicParsing $FullURL
Above is the PowerShell code used for triggering Jenkins job. But while executing this I am facing "Authentication required" error. But the same command from curl is working fine.
I am not sure whether I am missing something in URL or missing some Jenkins plugin to provide access from PowerShell.
The reason you are getting an authentication error is that you will need to convert the authentication to base 64 string. Below is the script that you can use if you have not enabled the CSRF in Jenkins.
$UserName = "admin"
$Password = "password"
$API_URL = "jenkinsservername"
$JobName = "TestItem1"
$JobToken = "token"
$header = #{}
$Params = #{}
$header.Add('Authorization', 'Basic ' + [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes("$(${UserName}):$(${Password})")))
$Params['uri'] = "http://jenkinsservername/$JobName/build?token=$JobToken"
$Params['Method'] = 'Post'
$Params['Headers'] = $header
Invoke-RestMethod #Params
But If you have CSRF Enabled in Jenkins then use below script
$UserName = "admin"
$Password = "password"
$API_URL = "jenkinsservername"
$JobName = "TestItem1"
$JobToken = "token"
$header = #{}
$header.Add('Authorization', 'Basic ' + [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes("$(${UserName}):$(${Password})")))
$Params = #{uri = "http://${API_URL}:${API_Port}/crumbIssuer/api/json";
Method = 'Get';
Headers = $header;}
$API_Crumb = Invoke-RestMethod #Params
write-host $API_Crumb
$h.Add('Jenkins-Crumb', $API_Crumb.crumb)
$Params['uri'] = "http://jenkinsservername/$JobName/build?token=$JobToken"
$Params['Method'] = 'Post'
$Params['Headers'] = $header
Invoke-RestMethod #Params
#Mike correctly described the instructions for working with the jenkins api when using CSRF. But I would like to add that when creating crumbs, the session and cookies are also taken into account.
The code that works for me is as follows:
$UserName = "admin"
$Password = "password"
$API_URL = "jenkinsservername"
$JobName = "TestItem1"
$JobToken = "token"
$header = #{}
$header.Add('Authorization', 'Basic ' + [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes("$(${UserName}):$(${Password})")))
$Params1 = #{uri = "http://${API_URL}:${API_Port}/crumbIssuer/api/json";
Method = 'Get';
SessionVariable = 'Session';
Headers = $header;}
$API_Crumb = Invoke-RestMethod #Params1
write-host $API_Crumb
$header.Add('Jenkins-Crumb', $API_Crumb.crumb)
$Params2 = #{}
$Params2['uri'] = "http://jenkinsservername/$JobName/build?token=$JobToken"
$Params2['Method'] = 'Post'
$Params2['Headers'] = $header
Invoke-RestMethod #Params2 -WebSession $Session
Also consider if the job is in a folder, then the uri will be different.
For example, if MyJob is in MyFolder then the uri will be:
http://jenkinsservername/job/MyFolder/job/MyJob/build?token=JobToken
You can see this path in the place where you assigned the token for the job
I have a PowerShell script that warms up our .Net web app that was using forms authentication. I used Invoke-WebRequest and read the anti-forgery token, then did a POST with that token, and the user/pass fields. Then I stored the session, and was able to request our remaining pages to warm up the site.
We have Auth0 implemented on the application now using the OWIN/cookies. How can I authenticate my powershell session with the new Auth0 login?
EDIT: got it working
The following code works
function LoginAuth0
{
LogAction 'Logging into Auth0'
$url = BnUrl('/auth/login?fromSignIn=True')
$login = Invoke-WebRequest $url -UseBasicParsing -SessionVariable Script:session -Method 'GET'
$match = [regex]::Match($login.Content, "var config = JSON\.parse\(decodeURIComponent\(escape\(window.atob\('([a-zA-Z0-9=]+)'\)\)\)\);")
if($match.Success)
{
$configDataBase64 = $match.captures.groups[1].value
}
if( -not $configDataBase64 )
{
LogError('Could not get config data');
Exit 1
}
$configDataUriEncoded = [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($configDataBase64))
$configDecoded = [System.Web.HttpUtility]::UrlDecode($configDataUriEncoded)
$lockConfig = ($configDecoded | ConvertFrom-Json)
$fields = #{
'redirect_uri' = BnUrl('/signin-auth0')
'tenant' = $Script:config.auth0_tenant
'response_type' = 'code id_token'
'connection' = 'Username-Password-Authentication'
'sso' = 'true'
'response_mode' = 'form_post'
'_intstate' = 'deprecated'
'allow_signup' = 'false'
'x-client-_sku' = 'ID_NET461'
'allow_login' = 'true'
'scope' = 'openid profile'
'x-client-ver' = '5.3.0.0'
'protocol' = 'oauth2'
'client_id' = $lockConfig.clientID
'username' = $Script:config.site_user
'password' = $Script:config.site_pass
'_csrf' = $lockConfig.internalOptions._csrf
'nonce' = $lockConfig.internalOptions.nonce
'state' = $lockConfig.internalOptions.state
}
$post_url = "https://$($Script:config.auth0_tenant).auth0.com/usernamepassword/login"
$post_json = Invoke-WebRequest $post_url -UseBasicParsing -WebSession $Script:session -Method 'POST' -ContentType 'application/json' -Body ($fields|ConvertTo-Json)
$match = [regex]::Match($post_json.Content, '<input\s+type="\w+"\s+name="wresult"\s+value="([^>]+)">')
if( -not $match.Success )
{
LogError('Could not find wresult')
Exit 1
}
$wresult = $match.captures.groups[1].value
$match = [regex]::Match($post_json.Content, '<input\s+type="\w+"\s+name="wctx"\s+value="([^>]+)">')
if( -not $match.Success )
{
LogError('Could not find wctx')
Exit 1
}
$wctx = $match.captures.groups[1].value -replace '"','"' | ConvertFrom-Json
$formFields = #{
wa = 'wsignin1.0'
wresult = $wresult
wctx = $wctx | ConvertTo-Json -Compress
}
$url = "https://$($Script:config.auth0_tenant).auth0.com/login/callback"
$post_form = Invoke-WebRequest $url -UseBasicParsing -WebSession $Script:session -Method 'POST' -ContentType 'application/x-www-form-urlencoded' -Body $formFields
$match = [regex]::Match($post_form.Content, '<input\s+type="\w+"\s+name="code"\s+value="([^>]+)"\s*/>')
if( -not $match.Success )
{
LogError('Could not find code')
Exit 1
}
$code = $match.captures.groups[1].value
$match = [regex]::Match($post_form.Content, '<input\s+type="\w+"\s+name="id_token"\s+value="([^>]+)"\s*/>')
if( -not $match.Success )
{
LogError('Could not find code')
Exit 1
}
$token = $match.captures.groups[1].value
$match = [regex]::Match($post_form.Content, '<input\s+type="\w+"\s+name="state"\s+value="([^>]+)"\s*/>')
if( -not $match.Success )
{
LogError('Could not find code')
Exit 1
}
$state = $match.captures.groups[1].value
$formFields = #{
code = $code
id_token = $token
state = $state
}
$url = BnUrl('/signin-auth0')
$result = Invoke-WebRequest $url -UseBasicParsing -WebSession $Script:session -Method 'POST' -ContentType 'application/x-www-form-urlencoded' -Body $formFields
if($result.StatusCode -eq 200)
{
LogOk
}
else
{
LogError('failed to login')
Exit 1
}
}
I'm struggling to access the Coinspot API from PowerShell. No matter what I do I always get the "no nonce" error back from the API:
$VerbosePreference = 'Continue'
$key = ''
$secret = ''
$epoc_start_date = ("01/01/1970" -as [DateTime])
[int]$nonce = ((New-TimeSpan -Start $epoc_start_date -End ([DateTime]::UtcNow)).TotalSeconds -as [string])
$baseUrl = 'www.coinspot.com.au/api'
$resourcePath = '/my/orders'
$url = 'https://{0}{1}&nonce={2}' -f $baseUrl, $resourcePath, $nonce
$encoded = New-Object System.Text.UTF8Encoding
$url_bytes = $encoded.GetBytes($url)
# create hash
$hmac = New-Object System.Security.Cryptography.HMACSHA512
$hmac.key = [Text.Encoding]::ASCII.GetBytes($secret)
$sha_result = $hmac.ComputeHash($url_bytes)
#remove dashes
$hmac_signed = [System.BitConverter]::ToString($sha_result) -replace "-";
$headers = #{
sign = $hmac_signed
key = $key
'content-type' = 'application/json'
}
$result = Invoke-RestMethod -Uri $url -Method Post -Headers $headers
$result
Alternatively I have already tested this:
$VerbosePreference = 'Continue'
$key = ''
$secret = ''
$epoc_start_date = ("01/01/1970" -as [DateTime])
[int]$nonce = ((New-TimeSpan -Start $epoc_start_date -End ([DateTime]::UtcNow)).TotalSeconds -as [string])
$baseUrl = 'www.coinspot.com.au/api'
$resourcePath = '/my/orders'
$url = 'https://{0}{1}' -f $baseUrl, $resourcePath
$body = #{
nonce = $nonce
}
$encoded = New-Object System.Text.UTF8Encoding
$body_bytes = $encoded.GetBytes($body)
# create hash
$hmac = New-Object System.Security.Cryptography.HMACSHA512
$hmac.key = [Text.Encoding]::ASCII.GetBytes($secret)
$sha_result = $hmac.ComputeHash($body_bytes)
#remove dashes
$hmac_signed = [System.BitConverter]::ToString($sha_result) -replace "-";
Invoke-RestMethod -Uri $url -Method Post -Headers #{sign = $hmac_signed ; key = $key ; 'content-type' = 'application/json' } -Body $($body | ConvertTo-Json)
The second gives me an invalid status error.
I have a feeling there's something wrong with my header.
Coinspot support responded:
Apologies for this.
Our current API system is way out of date and needs to be updated.
We know that we need to support the developers as best as we can but our current dev team are very busy with other things at the
moment.
They are aware of this and plan to update it as soon as possible, but right now there is no ETA for this.
Very sorry the inconvenience.
Looking at the docs this REST URI should be correct:
https://tenant.atlassian.net/rest/api/content/search?cql=space=myspace
Why I browse to this URL in chrome (after logging in) I'm getting a dead link.
When I try the following powershell script I get the same error in the response body:
#Connection settings
$restcreds = [System.Convert]::ToBase64String(
[System.Text.Encoding]::ASCII.GetBytes(('username' + ":" + 'pass123'))
)
$URI = 'http://tenant.atlassian.net/rest/api/content/search?cql=space=Myspace'
$httpheader = #{Authorization = "Basic $restcreds"}
$restParameters = #{
Uri = ($URI);
ContentType = "application/json";
Method = 'GET';
Headers = $httpheader;
}
$response = Invoke-RestMethod #restParameters
try{
$response = Invoke-RestMethod #restParameters
} catch {
$result = $_.Exception.Response.GetResponseStream()
$reader = New-Object System.IO.StreamReader($result)
$reader.BaseStream.Position = 0
$reader.DiscardBufferedData()
$errorResponse = $reader.ReadToEnd();
$errorResponse
}
$response
No, your URL is invalid, you need to add "wiki" in your URL: https://tenant.atlassian.net/wiki/rest/api/content/search?cql=space=myspace
I feel like I'm really close to being able to use the Coinbase Exchange API with PowerShell, but I'm having trouble creating a valid signature. Requests that don't require a signature, like /time and /products, work great.
Here's what I have so far.
$api = #{
"endpoint" = 'https://api.gdax.com'
"url" = '/account'
"method" = 'GET'
"body" = ''
"key" = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
"secret" = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
"passphrase" = 'xxxxxxxx'
}
# Base64 encoding/decoding functions derived from
# http://vstepic.blogspot.com/2013/02/how-to-convert-string-to-base64-and.html
function Base64-Encode($string) {
$conversion = [System.Text.Encoding]::ASCII.GetBytes($string)
return [System.Convert]::ToBase64String($conversion)
}
function Base64-Decode($string) {
$conversion = [System.Convert]::FromBase64String($string)
return [System.Text.Encoding]::ASCII.GetString($conversion)
}
# HMAC SHA256 code derived from
# http://www.jokecamp.com/blog/examples-of-creating-base64-hashes-using-hmac-sha256-in-different-languages/
function hmac($message, $secret) {
$hmacsha = New-Object System.Security.Cryptography.HMACSHA256
$hmacsha.key = [Text.Encoding]::ASCII.GetBytes($secret)
$signature = $hmacsha.ComputeHash([Text.Encoding]::ASCII.GetBytes($message))
$signature = [Convert]::ToBase64String($signature)
return $signature
}
function Submit-Request($request) {
$unixEpochStart = Get-Date -Date "01/01/1970"
$now = Get-Date
$timestamp = (New-TimeSpan -Start $unixEpochStart -End $now.ToUniversalTime()).TotalSeconds.ToString()
# create the prehash string by concatenating required parts
$prehash = $timestamp + $request.method.ToUpper() + $request.url + $request.body
$signature_b64 = hmac -message $prehash -secret (Base64-Decode $request.secret)
$header = #{
"CB-ACCESS-KEY" = $request.key
"CB-ACCESS-SIGN" = $signature_b64
"CB-ACCESS-TIMESTAMP" = $timestamp
"CB-ACCESS-PASSPHRASE" = $request.passphrase
"Content-Type" = 'application/json'
}
$uri = $request.endpoint + $request.url
if ($request.method.ToUpper() -eq 'POST') {
$response = Invoke-RestMethod -Method $request.method -Uri $uri -Headers $header -Body $request.body
} else {
$response = Invoke-RestMethod -Method $request.method -Uri $uri -Headers $header
}
return $response
}
$api.method = 'GET'
$api.url = '/account'
$response = Submit-Request $api
Write-Output $response
After reviewing some C# code in the Coinbase community, I was able to revise my code and get it working. Decoding of the secret key did not need to go to a string format, which is what was happening when I called Base64-Decode before passing the secret to the HMAC function. I followed the C# example and decoded it directly in the HMAC function without making a string out of it. Another change I made was to make the timestamp match the format retrieved from /time, using 3 decimal places instead of 5.
Here's my revised code. I hope it will be of help to others.
$api = #{
"endpoint" = 'https://api.gdax.com'
"url" = '/account'
"method" = 'GET'
"body" = ''
"key" = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
"secret" = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
"passphrase" = 'xxxxxxxx'
}
# Base64 encoding/decoding functions derived from
# http://vstepic.blogspot.com/2013/02/how-to-convert-string-to-base64-and.html
function Base64-Encode($string) {
$conversion = [System.Text.Encoding]::ASCII.GetBytes($string)
return [System.Convert]::ToBase64String($conversion)
}
function Base64-Decode($string) {
$conversion = [System.Convert]::FromBase64String($string)
return [System.Text.Encoding]::ASCII.GetString($conversion)
}
# HMAC SHA256 code derived from
# http://www.jokecamp.com/blog/examples-of-creating-base64-hashes-using-hmac-sha256-in-different-languages/
function hmac($message, $secret) {
$hmacsha = New-Object System.Security.Cryptography.HMACSHA256
$hmacsha.key = [Convert]::FromBase64String($secret)
$signature = $hmacsha.ComputeHash([Text.Encoding]::ASCII.GetBytes($message))
$signature = [Convert]::ToBase64String($signature)
return $signature
}
function Submit-Request($request) {
$unixEpochStart = Get-Date -Date "01/01/1970"
$now = Get-Date
$timestamp = (New-TimeSpan -Start $unixEpochStart -End $now.ToUniversalTime()).TotalSeconds
# round timestamp to 3 decimal places and convert to string
$timestamp = ([math]::Round($timestamp, 3)).ToString()
# create the prehash string by concatenating required parts
$prehash = $timestamp + $request.method.ToUpper() + $request.url + $request.body
$signature_b64 = hmac -message $prehash -secret $request.secret
$header = #{
"CB-ACCESS-KEY" = $request.key
"CB-ACCESS-SIGN" = $signature_b64
"CB-ACCESS-TIMESTAMP" = $timestamp
"CB-ACCESS-PASSPHRASE" = $request.passphrase
"Content-Type" = 'application/json'
}
$uri = $request.endpoint + $request.url
if ($request.method.ToUpper() -eq 'POST') {
$response = Invoke-RestMethod -Method $request.method -Uri $uri -Headers $header -Body $request.body
} else {
$response = Invoke-RestMethod -Method $request.method -Uri $uri -Headers $header
}
return $response
}
$api.method = 'GET'
$api.url = '/accounts'
$response = Submit-Request $api
Write-Output $response