Reputation: 69
I need to add user permission when creating an environment through REST API with PowerShell.
I've looked at the network trace and this is the header when I tried to manually add a user permissions
Request URL:
https://dev.azure.com/{org}/_apis/securityroles/scopes/distributedtask.environmentreferencerole/roleassignments/resources/{project_id}_{env_id}
Request Method: Put
Request Body:
[{userId: "{id_of_user}", roleName: "Administrator"}]
And this is the code I tried:
# other code
...
$body = @(
@{ 'userId' = '{id_of_user}'; 'roleName': 'Administrator' }
) | ConvertTo-Json
Invoke-RestMethod -Uri $uri -Method Put -Body $body -ContentType "application/json" -Headers $header
But it is returning:
{"count":0,"value":{}}
Upvotes: 3
Views: 2008
Reputation: 760
If someone is looking for the cURL + Bash version, here it is:
#!/usr/bin/env bash
set -o errexit # Exit when a command fails
set -o nounset # Exit on undeclared variable
set -o pipefail # Exit on the first command in pipe fail
PERSONAL_ACCESS_TOKEN='<secret>'
GROUP_OR_USER_ID='11111111-1111-1111-1111-111111111111'
ENVIRONMENT_ID='22'
ORGANIZATION=example
PROJECT_ID='33333333-3333-3333-3333-333333333333'
DATA="[{\"userId\":\"${GROUP_OR_USER_ID}\",\"roleName\":\"User\"}]"
URL="https://dev.azure.com/${ORGANIZATION}/_apis/`
`securityroles/scopes/distributedtask.environmentreferencerole/roleassignments/resources/`
`${PROJECT_ID}_${ENVIRONMENT_ID}`
`?api-version=5.0-preview.1"
curl "${URL}" \
--user ":${PERSONAL_ACCESS_TOKEN}" \
--request PUT \
--header 'Content-Type: application/json' \
--data "${DATA}" \
| jq # jq is just for pretty JSON printout, not strictly required
NOTE: This can be integrated with Terraform like this.
Upvotes: 0
Reputation: 1503
@Bruno answer can have its header greatly simplified, also the body can be constructed using ConvertTo-Json to avoid syntax errors.
function Get-AzureDevOpsAuthenticationHeader
{
param (
[Parameter(Mandatory=$false)][SecureString]$PAT
)
$AzureDevOpsPAT = (new-object System.Net.NetworkCredential -argumentList " ", (Get-AzureDevOpsPAT -PAT $PAT)).Password
$AzureDevOpsAuthenicationHeader = @{Authorization = 'Basic ' + [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(":$($AzureDevOpsPAT)")) }
return $AzureDevOpsAuthenicationHeader
}
#parms
$orgname='...'
$userid='guid'
$projectid='guid'
$environmentid='int'
$PAT = '...' | ConvertTo-SecureString -asplaintext -force
#get the header
$header = Get-AzureDevOpsAuthenticationHeader -PAT $PAT
#construct the body
$body = ConvertTo-Json -InputObject @(,@{userId= $userid;"roleName"="Administrator"})
#send the request
$uri = "https://dev.azure.com/$orgname/_apis/securityroles/scopes/distributedtask.environmentreferencerole/roleassignments/resources/$projectid`_$EnvironmentID`?api-version=5.0-preview.1"
Invoke-RestMethod -UseBasicParsing -Uri $uri -Method "PUT" -Body $body -ContentType application/json -Headers $header
output:
count value
----- -----
1 {@{identity=; role=; access=assigned; accessDisplayName=Assigned}}
Upvotes: 1
Reputation: 1006
The only missing thing is that in your body, you should provide an array instead of a single object, here is a working example:
$uri = "https://dev.azure.com/bauca/_apis/securityroles/scopes/distributedtask.environmentreferencerole/roleassignments/resources/{project_id}_{env_id}"
$id_of_user = 'YOUR_USER_ID'
$tokenbase = 'YOUR_PAT'
$header = @{
"authority"="dev.azure.com"
"Authorization"= "Basic $tokenbase"
"method"="PUT"
"path"="/{ORG}/_apis/securityroles/scopes/distributedtask.environmentreferencerole/roleassignments/resources/{project_id}_{env_id}"
"scheme"="https"
"accept"="application/json;api-version=5.0-preview.1;excludeUrls=true;enumsAsNumbers=true;msDateFormat=true;noArrayWrap=true"
"accept-encoding"="gzip, deflate, br"
"accept-language"="en-US,en;q=0.9,pt;q=0.8,nl;q=0.7"
"origin"="https://dev.azure.com"
"x-vss-reauthenticationaction"="Suppress"
} `
$body = "[{`"userId`":`"${id_of_user}`",`"roleName`":`"Administrator`"}]"
Invoke-RestMethod -UseBasicParsing -Uri $uri -Method "PUT" -Body $body -ContentType "application/json" -Headers $header
The returned results should be something like:
@{displayName=USER_NAME; id=USERID; uniqueName=USER_UNIQUENAME}
The API documentation is not clear about that, so, in this situations what I'd recommend you to do, is just use Chrome to do the requests through the UI, then inspect element and grab the network information of the request, after that 'Click with the right button' and then select 'Copy to Powershell' you'll see exactly what is the 'body' required to perform the request.
Upvotes: 3