Get all users under all projects from Azure DevOps - powershell

I am trying to get all users under couple of project. The case is that under users there are many and I need to to use continuationToken. The result is messy because my logic is bad. I cannot figure out how to use the second foreach..
$outputItems = #()
foreach ($project in $projects) {
$uriProjectDescriptor = "https://vssps.dev.azure.com/$OrganizationName/_apis/graph/descriptors/$($project.id)?api-version=5.0-preview.1"
$projectDescriptor = Invoke-RestMethod -Uri $uriProjectDescriptor -Method Get -Headers $AzureDevOpsAuthenicationHeader
$descriptors = $projectDescriptor.value
foreach ($descriptor in $descriptors) {
do
{
$uriUsers="https://vssps.dev.azure.com/$OrganizationName/_apis/graph/users?continuationToken=$continuationToken&scopeDescriptor=$($descriptor)&api-version=6.0-preview.1"
$responseUsers=Invoke-WebRequest -Uri $uriUser -Method Get -ContentType "application/json" -Headers $AzureDevOpsAuthenicationHeader -UseBasicParsing -MaximumRedirection 0
$continuationToken = $responseUsers.Headers.'x-ms-continuationtoken'
$userSet = $responseUsers.content | ConvertFrom-Json
$users += $userSet.value.Count
$arealList = New-Object -TypeName PSObject -Property #{
CountUsers = $users.Count
} | Select-Object "CountUsers"
$outputItems += $arealList
$arealList = $null
}
while (($continuationToken))
$ProgressPreference = 'Continue'
}
} $outputItems

You could try the following Powershell Script:
$token = "PAT"
$url="https://dev.azure.com/{Organizationname}/_apis/projects?api-version=6.0"
$token = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes(":$($token)"))
$responses = Invoke-RestMethod -Uri $url -Headers #{Authorization = "Basic $token"} -Method Get -ContentType application/json
ForEach ($response in $responses.value.id)
{
$url1="https://vssps.dev.azure.com/{Organizationname}/_apis/graph/descriptors/$($response)?api-version=6.0-preview.1"
$Descriptor = Invoke-RestMethod -Uri $url1 -Headers #{Authorization = "Basic $token"} -Method Get -ContentType application/json
ForEach ($Descriptor1 in $Descriptor.value)
{
do
{
$url2="https://vssps.dev.azure.com/{Organizationname}/_apis/graph/users?scopeDescriptor=$($Descriptor1)&api-version=6.0-preview.1"
$UserLists = Invoke-RestMethod -Uri $url2 -Headers #{Authorization = "Basic $token"} -Method Get -ContentType application/json
$continuationToken = $UserLists.Headers.'x-ms-continuationtoken'
}
while ($continuationToken -ne $null)
Write-Host "result = $($UserLists | ConvertTo-Json -Depth 100)"
}
}
Explaination:
The first Rest API is used to get the Project name.
Then the second Rest API is used to get the descriptors.
The third Rest api is used to get the userlist.
I use foreach nesting to realize the loop of response to Rest API.
Update:
Test with the continuationToken and the maximum value of objects returned by a project is 500.
I found another Rest Api User Entitlements - List to get the users.
https://vsaex.dev.azure.com/Organization Name/_apis/userentitlements?top=10000&select=project&api-version=4.1-preview.1
This Rest APi could directly return the users under the organization(Project Scope). The max value is 10000.

Related

graph api assign manager

I'm trying to assign the manager to a user in AAD the documentation says
PUT /users/{id}/manager/$ref
but i'm not sure what to feed the $ref variable. I've tried UPN and the ID, but I keep getting
The remote server returned an error: (400) Bad Request.
Here is how i'm trying to put the manager info, but clearly i'm not doing it right or I can't read the documentation from here
$Header = #{
Authorization = "$($Request.token_type) $($Request.access_token)"
}
$bodyProcess = #{
id= "string aa9999a1-1111-11a2-abab-asfdas32"
}
$body = $bodyProcess | ConvertTo-Json
$Uri = "https://graph.microsoft.com/v1.0/users/4d5f6c5a-0e69-40b6-a86d-e825582add50/manager/$ref"
$UserData = Invoke-RestMethod -Uri $Uri -Headers $Header -Method PUT -ContentType "application/json" -Body $Body
Any help would be greatly appreciated.
thanks,
Here is the full script that works for me.
$Header = #{
Authorization = "$($Request.token_type) $($Request.access_token)"
}
$bodyProcess = #{
"#odata.id"= "https://graph.microsoft.com/v1.0/users/aa9999a1-1111-11a2-abab-asfdas32"
}
$body = $bodyProcess | ConvertTo-Json
$Uri = 'https://graph.microsoft.com/v1.0/users/4d5f6c5a-0e69-40b6-a86d-e825582add50/manager/$ref'
Invoke-RestMethod -Uri $Uri -Headers $Header -Method PUT -ContentType "application/json" -Body $Body

How to remove runs with Legacy retention Model

I have runs which are retained due to Legacy retention model as below:
I'm not sure where it coming from. And I want to remove them but not going through each run and removing lease. Is there a way to do that?
I didn't found an settings on Azure DevOps to turn it off so I wrote powershell script which goes through each pipeline definition and then builds and remove Legacy Retention Mode lease and build with this lease.
$AzureDevOpsAuthenicationHeader = #{Authorization = 'Basic ' + [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(":your-pat-here")) }
$organization = "org-name"
$project = "project-name"
$definitionsUrl = "https://dev.azure.com/${organization}/${project}/_apis/build/definitions?api-version=6.0"
$definitions = Invoke-RestMethod -Uri $definitionsUrl -Method Get -Headers $AzureDevOpsAuthenicationHeader
foreach ($definition in $definitions.value)
{
Write-Host $definition.name -ForegroundColor Green
$pipelineUrl = "https://dev.azure.com/${organization}/${project}/_apis/pipelines/$($definition.id)/runs?api-version=6.0-preview.1"
# Invoke the REST call
$result = Invoke-RestMethod -Uri $pipelineUrl -Method Get -Headers $AzureDevOpsAuthenicationHeader
foreach ($run in $result.value) {
$leasesUrl = "https://dev.azure.com/${organization}/${project}/_apis/build/builds/$($run.id)/leases?api-version=6.1-preview.1"
$leasesResult = Invoke-RestMethod -Uri $leasesUrl -Method Get -Headers $AzureDevOpsAuthenicationHeader
$ownerId = "Legacy Retention Model"
foreach ($lease in $leasesResult.value) {
if($lease.ownerId -Match $ownerId){
$deleteLeaseUrl = "https://dev.azure.com/${organization}/${project}/_apis/build/retention/leases?ids=$($lease.leaseId)&api-version=6.0-preview.1"
Write-Host "Removing ${ownerId} from run $($run.id) (created date $($run.createdDate))" -ForegroundColor Blue
$leasesResult = Invoke-RestMethod -Uri $deleteLeaseUrl -Method Delete -Headers $AzureDevOpsAuthenicationHeader
Write-Host "Removed lease"
$deleteBuildUrl = "https://dev.azure.com/${organization}/${project}/_apis/build/builds/$($run.id)?api-version=6.0"
$leasesResult = Invoke-RestMethod -Uri $deleteBuildUrl -Method Delete -Headers $AzureDevOpsAuthenicationHeader
Write-Host "Removed build"
}
}
}
}

How can I cancel & delete a waiting build in the queue using PowerShell

Due to long running builds various next in line builds take longer time to execute.
Is there a way I can cancel and delete waiting build in queue and give way for latest triggered build using PowerShell or REST API's?
The following code snippet goes over all TFS builds,Gets the Builds which in Progress and not started, and then, cancel them.
$tfsUrl = "http://{server}:{port}/{organization}/{collection}/{project}" # TFS Base URL
$BuildDefsUrl = "$tfsUrl/_apis/build/definitions?api-version=2.0" # TFS build definitions URL
$BuildsUrl = "$tfsUrl/_apis/build/builds" #TFS Builds URL
$Builds = (Invoke-RestMethod -Uri ($BuildDefsUrl) -Method GET -UseDefaultCredentials).value | Select id,name # get all builds
#for filtering use : | Where-Object {$_.name -like "*Your Pattern*"}
foreach($Build in $Builds)
{
$command = "$($BuildsUrl)?api-version=3.2-preview.3&resultFilter=inprogress&definitions=$($Build.id)&queryOrder=finishTimeDescending"
$Ids = (((Invoke-RestMethod -Method Get -Uri $command -UseDefaultCredentials).value) | where status -like "*notStarted*").id # get waiting builds id's
foreach($id in $Ids)
{
$uri = "$($BuildsUrl)/$($id)?api-version=2.0" # TFS URI
$body = '{"status":4}' # body
$result = Invoke-RestMethod -Method Patch -Uri $uri -UseDefaultCredentials -ContentType 'application/json' -Body $body -Verbose #cancel build
}
}
The above example is pretty old. The code snippet below working for Azure Devops-
$PATToken = "PAT_GOES_HERE"
$AuthHeader= #{Authorization = 'Basic ' + [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(":$($PATToken)")) }
$azureDevops = "https://dev.azure.com/{organization}/{project}"
$BuildsUrl = "$azureDevops/_apis/build/builds"
$filterBuilds = "$($BuildsUrl)?statusFilter=notStarted&api-version=6.0"
(Invoke-RestMethod -Method Get -Uri $filterBuilds -Headers $AuthHeader).value | % {
$uri = "$($BuildsUrl)/$($_.id)?api-version=6.0" # Azure Devops URI
$body = '{"status":4}' # body
$result = Invoke-RestMethod -Method Patch -Uri $uri -Headers $AuthHeader -ContentType 'application/json' -Body $body -Verbose #cancel build
Write-Output "$($_.definition.name) cancaled"
}

Powershell Script does not wait for the response from Invoke-RestMethod cmdlet

I am new to powershell. I have a powershell script which basically makes an REST API request and gets back a JSON response. But I have an issue with the Invoke-RestMethod cmdlet. I mean the script sometimes doesn't wait for the response and continues with the next line of code.
Is there some trick in powershell which asks the code to wait for the API response and then run the remaining code. Below is my code
if ($EventID -eq '4726') {
$ad_user = "$TargetUsername#avayaaws.int"
$jsonbody = #{
"setupName" = "avayadev-or"
"instanceName" = "000_JumpServer_DMZ"
"command" = "$Command"
"parameters" = #{
"mobile" = "$getMobileAttr"
"ad_user"="$ad_user"
"label" ="$environment"
}
"eventToken" = "optional"
} | ConvertTo-Json
#$response = Start-Job {
# Invoke-RestMethod -Uri $uri -Method $verb -Body $jsonbody -Headers $header
#} | wait-job | receive-job
#$response = Invoke-RestMethod -Uri $uri -Method $verb -Body $jsonbody -Headers $header
$response = Invoke-WebRequest -Uri $uri -Method $verb -Body $jsonbody -Headers $header
$EventTrigger = $translEvent4726
Write-Output "Response is: $response"
PushLogs -transaction $EventTrigger -adUser $ad_user -transResult $response
}
I have tried many ways like using Out-Null and Wait-Job, Recieve-Job but couldn't get it to work. Any help is much appreciated.

How do I access the value of a field returned by a Restful API

I have a very basic requirement to call a RESTful API. I am currently on a Windows 2012 R2 server using version 4 of PowerShell.
Here is my code:
$logon = #{
username = 'blah'
password='blah'
}
$body = $logon | ConvertTo-Json
$URI = 'https://URL/Logon'
Invoke-WebRequest -URI $URI -Method POST -Body $body -ContentType 'application/json' -Verbose
I get the following result:
{"LogonResult":"blahblahblah"}
How do I extract just the logon token to reuse as a variable? I've already put a variable at the beginning of the command:
$token = (Invoke-WebRequest -URI $URI -Method POST -Body $body -ContentType 'application/json' -Verbose).content
This returns the entire result, not just the token. How do I get just the token as a result?
You can get the value of the returned LogonResult property as follows:
$token = ((Invoke-WebRequest -URI $URI -Method POST -Body $body -ContentType 'application/json' -Verbose).content | ConvertFrom-JSON).LogonResult
Or you simplify this by using Invoke-RestMethod as this returns just the content and converts it to a PSObject automatically:
$token = (Invoke-RestMethod -URI $URI -Method POST -Body $body -ContentType 'application/json' -Verbose).LogonResult