Azure DevOps Services REST API 6.0: Deployments/Release - List not returning count more than 100 - api

Azure DevOps Services REST API 6.0: Deployments/Release - List not returning count more than 100
I'm using doc (Build, Release & Deployment List)
https://learn.microsoft.com/en-us/rest/api/azure/devops/release/deployments/list?view=azure-devops-rest-6.0&tabs=HTTP
Below API call is giving me list of total builds (approx 930)
GET https://dev.azure.com/{organization}/{project}/_apis/build/builds?$top=999&api-version=6.0
Whereas it wont show more than 100 releases/deployments with below queries
GET https://vsrm.dev.azure.com/{organization}/{project}/_apis/release/releases?$top=999&api-version=6.0
GET https://vsrm.dev.azure.com/{organization}/{project}/_apis/release/deployments?$top=999&api-version=6.0
please suggest further if you have any solutions.

Please try this PowerShell script:
[string]$orgurl = "https://vsrm.dev.azure.com/{organization}"
[string]$project = "ProjectName"
[string]$user = ""
[string]$token = "PAT"
[System.Net.ServicePointManager]::SecurityProtocol = "tls12"
# Ignore the error
$ErrorActionPreference = 'SilentlyContinue'
# Base64-encodes the Personal Access Token (PAT) appropriately
$base64AuthInfo = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f $user,$token)))
cls
$headers = #{Authorization = ("Basic {0}" -f $base64AuthInfo)}
$continuationToken = ''
$deployments = #()
Do {
$uri = "$orgurl/$project/_apis/release/deployments?api-version=6.0&continuationToken=$ContinuationToken"
$result = Invoke-WebRequest -Uri $uri -Headers $headers
$deployments += ($result.Content | ConvertFrom-Json).Value
$continuationToken = $result.Headers.'x-ms-continuationtoken'
Write-Host "continuationToken:" $continuationToken
}
While($continuationToken)
$deployments.Count
$deployments.release | Select id, name, url

I got it to work by the first time not passing the ContinuationToken parameter the first call.
$uri = "$orgurl/$project/_apis/release/deployments?api-version=6.0"
Do {
$result = Invoke-WebRequest -Uri $uri -Headers $headers
$uri = "$orgurl/$project/_apis/release/deployments?api-version=6.0&continuationToken=$ContinuationToken"
$deployments += ($result.Content | ConvertFrom-Json).Value
$continuationToken = $result.Headers.'x-ms-continuationtoken'
}

Related

How to make a rest call in Azure pipeline then use the response to make another call?

I am creating an Azure pipeline where I need to make a rest api call from the pipeline then use part of the api call response in the request of another consecutive rest api call.
How can I achieve that?
In my test, I use the script below to get the work item state value in the pipeline, and you could use this variable in your script or pipeline for other api calls.
1.I transfer the api result into json with variable $field
2.Write-host the value $field
3.Get the element of system.state and set it as variable $witstate
4.Write-host the value.
# Define organization base url, PAT, linked wit, Target WIT state and API version variables
$orgUrl = "https://dev.azure.com/{yourORG}/{yourPROJECT}"
$pat = ""
$queryString = "fields=system.state&api-version=7.0"
$witID = {YourWitID}
# Create header with PAT
$token = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes(":$($pat)"))
$header = #{authorization = "Basic $token"}
# Get the linked wit state
$projectsUrl = "$orgUrl/_apis/wit/workitems/$witID?$queryString"
$field = Invoke-RestMethod -Uri $projectsUrl -Method Get -ContentType "application/json" -Headers $header | ConvertTo-Json | ConvertFrom-Json | Select-Object -ExpandProperty fields
write-host $field
$witstate = $field.'System.State'
Write-Host $witstate

I need reource code of main.iam.ad.ext.azure.us

I need to collect information about total and assigned licenses programmatically.
The way that is described here: https://tech.nicolonsky.ch/manage-azure-ad-group-based-licensing-with-powershell/ - does not work on AzureUSGovernment environment. The following error occurs: ""Get-AADLicenseSku : AADSTS900382: Confidential Client is not supported in Cross Cloud request."
So, I am looking for a way to adjust it and use it on AzureUSGovernment. But I could not find the resource ID of main.iam.ad.ext.azure.us
As I understood, the ID of main.iam.ad.ext.azure.com is 74658136-14ec-4630-ad9b-26e160ff0f. But I do not understand where it is coming from.
Thank you in advance for the help.
I created a script based on the original scripts:
$context = Get-AzContext
if ($null -eq $context) {
$null = Connect-AZAccount -EA stop
$context = Get-AzContext
}
$apiToken = [Microsoft.Azure.Commands.Common.Authentication.AzureSession]::Instance.AuthenticationFactory.Authenticate($context.Account, $context.Environment, $context.Tenant.Id, $null, "Never", $null, "https://main.iam.ad.ext.azure.us")
$header = #{
'Authorization' = 'Bearer ' + $apiToken.AccessToken.ToString()
'Content-Type' = 'application/json'
'X-Requested-With' = 'XMLHttpRequest'
'x-ms-client-request-id' = [guid]::NewGuid()
'x-ms-correlation-id' = [guid]::NewGuid()
}
Write-Verbose "Connected to tenant: '$($context.Tenant.Id)' as: '$($context.Account)'"
$baseUrl = "https://main.iam.ad.ext.azure.us/api/"
try {
$request = Invoke-WebRequest -Method Get -Uri $($baseUrl + "AccountSkus") -Headers $header
$requestContent = $request | ConvertFrom-Json
return $requestContent
}
catch {
# convert the error message if it appears to be JSON
if ($_.ErrorDetails.Message -like "{`"Classname*") {
$local:errmsg = $_.ErrorDetails.Message | ConvertFrom-Json
if ($local:errmsg.Clientdata.operationresults.details) {
Write-Error $local:errmsg.Clientdata.operationresults.details
}
else {
Write-Error $local:errmsg
}
}
else {
Write-Error $_
}
}
But it fails with the following error:
"Invoke-RestMethod :
401 - Unauthorized: Access is denied due to invalid credentials.
Server Error
401 - Unauthorized: Access is denied due to invalid credentials.
You do not have permission to view this directory or page using the credentials that you supplied."
I tried to use the user account and service principal. Global Admin role is assigned to both.
I found the solution. In my script above ^^, I replaced
$apiToken = [Microsoft.Azure.Commands.Common.Authentication.AzureSession]::Instance.AuthenticationFactory.Authenticate($context.Account, $context.Environment, $context.Tenant.Id, $null, "Never", $null, "https://main.iam.ad.ext.azure.us")
with
$apiToken = [Microsoft.Azure.Commands.Common.Authentication.AzureSession]::Instance.AuthenticationFactory.Authenticate($context.Account, $context.Environment, $context.Tenant.Id, $null, "Never", $null, "ee62de39-b9b0-4886-aa58-08b89c4e3db3")
And now it works. Here is the example of the response:
name : Office 365 E3 - GCCHIGH
accountId : XXXXXX-XXXX-4427-8719-XXXXXXXXXXXX
accountSkuId : TEST:ENTERPRISEPACK_USGOV_GCCHIGH
availableUnits : 0
totalUnits : 1
consumedUnits : 1
skuId : aea38a85-XXXX-XXXX-aa00-XXXXXXXXXXXX
isDepartment : False
warningUnits : 0
serviceStatuses : {#{provisioningStatus=Success; servicePlan=}, #{provisioningStatus=Success; servicePlan=}, #{provisioningStatus=Success; servicePlan=}, #{provisioningStatus=Success; servicePlan=}...}

Output the results of a Log Analytics Workspace query to Event Hub

I'm performing a query to output logs captured in an Azure Log Analytics Workspace, for example:
Invoke-AzOperationalInsightsQuery -WorkspaceId '' -Query "AzureDiagnostics | where Category == 'AzureFirewallApplicationRule'"
However I need to send the results of this to an Event Hub for further processing.
I'm trying to use the REST API (https://learn.microsoft.com/en-us/rest/api/eventhub/send-batch-events) but struggling to dynamically generate a request body to send to the Event Hub based on the output fields of the query. This may not be the best way to do it, any suggestions?
I suggest you can use Send event api by sending a simple json data one by one. Because if you use send batch api, you should build a more complex source data.
You can use the following powershell code to send data to event hub using send event api.
$queryResults = Invoke-AzOperationalInsightsQuery -WorkspaceId "xxx" -Query "your query"
#generate sas token
$URI_1 = "event_hub_namespace.servicebus.windows.net/eventhub_path"
$Access_Policy_Name="RootManageSharedAccessKey"
$Access_Policy_Key="the key"
#Token expires now+3000
$Expires=([DateTimeOffset]::Now.ToUnixTimeSeconds())+3000
$SignatureString=[System.Web.HttpUtility]::UrlEncode($URI_1)+ "`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_1) + "&sig=" + [System.Web.HttpUtility]::UrlEncode($Signature) + "&se=" + $Expires + "&skn=" + $Access_Policy_Name
$SASToken
$method = "POST"
$url = "https://event_hub_namespace.servicebus.windows.net/eventhub_path/messages"
$signature = $SASToken
# API headers
$headers = #{
"Authorization"=$signature;
"Content-Type"="application/atom+xml;type=entry;charset=utf-8";
}
#use foreach to send data
foreach($s in $queryResults.Results){
#Write-Output "hello"
$json = $s | ConvertTo-Json
#Write-Output $json
Invoke-WebRequest -Method $method -Headers $headers -Body $json -uri $url
}
Write-Output "**completed**"
After execute the powershell, I use code to receive the data from event hub, and I can confirm that all the data are sent to event hub. The screenshot as below:

How to do a web request call to sqlpad?

Hi I have been trying to do a web request call to sqlpad.
I have got the basis of the script to make the connection
Invoke-WebRequest -uri
However when I run the command I get connection 200 showing it has made a connection but how do I use cached cookies or how do I sign into sqlpad using credentials and run query all from using web request.
Sorry I am new to powershell and webrequest so I appreciate all your advice thank you.
That should be doable. You'd need to use sqlpad api. To keep cookies you need to create a session variable when calling signin and reuse it in later calls. To extract query data you'd need to use query-result end point. You need to know connectionId (can lookup at api/connections using browser) and SQL code (query text). Turns out there is no direct way to run query by query name. So you either need to know the sql of the query or you can extract it from /api/queries for specific query
$baseUrl = "http://localhost:39325/api"
$user = "yourEmail"
$password = "yourPassword"
$signinUrl = "$baseUrl/signin?email=$user&password=$password&redirect=false"
# sign in and create session variable $ws
if(!$ws) { $r = Invoke-WebRequest -Uri $signinUrl -SessionVariable ws -Method Post } else { Write-Host "connected"}
# list of available queries and connections. May need to run this to determine connection id or existing query sql
$QueryList = Invoke-RestMethod -Uri "$baseUrl/queries" -WebSession $ws
$ConnectionList = Invoke-RestMethod -Uri "$baseUrl/connections" -WebSession $ws
Write-Host "Available queries:"
$QueryList.queries | select name, connectionId, queryText | ft -AutoSize
# Execute Query
$params = #{
connectionId = "vhsNXMXCJeI9QlUL" #use $ConnectionList var or just look up on http://localhost:39325/api/connections/
cacheKey = "null" #just some dummy value, parameter is required but it's not really affecting anything
queryName = "test2" #optional
queryText = "select top 15 * from sys.columns" # required
} | ConvertTo-Json
$head = #{'Content-Type'='application/json'}
$data = Invoke-RestMethod -Uri "$baseUrl/query-result" -Method Post -Body $params -Headers $head -WebSession $ws
$data.queryResult.rows | ft

Coinbase API invalid signature with Powershell

I would like to retrieve account balance through Coinbase API with Powershell.
I coded the following reading from coinbase api documentation but the last request throws the following error:
Invoke-RestMethod : {"errors":[{"id":"authentication_error","message":"invalid signature"}]}
Here is my code.
What's wrong? Thank you.
$accounts = 'https://api.coinbase.com/v2/accounts'
$time = 'https://api.coinbase.com/v2/time'
$epochtime = [string]((Invoke-WebRequest $time | ConvertFrom-Json).data).epoch
$method = 'GET'
$requestpath = '/v2/accounts'
$secret_key = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
$sign = $epochtime + $method + $requestpath
$hmacsha = New-Object System.Security.Cryptography.HMACSHA256
$hmacsha.key = [Convert]::FromBase64String($secret_key)
$signature = $hmacsha.ComputeHash([Text.Encoding]::ASCII.GetBytes($sign))
$signature = [Convert]::ToBase64String($signature)
$header = #{
"CB-ACCESS-SIGN"=$signature
"CB-ACCESS-TIMESTAMP"=$epochtime
"CB-VERSION" = '2017-08-07'
"CB-ACCESS-KEY"='xxxxxxxxxxxxxx'
}
Invoke-WebRequest $accounts -Headers $header
Hopefully this will get you going. I just started working on a module today and got stuck on the same thing. I came across your question while trying to solve the problem myself. Figured I would share what I found. Good luck!
$accounts = 'https://api.coinbase.com/v2/accounts'
$time = 'https://api.coinbase.com/v2/time'
$epochtime = [string]((Invoke-WebRequest $time | ConvertFrom-Json).data).epoch
$method = 'GET'
$requestpath = '/v2/accounts'
$secret_key = (Get-CoinBaseAPIKeys).Secret
$sign = $epochtime + $method + $requestpath
$hmacsha = New-Object System.Security.Cryptography.HMACSHA256
$hmacsha.key = [Text.Encoding]::UTF8.GetBytes($secret_key)
$computeSha = $hmacsha.ComputeHash([Text.Encoding]::UTF8.GetBytes($sign))
The LONG WAY, for reference:
$signature = ""
foreach ( $c in $computeSha )
{
$signature += "{0:x2}" -f $c
}
The short way. Oddly I got stuck on this SAME issue, because the short way
produces UPPER CASE HEX and the long way ^^above^^ converts to lower case HEX.
The CoinBase API will ONLY accept the signature in HEX in lower case.
$signature = ([System.BitConverter]::ToString($computeSha) -replace "-").ToLower()
Now that we have the signature figured out, the rest should work great. I removed the CB_VERSION because it will default to your OWN API version. My default was different, so I simply removed it.
$header = #{
"CB-ACCESS-SIGN"=$signature
"CB-ACCESS-TIMESTAMP"=$epochtime
"CB-ACCESS-KEY"=(Get-CoinBaseAPIKeys).Key
}
$result = Invoke-WebRequest $accounts -Headers $header -Method Get -ContentType "application/json"
$accounts = $result.Content | ConvertFrom-Json
Write-Output $accounts.data
As an aside on storing PRIVATE KEY/SECRET you can find some ideas here:
https://github.com/cmaahs/BittrexAPI/tree/master/Encryption. Feel free to grab it and modify as you will. Better to store your KEY/SECRET encrypted in the registry rather than as plain text in your script or as environment variables.