src/Connect-CciGet.ps1
|
function Connect-CciGet { <# .SYNOPSIS Register configured CCI feeds as PSResource repositories and prepare credentials. .DESCRIPTION For each enabled feed in Get-CciGetConfig, Connect-CciGet: - Ensures the Azure Artifacts Credential Provider is installed (one-time bootstrap on Windows; uses the Microsoft installer at https://github.com/microsoft/artifacts-credprovider). - Calls Register-PSResourceRepository for the feed (idempotent). After Connect-CciGet succeeds, Find-CciModule / Install-CciModule will transparently use the user's Entra identity (or, in CI, a workload identity) to authenticate to the feed. No PATs are required. .PARAMETER Tenant Optional. Limit registration to the named feed only. .PARAMETER SkipCredentialProvider Skip the credential-provider bootstrap (use when you have managed it centrally or are running in CI with a different auth strategy). #> [CmdletBinding()] param( [string]$Tenant, [switch]$SkipCredentialProvider ) if (-not (Get-Module -ListAvailable -Name Microsoft.PowerShell.PSResourceGet)) { throw "cciget: Microsoft.PowerShell.PSResourceGet is required but not installed. Run: Install-Module Microsoft.PowerShell.PSResourceGet -Scope CurrentUser" } Import-Module Microsoft.PowerShell.PSResourceGet -ErrorAction Stop if (-not $SkipCredentialProvider) { $pluginRoot = Join-Path $env:USERPROFILE '.nuget\plugins\netcore' if (-not (Test-Path $pluginRoot) -or -not (Get-ChildItem $pluginRoot -Filter 'CredentialProvider.Microsoft.dll' -Recurse -ErrorAction SilentlyContinue)) { Write-Host "cciget: installing Azure Artifacts Credential Provider..." try { $script = (New-Object System.Net.WebClient).DownloadString('https://aka.ms/install-artifacts-credprovider.ps1') Invoke-Expression $script } catch { Write-Warning "cciget: credential provider install failed: $_. You may need to install manually from https://github.com/microsoft/artifacts-credprovider." } } } $feeds = _Resolve-CciGetFeed -Tenant $Tenant $authFailed = @() foreach ($feed in $feeds) { $repoName = _Get-CciGetRepositoryName -FeedName $feed.name # Configure credential provider for this feed's tenant. # Enable device-code flow so auth works on machines where WIA is unavailable. if ($feed.tenantId) { $env:NUGET_CREDENTIALPROVIDER_MSAL_AUTHORITY = "https://login.microsoftonline.com/$($feed.tenantId)" } $env:NUGET_CREDENTIALPROVIDER_MSAL_ALLOW_DEVICECODEFLOW = 'true' $existing = Get-PSResourceRepository -Name $repoName -ErrorAction SilentlyContinue if ($existing) { if ($existing.Uri -ne $feed.url) { Set-PSResourceRepository -Name $repoName -Uri $feed.url -Trusted Write-Verbose "cciget: updated $repoName URL." } } else { Register-PSResourceRepository -Name $repoName -Uri $feed.url -Trusted Write-Host "cciget: registered repository '$repoName' -> $($feed.url)" } # Verify auth by probing the feed. This triggers the credential provider # now (at connect time) so auth issues surface here, not in Find-CciModule. Write-Host "cciget: authenticating to '$repoName'..." $probeOk = $false try { # A probe for a name that will never exist. If auth succeeds, we get # a "no match" error (which is fine). If auth fails, we get a # different error (401, credential-provider stderr, etc.). $null = Find-PSResource -Name '_cciget_auth_probe_' -Repository $repoName -ErrorAction Stop # If no error at all, auth worked (unexpected match or empty result). $probeOk = $true } catch { $msg = $_.Exception.Message if ($msg -match 'No match was found') { # Auth succeeded — feed simply has nothing matching the probe name. $probeOk = $true } elseif ($msg -match '\[Warning\].*CredentialProvider' -and $msg -notmatch '401|Unauthorized|forbidden') { # Credential provider emitted a deprecation warning (e.g. WIA obsolete) # but auth itself succeeded. Treat as non-fatal. Write-Verbose "cciget: credential provider warning (non-fatal): $msg" $probeOk = $true } else { Write-Warning "cciget: authentication failed for '$repoName'." Write-Warning " Error: $msg" $authFailed += $repoName } } if ($probeOk) { Write-Host "cciget: '$repoName' authenticated and ready." } } if ($authFailed.Count -gt 0) { Write-Warning "cciget: $($authFailed.Count) feed(s) failed authentication: $($authFailed -join ', ')" Write-Warning "cciget: You may need to run Connect-CciGet again. If prompted for a device code, complete the sign-in in your browser." } Get-PSResourceRepository -Name (_Get-CciGetRepositoryName -FeedName '*') } |