Modules/AzureDevOpsDsc.Common/Resources/Functions/Public/AzDoGitPermission/Get-AzDoGitPermission.ps1
|
<#
.SYNOPSIS Retrieves the Git repository permissions for a specified Azure DevOps project and repository. .DESCRIPTION The Get-AzDoGitPermission function retrieves the Git repository permissions for a specified Azure DevOps project and repository. It performs a lookup within the cache for the repository and retrieves the Access Control List (ACL) for the repository. The function then compares the retrieved ACLs with the provided permissions and returns the result. .PARAMETER ProjectName The name of the Azure DevOps project. .PARAMETER RepositoryName The name of the Git repository within the Azure DevOps project. .PARAMETER isInherited A boolean value indicating whether the permissions are inherited. .PARAMETER Permissions An optional hashtable array of permissions to compare against the retrieved ACLs. .PARAMETER LookupResult An optional hashtable to store the lookup result. .PARAMETER Ensure An optional parameter to specify the desired state of the permissions. .PARAMETER Force A switch parameter to force the operation. .EXAMPLE Get-AzDoGitPermission -ProjectName "MyProject" -RepositoryName "MyRepo" -isInherited $true This example retrieves the Git repository permissions for the "MyRepo" repository in the "MyProject" Azure DevOps project, considering inherited permissions. .NOTES The function relies on cached items for the repository and security namespace. It uses helper functions like Get-CacheItem, Get-DevOpsACL, ConvertTo-FormattedACL, ConvertTo-ACL, and Test-ACLListforChanges. #> Function Get-AzDoGitPermission { [CmdletBinding()] [OutputType([System.Management.Automation.PSObject[]])] param ( [Parameter(Mandatory = $true)] [string]$ProjectName, [Parameter(Mandatory = $false)] [string]$RepositoryName, [Parameter(Mandatory = $true)] [bool]$isInherited, [Parameter()] [HashTable[]]$Permissions, [Parameter()] [HashTable]$LookupResult, [Parameter()] [Ensure]$Ensure, [Parameter()] [System.Management.Automation.SwitchParameter] $Force ) Write-Verbose "[Get-AzDoGitPermission] Started." # Define the Descriptor Type and Organization Name $SecurityNamespace = 'Git Repositories' $OrganizationName = (Get-AzDoOrganizationName) Write-Verbose "[Get-AzDoGitPermission] Security Namespace: $SecurityNamespace" Write-Verbose "[Get-AzDoGitPermission] Organization Name: $OrganizationName" Write-Verbose "[Get-AzDoGitPermission] Project Name: $ProjectName" if ([String]::IsNullOrEmpty($RepositoryName)) { Write-Warning "[Get-AzDoGitPermission] RepositoryName not specified. Defaulting to top-level Project permissions" $RepositoryName = $null } else { Write-Verbose "[Get-AzDoGitPermission] Repository Name: $RepositoryName" } # # Construct a hashtable detailing the group $getGroupResult = @{ Ensure = [Ensure]::Absent propertiesChanged = @() project = $ProjectName repositoryName = $RepositoryName status = $null reason = $null } Write-Verbose "[Get-AzDoGitPermission] Group result hashtable constructed." Write-Verbose "[Get-AzDoGitPermission] Performing lookup of permissions for the repository." # Define the ACL List $ACLList = [System.Collections.Generic.List[Hashtable]]::new() # Perform a Lookup within the Cache for the Project, with live fallback $projectCache = Get-CacheItem -Key $ProjectName -Type 'LiveProjects' if (-not $projectCache) { Write-Verbose "[Get-AzDoGitPermission] Project '$ProjectName' not in cache — falling back to live API lookup." $projectCache = Invoke-AzDevOpsApiRestMethod -Uri "https://dev.azure.com/$OrganizationName/_apis/projects/${ProjectName}?api-version=7.1-preview.4" -Method Get if ($projectCache) { Add-CacheItem -Key $ProjectName -Value $projectCache -Type 'LiveProjects' } } # Test if the Project was found if (-not $projectCache) { Write-Warning "[Get-AzDoGitPermission] Project not found: $ProjectName" $getGroupResult.status = [DSCGetSummaryState]::Error $getGroupResult.reason = "Project not found: $ProjectName" return $getGroupResult } # Test if the RepositoryName was specified if ($RepositoryName) { # Write-Verbose "[Get-AzDoGitPermission] Repository Name: $RepositoryName is not null." # # Perform a Lookup within the Cache for the Repository $repoCacheKey = '{0}\{1}' -f $ProjectName, $RepositoryName $repositoryCache = Get-CacheItem -Key $repoCacheKey -Type 'LiveRepositories' if (-not $repositoryCache) { Write-Verbose "[Get-AzDoGitPermission] Repository '$RepositoryName' not in cache — falling back to live API lookup." $allRepos = Invoke-AzDevOpsApiRestMethod -Uri "https://dev.azure.com/$OrganizationName/$ProjectName/_apis/git/repositories?api-version=7.1-preview.1" -Method Get $repositoryCache = $allRepos.value | Where-Object { $_.name -eq $RepositoryName } | Select-Object -First 1 if ($repositoryCache) { Add-CacheItem -Key $repoCacheKey -Value $repositoryCache -Type 'LiveRepositories' } } # Test if the Repository was found, however only if the ProjectName was specified if (-not $repositoryCache) { Write-Warning "[Get-AzDoGitPermission] Repository not found: $RepositoryName" $getGroupResult.status = [DSCGetSummaryState]::NotFound return $getGroupResult } } # # Perform Lookup of the Permissions $namespace = Get-CacheItem -Key $SecurityNamespace -Type 'SecurityNamespaces' Write-Verbose "[Get-AzDoGitPermission] Retrieved namespace: $($namespace.namespaceId)" # Add to the ACL Lookup Params $getGroupResult.namespace = $namespace # Token-scope the ACL fetch to this repository's (or the project's) Git token instead of pulling # every ACL in the namespace. Fall back to the full-namespace fetch if the scoped query returns # nothing, so behaviour is never worse than the previous full scan. $aclToken = if ($RepositoryName) { 'repoV2/{0}/{1}' -f $projectCache.id, $repositoryCache.id } else { 'repoV2/{0}' -f $projectCache.id } $ACLLookupParams = @{ OrganizationName = $OrganizationName SecurityDescriptorId = $namespace.namespaceId Token = $aclToken } # Get the ACL List and format the ACLS Write-Verbose "[Get-AzDoGitPermission] ACL Lookup Params: $($ACLLookupParams | Out-String)" # Get the ACLs for the Repository $DevOpsACLs = Get-DevOpsACL @ACLLookupParams if ($null -eq $DevOpsACLs) { $DevOpsACLs = Get-DevOpsACL -OrganizationName $OrganizationName -SecurityDescriptorId $namespace.namespaceId } # Test if the ACLs were found if ($DevOpsACLs -eq $null) { Write-Error "[Get-AzDoGitPermission] No ACLs were found within the Security Namespace." $getGroupResult.status = [DSCGetSummaryState]::Error $getGroupResult.reason = "No ACLs were found within the Security Namespace." return $getGroupResult } # Convert the ACLs to a formatted ACL $DifferenceACLs = $DevOpsACLs | ConvertTo-FormattedACL -SecurityNamespace $SecurityNamespace -OrganizationName $OrganizationName # Test if the ACLs were found if ($DifferenceACLs -eq $null) { Write-Warning "[Get-AzDoGitPermission] No ACLs found for the repository." $getGroupResult.status = [DSCGetSummaryState]::NotFound return $getGroupResult } # Filter the ACLs for the Repository # If the Repository is not specified, return the GitProject ACLs if (-not $RepositoryName) { # Filter the ACLs for the top-level GitProject $DifferenceACLs = $DifferenceACLs | Where-Object { ($_.Token.Type -eq 'GitProject') -and ($_.Token.ProjectId -eq $projectCache.id) } } else { # Filter the ACLs for the GitRepository $DifferenceACLs = $DifferenceACLs | Where-Object { ($_.Token.Type -eq 'GitRepository') -and ($_.Token.RepoId -eq $repositoryCache.id) } } Write-Verbose "[Get-AzDoGitPermission] ACL List retrieved and formatted." # # Convert the Permissions into an ACL Token $params = @{ Permissions = $Permissions SecurityNamespace = $SecurityNamespace isInherited = $isInherited OrganizationName = $OrganizationName TokenName = $( if (-not $RepositoryName) { 'repoV2\{0}' -f $ProjectName } else { '[{0}]\{1}' -f $ProjectName, $RepositoryName }) } # Convert the Permissions to an ACL Token $ReferenceACLs = ConvertTo-ACL @params | Where-Object { $_.token.Type -ne 'GitUnknown' } # Compare the Reference ACLs to the Difference ACLs $compareResult = Test-ACLListforChanges -ReferenceACLs $ReferenceACLs -DifferenceACLs $DifferenceACLs $getGroupResult.propertiesChanged = $compareResult.propertiesChanged $getGroupResult.status = [DSCGetSummaryState]::"$($compareResult.status)" $getGroupResult.reason = $compareResult.reason Write-Verbose "[Get-AzDoGitPermission] ACL Token converted." Write-Verbose "[Get-AzDoGitPermission] ACL Token Comparison Result: $($getGroupResult.status)" # Export the ACL List to a file $getGroupResult.ReferenceACLs = $ReferenceACLs $getGroupResult.DifferenceACLs = $DifferenceACLs # Write Write-Verbose "[Get-AzDoGitPermission] Result Status: $($getGroupResult.status)" Write-Verbose "[Get-AzDoGitPermission] Returning Group Result." # Return the Group Result return $getGroupResult } |