Private/Resolve-CollectionPat.ps1
|
function Resolve-CollectionPat { <# .SYNOPSIS Resolves a PAT for a collection URL from the workspace secrets or the environment. .DESCRIPTION The fallback half of Entra-first authentication: when Entra sign-in is unavailable for a collection, Invoke-AzureDevOpsApi asks here for a stored PAT before giving up. Resolution order: 1. A secrets.json organisation entry matched by URL (trailing-slash and case insensitive), by Org name, or by org-name suffix of the URL. 2. The derived AZDO_PAT_<ORG> environment variable, where <ORG> is the last URL segment for dev.azure.com/<org> style URLs or the subdomain for <org>.visualstudio.com style URLs. Returns $null - never throws - when nothing matches. Cached per collection for the session. Never log the returned value. #> [CmdletBinding()] param( [Parameter(Mandatory)] [string]$Collection ) $key = $Collection.TrimEnd('/').ToLowerInvariant() if (-not $script:CollectionPatCache) { $script:CollectionPatCache = @{} } if ($script:CollectionPatCache.ContainsKey($key)) { return $script:CollectionPatCache[$key] } # The org name lives in a different URL segment per hosting style. $orgName = $null try { $uri = [uri]$Collection $orgName = if ($uri.Host -match '^(?<org>[^.]+)\.visualstudio\.com$') { $Matches['org'] } else { ($Collection.TrimEnd('/') -split '/')[-1] } } catch { $orgName = ($Collection.TrimEnd('/') -split '/')[-1] } $normalise = { param($value) if ($value) { $value.TrimEnd('/').ToLowerInvariant() } } $pat = $null if ($script:Workspace -and $script:Workspace.SecretsPath) { $secrets = @(Get-AutomationSecrets -SecretsPath $script:Workspace.SecretsPath) $match = $secrets | Where-Object { $_.AccessToken -and ( (& $normalise $_.Url) -eq (& $normalise $Collection) -or ($_.Org -and $orgName -and $_.Org -ieq $orgName) -or ($_.Org -and (& $normalise $Collection).EndsWith('/' + $_.Org.ToLowerInvariant())) ) } | Select-Object -First 1 if ($match) { $pat = $match.AccessToken } } if (-not $pat -and $orgName) { $envName = Get-DerivedPatEnvVarName -Org $orgName $envValue = [Environment]::GetEnvironmentVariable($envName) if (-not [string]::IsNullOrWhiteSpace($envValue)) { $pat = $envValue } } $script:CollectionPatCache[$key] = $pat return $pat } |