Functions/Add-AzDoProjectPermission.ps1
|
Function Add-AzDoProjectPermission{ <# .SYNOPSIS Adds permissions for a user or group to an Azure DevOps project. .DESCRIPTION Adds permissions for a user or group to an Azure DevOps project. This function uses the Azure DevOps Security API to grant project-level permissions such as Reader, Contributor, Project Administrator, etc. .EXAMPLE Add-AzDoProjectPermission -Project "TeamDevOps" -UserEmail "user@company.com" -Role "Contributor" This will add Contributor permissions for the specified user to the TeamDevOps project. .EXAMPLE Add-AzDoProjectPermission -Project "TeamDevOps" -GroupName "DevTeam" -Role "Reader" This will add Reader permissions for the specified group to the TeamDevOps project. .EXAMPLE $Splat = @{ Project = "TeamDevOps" UserEmail = "user@company.com" Role = "ProjectAdministrator" } Add-AzDoProjectPermission @Splat This will add Project Administrator permissions using splatting. .PARAMETER Project The name of your Azure DevOps Project or Team. .PARAMETER UserEmail The email address of the user to grant permissions to. Either UserEmail or GroupName must be specified. .PARAMETER GroupName The name of the group to grant permissions to. Either UserEmail or GroupName must be specified. .PARAMETER Role The role to assign. Valid values are: - Reader - Contributor - ProjectAdministrator - BuildAdministrator .INPUTS Input is from command line or called from a script. .OUTPUTS RETURNs the result of the permission assignment. .NOTES Author: Lars Panzerbjørn Creation Date: 2024.12.05 #> [CmdletBinding(PositionalBinding=$False)] param( [Parameter(Mandatory)] [Alias('TeamName')] [string]$Project, [Parameter()] [string]$UserEmail, [Parameter()] [string]$GroupName, [Parameter(Mandatory)] [ValidateSet('Reader', 'Contributor', 'ProjectAdministrator', 'BuildAdministrator')] [string]$Role ) BEGIN{ Write-Verbose "Beginning $($MyInvocation.Mycommand)" #Validate that either UserEmail or GroupName is specified IF(-not $UserEmail -and -not $GroupName) { Write-Error "You must specify either a UserEmail or a GroupName." RETURN } #Get Project ID $ProjectInfo = Get-AzDOProjects | Where-Object {$_.name -eq $Project} IF(-not $ProjectInfo) { Write-Error "Project '$Project' not found." RETURN } $ProjectId = $ProjectInfo.id Write-Verbose "Project ID: $ProjectId" #Map Role to Azure DevOps group name $RoleGroupMap = @{ 'Reader' = 'Readers' 'Contributor' = 'Contributors' 'ProjectAdministrator' = 'Project Administrators' 'BuildAdministrator' = 'Build Administrators' } $TargetGroupName = $RoleGroupMap[$Role] Write-Verbose "Target Group: $TargetGroupName" } PROCESS{ Write-Verbose "Processing $($MyInvocation.Mycommand)" #Get the project's security group descriptor $GroupsUri = "https://vssps.dev.azure.com/$Script:Organisation/_apis/graph/groups?scopeDescriptor=scp.$ProjectId&api-version=7.0-preview.1" Write-Verbose "Groups URI: $GroupsUri" TRY{ $Groups = Invoke-RestMethod -Uri $GroupsUri -Method GET -Headers $Header $TargetGroup = $Groups.value | Where-Object {$_.displayName -eq $TargetGroupName} IF(-not $TargetGroup) { Write-Error "Could not find group '$TargetGroupName' in project '$Project'." RETURN } Write-Verbose "Found target group: $($TargetGroup.displayName)" $GroupDescriptor = $TargetGroup.descriptor } CATCH{ Write-Error "Failed to get project groups: $_" RETURN } #Resolve the user or group to add IF($UserEmail) { #Get user descriptor by email $UserSearchUri = "https://vssps.dev.azure.com/$Script:Organisation/_apis/graph/users?api-version=7.0-preview.1" Write-Verbose "User Search URI: $UserSearchUri" TRY{ $Users = Invoke-RestMethod -Uri $UserSearchUri -Method GET -Headers $Header $User = $Users.value | Where-Object {$_.mailAddress -eq $UserEmail} IF(-not $User) { Write-Error "User with email '$UserEmail' not found in organisation." RETURN } Write-Verbose "Found user: $($User.displayName)" $MemberDescriptor = $User.descriptor } CATCH{ Write-Error "Failed to find user: $_" RETURN } } ELSEIF($GroupName) { #Get group descriptor by name $AllGroupsUri = "https://vssps.dev.azure.com/$Script:Organisation/_apis/graph/groups?api-version=7.0-preview.1" Write-Verbose "All Groups URI: $AllGroupsUri" TRY{ $AllGroups = Invoke-RestMethod -Uri $AllGroupsUri -Method GET -Headers $Header $SourceGroup = $AllGroups.value | Where-Object {$_.displayName -eq $GroupName} IF(-not $SourceGroup) { Write-Error "Group '$GroupName' not found in organisation." RETURN } Write-Verbose "Found group: $($SourceGroup.displayName)" $MemberDescriptor = $SourceGroup.descriptor } CATCH{ Write-Error "Failed to find group: $_" RETURN } } #Add member to the target group $AddMemberUri = "https://vssps.dev.azure.com/$Script:Organisation/_apis/graph/memberships/$MemberDescriptor/$GroupDescriptor`?api-version=7.0-preview.1" Write-Verbose "Add Member URI: $AddMemberUri" TRY{ $Result = Invoke-RestMethod -Uri $AddMemberUri -Method PUT -Headers $Header -ContentType $JsonContentType } CATCH{ Write-Error "Failed to add membership: $_" RETURN } } END{ Write-Verbose "Ending $($MyInvocation.Mycommand)" IF($Result) { IF($UserEmail) { Write-Output "Successfully added '$UserEmail' to '$TargetGroupName' in project '$Project'." } ELSE { Write-Output "Successfully added group '$GroupName' to '$TargetGroupName' in project '$Project'." } $Result } } } |