Skip to content
Merged
84 changes: 42 additions & 42 deletions eng/Version.Details.xml
Original file line number Diff line number Diff line change
Expand Up @@ -93,87 +93,87 @@
</Dependency>
</ProductDependencies>
<ToolsetDependencies>
<Dependency Name="Microsoft.DotNet.Arcade.Sdk" Version="9.0.0-beta.26301.4">
<Dependency Name="Microsoft.DotNet.Arcade.Sdk" Version="9.0.0-beta.26406.11">
<Uri>https://github.com/dotnet/arcade</Uri>
<Sha>efce34e9f9f25af27e2b471fbbf8c21f1ac2e318</Sha>
<Sha>f3bffca1f93573c88a7f9b79fac258dff76f6215</Sha>
</Dependency>
<!-- Intermediate is necessary for source build. -->
<Dependency Name="Microsoft.SourceBuild.Intermediate.arcade" Version="9.0.0-beta.26301.4">
<Dependency Name="Microsoft.SourceBuild.Intermediate.arcade" Version="9.0.0-beta.26406.11">
<Uri>https://github.com/dotnet/arcade</Uri>
<Sha>efce34e9f9f25af27e2b471fbbf8c21f1ac2e318</Sha>
<Sha>f3bffca1f93573c88a7f9b79fac258dff76f6215</Sha>
<SourceBuild RepoName="arcade" ManagedOnly="true" />
</Dependency>
<Dependency Name="Microsoft.DotNet.XliffTasks" Version="9.0.0-beta.26301.4">
<Dependency Name="Microsoft.DotNet.XliffTasks" Version="9.0.0-beta.26406.11">
<Uri>https://github.com/dotnet/arcade</Uri>
<Sha>efce34e9f9f25af27e2b471fbbf8c21f1ac2e318</Sha>
<Sha>f3bffca1f93573c88a7f9b79fac258dff76f6215</Sha>
</Dependency>
<Dependency Name="Microsoft.DotNet.Helix.Sdk" Version="9.0.0-beta.26301.4">
<Dependency Name="Microsoft.DotNet.Helix.Sdk" Version="9.0.0-beta.26406.11">
<Uri>https://github.com/dotnet/arcade</Uri>
<Sha>efce34e9f9f25af27e2b471fbbf8c21f1ac2e318</Sha>
<Sha>f3bffca1f93573c88a7f9b79fac258dff76f6215</Sha>
</Dependency>
<Dependency Name="Microsoft.DotNet.GenAPI" Version="9.0.0-beta.26301.4">
<Dependency Name="Microsoft.DotNet.GenAPI" Version="9.0.0-beta.26406.11">
<Uri>https://github.com/dotnet/arcade</Uri>
<Sha>efce34e9f9f25af27e2b471fbbf8c21f1ac2e318</Sha>
<Sha>f3bffca1f93573c88a7f9b79fac258dff76f6215</Sha>
</Dependency>
<Dependency Name="Microsoft.DotNet.GenFacades" Version="9.0.0-beta.26301.4">
<Dependency Name="Microsoft.DotNet.GenFacades" Version="9.0.0-beta.26406.11">
<Uri>https://github.com/dotnet/arcade</Uri>
<Sha>efce34e9f9f25af27e2b471fbbf8c21f1ac2e318</Sha>
<Sha>f3bffca1f93573c88a7f9b79fac258dff76f6215</Sha>
</Dependency>
<Dependency Name="Microsoft.DotNet.XUnitAssert" Version="2.9.0-beta.26301.4">
<Dependency Name="Microsoft.DotNet.XUnitAssert" Version="2.9.0-beta.26406.11">
<Uri>https://github.com/dotnet/arcade</Uri>
<Sha>efce34e9f9f25af27e2b471fbbf8c21f1ac2e318</Sha>
<Sha>f3bffca1f93573c88a7f9b79fac258dff76f6215</Sha>
</Dependency>
<Dependency Name="Microsoft.DotNet.XUnitExtensions" Version="9.0.0-beta.26301.4">
<Dependency Name="Microsoft.DotNet.XUnitExtensions" Version="9.0.0-beta.26406.11">
<Uri>https://github.com/dotnet/arcade</Uri>
<Sha>efce34e9f9f25af27e2b471fbbf8c21f1ac2e318</Sha>
<Sha>f3bffca1f93573c88a7f9b79fac258dff76f6215</Sha>
</Dependency>
<Dependency Name="Microsoft.DotNet.XUnitConsoleRunner" Version="2.9.0-beta.26301.4">
<Dependency Name="Microsoft.DotNet.XUnitConsoleRunner" Version="2.9.0-beta.26406.11">
<Uri>https://github.com/dotnet/arcade</Uri>
<Sha>efce34e9f9f25af27e2b471fbbf8c21f1ac2e318</Sha>
<Sha>f3bffca1f93573c88a7f9b79fac258dff76f6215</Sha>
</Dependency>
<Dependency Name="Microsoft.DotNet.Build.Tasks.Archives" Version="9.0.0-beta.26301.4">
<Dependency Name="Microsoft.DotNet.Build.Tasks.Archives" Version="9.0.0-beta.26406.11">
<Uri>https://github.com/dotnet/arcade</Uri>
<Sha>efce34e9f9f25af27e2b471fbbf8c21f1ac2e318</Sha>
<Sha>f3bffca1f93573c88a7f9b79fac258dff76f6215</Sha>
</Dependency>
<Dependency Name="Microsoft.DotNet.Build.Tasks.Packaging" Version="9.0.0-beta.26301.4">
<Dependency Name="Microsoft.DotNet.Build.Tasks.Packaging" Version="9.0.0-beta.26406.11">
<Uri>https://github.com/dotnet/arcade</Uri>
<Sha>efce34e9f9f25af27e2b471fbbf8c21f1ac2e318</Sha>
<Sha>f3bffca1f93573c88a7f9b79fac258dff76f6215</Sha>
</Dependency>
<Dependency Name="Microsoft.DotNet.Build.Tasks.Installers" Version="9.0.0-beta.26301.4">
<Dependency Name="Microsoft.DotNet.Build.Tasks.Installers" Version="9.0.0-beta.26406.11">
<Uri>https://github.com/dotnet/arcade</Uri>
<Sha>efce34e9f9f25af27e2b471fbbf8c21f1ac2e318</Sha>
<Sha>f3bffca1f93573c88a7f9b79fac258dff76f6215</Sha>
</Dependency>
<Dependency Name="Microsoft.DotNet.Build.Tasks.Templating" Version="9.0.0-beta.26301.4">
<Dependency Name="Microsoft.DotNet.Build.Tasks.Templating" Version="9.0.0-beta.26406.11">
<Uri>https://github.com/dotnet/arcade</Uri>
<Sha>efce34e9f9f25af27e2b471fbbf8c21f1ac2e318</Sha>
<Sha>f3bffca1f93573c88a7f9b79fac258dff76f6215</Sha>
</Dependency>
<Dependency Name="Microsoft.DotNet.Build.Tasks.Workloads" Version="9.0.0-beta.26301.4">
<Dependency Name="Microsoft.DotNet.Build.Tasks.Workloads" Version="9.0.0-beta.26406.11">
<Uri>https://github.com/dotnet/arcade</Uri>
<Sha>efce34e9f9f25af27e2b471fbbf8c21f1ac2e318</Sha>
<Sha>f3bffca1f93573c88a7f9b79fac258dff76f6215</Sha>
</Dependency>
<Dependency Name="Microsoft.DotNet.CodeAnalysis" Version="9.0.0-beta.26301.4">
<Dependency Name="Microsoft.DotNet.CodeAnalysis" Version="9.0.0-beta.26406.11">
<Uri>https://github.com/dotnet/arcade</Uri>
<Sha>efce34e9f9f25af27e2b471fbbf8c21f1ac2e318</Sha>
<Sha>f3bffca1f93573c88a7f9b79fac258dff76f6215</Sha>
</Dependency>
<Dependency Name="Microsoft.DotNet.Build.Tasks.TargetFramework" Version="9.0.0-beta.26301.4">
<Dependency Name="Microsoft.DotNet.Build.Tasks.TargetFramework" Version="9.0.0-beta.26406.11">
<Uri>https://github.com/dotnet/arcade</Uri>
<Sha>efce34e9f9f25af27e2b471fbbf8c21f1ac2e318</Sha>
<Sha>f3bffca1f93573c88a7f9b79fac258dff76f6215</Sha>
</Dependency>
<Dependency Name="Microsoft.DotNet.RemoteExecutor" Version="9.0.0-beta.26301.4">
<Dependency Name="Microsoft.DotNet.RemoteExecutor" Version="9.0.0-beta.26406.11">
<Uri>https://github.com/dotnet/arcade</Uri>
<Sha>efce34e9f9f25af27e2b471fbbf8c21f1ac2e318</Sha>
<Sha>f3bffca1f93573c88a7f9b79fac258dff76f6215</Sha>
</Dependency>
<Dependency Name="Microsoft.DotNet.Build.Tasks.Feed" Version="9.0.0-beta.26301.4">
<Dependency Name="Microsoft.DotNet.Build.Tasks.Feed" Version="9.0.0-beta.26406.11">
<Uri>https://github.com/dotnet/arcade</Uri>
<Sha>efce34e9f9f25af27e2b471fbbf8c21f1ac2e318</Sha>
<Sha>f3bffca1f93573c88a7f9b79fac258dff76f6215</Sha>
</Dependency>
<Dependency Name="Microsoft.DotNet.VersionTools.Tasks" Version="9.0.0-beta.26301.4">
<Dependency Name="Microsoft.DotNet.VersionTools.Tasks" Version="9.0.0-beta.26406.11">
<Uri>https://github.com/dotnet/arcade</Uri>
<Sha>efce34e9f9f25af27e2b471fbbf8c21f1ac2e318</Sha>
<Sha>f3bffca1f93573c88a7f9b79fac258dff76f6215</Sha>
</Dependency>
<Dependency Name="Microsoft.DotNet.SharedFramework.Sdk" Version="9.0.0-beta.26301.4">
<Dependency Name="Microsoft.DotNet.SharedFramework.Sdk" Version="9.0.0-beta.26406.11">
<Uri>https://github.com/dotnet/arcade</Uri>
<Sha>efce34e9f9f25af27e2b471fbbf8c21f1ac2e318</Sha>
<Sha>f3bffca1f93573c88a7f9b79fac258dff76f6215</Sha>
</Dependency>
<Dependency Name="System.ComponentModel.TypeConverter.TestData" Version="9.0.0-beta.26330.2">
<Uri>https://github.com/dotnet/runtime-assets</Uri>
Expand Down Expand Up @@ -333,9 +333,9 @@
<Uri>https://github.com/dotnet/xharness</Uri>
<Sha>4da0015e9dd1ed7d3992db7d1eb6878a5ee11ab2</Sha>
</Dependency>
<Dependency Name="Microsoft.DotNet.PackageTesting" Version="9.0.0-beta.26301.4">
<Dependency Name="Microsoft.DotNet.PackageTesting" Version="9.0.0-beta.26406.11">
<Uri>https://github.com/dotnet/arcade</Uri>
<Sha>efce34e9f9f25af27e2b471fbbf8c21f1ac2e318</Sha>
<Sha>f3bffca1f93573c88a7f9b79fac258dff76f6215</Sha>
</Dependency>
<Dependency Name="optimization.windows_nt-x64.MIBC.Runtime" Version="1.0.0-prerelease.24462.2">
<Uri>https://dev.azure.com/dnceng/internal/_git/dotnet-optimization</Uri>
Expand Down
32 changes: 16 additions & 16 deletions eng/Versions.props
Original file line number Diff line number Diff line change
Expand Up @@ -84,22 +84,22 @@
<!-- SDK dependencies (also used in wasm build tests -->
<MicrosoftDotNetApiCompatTaskVersion>9.0.109</MicrosoftDotNetApiCompatTaskVersion>
<!-- Arcade dependencies -->
<MicrosoftDotNetBuildTasksFeedVersion>9.0.0-beta.26301.4</MicrosoftDotNetBuildTasksFeedVersion>
<MicrosoftDotNetCodeAnalysisVersion>9.0.0-beta.26301.4</MicrosoftDotNetCodeAnalysisVersion>
<MicrosoftDotNetGenAPIVersion>9.0.0-beta.26301.4</MicrosoftDotNetGenAPIVersion>
<MicrosoftDotNetGenFacadesVersion>9.0.0-beta.26301.4</MicrosoftDotNetGenFacadesVersion>
<MicrosoftDotNetXUnitAssertVersion>2.9.0-beta.26301.4</MicrosoftDotNetXUnitAssertVersion>
<MicrosoftDotNetXUnitExtensionsVersion>9.0.0-beta.26301.4</MicrosoftDotNetXUnitExtensionsVersion>
<MicrosoftDotNetXUnitConsoleRunnerVersion>2.9.0-beta.26301.4</MicrosoftDotNetXUnitConsoleRunnerVersion>
<MicrosoftDotNetBuildTasksArchivesVersion>9.0.0-beta.26301.4</MicrosoftDotNetBuildTasksArchivesVersion>
<MicrosoftDotNetBuildTasksInstallersVersion>9.0.0-beta.26301.4</MicrosoftDotNetBuildTasksInstallersVersion>
<MicrosoftDotNetBuildTasksPackagingVersion>9.0.0-beta.26301.4</MicrosoftDotNetBuildTasksPackagingVersion>
<MicrosoftDotNetBuildTasksTargetFrameworkVersion>9.0.0-beta.26301.4</MicrosoftDotNetBuildTasksTargetFrameworkVersion>
<MicrosoftDotNetBuildTasksTemplatingVersion>9.0.0-beta.26301.4</MicrosoftDotNetBuildTasksTemplatingVersion>
<MicrosoftDotNetBuildTasksWorkloadsPackageVersion>9.0.0-beta.26301.4</MicrosoftDotNetBuildTasksWorkloadsPackageVersion>
<MicrosoftDotNetRemoteExecutorVersion>9.0.0-beta.26301.4</MicrosoftDotNetRemoteExecutorVersion>
<MicrosoftDotNetVersionToolsTasksVersion>9.0.0-beta.26301.4</MicrosoftDotNetVersionToolsTasksVersion>
<MicrosoftDotNetPackageTestingVersion>9.0.0-beta.26301.4</MicrosoftDotNetPackageTestingVersion>
<MicrosoftDotNetBuildTasksFeedVersion>9.0.0-beta.26406.11</MicrosoftDotNetBuildTasksFeedVersion>
<MicrosoftDotNetCodeAnalysisVersion>9.0.0-beta.26406.11</MicrosoftDotNetCodeAnalysisVersion>
<MicrosoftDotNetGenAPIVersion>9.0.0-beta.26406.11</MicrosoftDotNetGenAPIVersion>
<MicrosoftDotNetGenFacadesVersion>9.0.0-beta.26406.11</MicrosoftDotNetGenFacadesVersion>
<MicrosoftDotNetXUnitAssertVersion>2.9.0-beta.26406.11</MicrosoftDotNetXUnitAssertVersion>
<MicrosoftDotNetXUnitExtensionsVersion>9.0.0-beta.26406.11</MicrosoftDotNetXUnitExtensionsVersion>
<MicrosoftDotNetXUnitConsoleRunnerVersion>2.9.0-beta.26406.11</MicrosoftDotNetXUnitConsoleRunnerVersion>
<MicrosoftDotNetBuildTasksArchivesVersion>9.0.0-beta.26406.11</MicrosoftDotNetBuildTasksArchivesVersion>
<MicrosoftDotNetBuildTasksInstallersVersion>9.0.0-beta.26406.11</MicrosoftDotNetBuildTasksInstallersVersion>
<MicrosoftDotNetBuildTasksPackagingVersion>9.0.0-beta.26406.11</MicrosoftDotNetBuildTasksPackagingVersion>
<MicrosoftDotNetBuildTasksTargetFrameworkVersion>9.0.0-beta.26406.11</MicrosoftDotNetBuildTasksTargetFrameworkVersion>
<MicrosoftDotNetBuildTasksTemplatingVersion>9.0.0-beta.26406.11</MicrosoftDotNetBuildTasksTemplatingVersion>
<MicrosoftDotNetBuildTasksWorkloadsPackageVersion>9.0.0-beta.26406.11</MicrosoftDotNetBuildTasksWorkloadsPackageVersion>
<MicrosoftDotNetRemoteExecutorVersion>9.0.0-beta.26406.11</MicrosoftDotNetRemoteExecutorVersion>
<MicrosoftDotNetVersionToolsTasksVersion>9.0.0-beta.26406.11</MicrosoftDotNetVersionToolsTasksVersion>
<MicrosoftDotNetPackageTestingVersion>9.0.0-beta.26406.11</MicrosoftDotNetPackageTestingVersion>
<!-- TODO: Remove pinned xunit.analyzers version: https://github.com/dotnet/runtime/issues/97088 -->
<XUnitAnalyzersVersion>1.4.0</XUnitAnalyzersVersion>
<!-- NuGet dependencies -->
Expand Down
154 changes: 154 additions & 0 deletions eng/common/Get-GitHubAppToken.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
# Mints a short-lived GitHub App installation access token by signing a JWT
# with a private key stored in Azure Key Vault (RSA, RS256). The signed JWT is
# exchanged with the GitHub API for a token scoped to a single installation.
#
# Requirements:
# - A GitHub App whose private key has been uploaded into Key Vault as an RSA
# key (the PEM converted to a Key Vault *key*, NOT stored as a secret).
# - The caller (the federated Azure service connection used to run this script)
# must have the `Key Vault Crypto User` role (or at minimum the `Sign`
# action) on that key.
# - The App must be installed on the target organization/account
# (`InstallationOwner`) with the permissions/repositories it needs.
#
# Installation tokens (ghs_*) are exempt from the enterprise classic-PAT
# lifetime policy, which is why this replaces the long-lived PAT.

[CmdletBinding()]
param(
# Name of the Key Vault that holds the GitHub App's RSA signing key.
[Parameter(Mandatory = $true)]
[string] $KeyVaultName,

# Name of the RSA key inside the Key Vault (the App's private key).
[Parameter(Mandatory = $true)]
[string] $KeyName,

# The GitHub App's Client ID (the value to put in the `iss` JWT claim).
[Parameter(Mandatory = $true)]
[string] $AppClientId,

# Login of the organization or user account whose installation we should
# mint the token for (e.g. `dotnet`, `microsoft`).
[Parameter(Mandatory = $true)]
[string] $InstallationOwner,

# Optional Azure DevOps pipeline variable name to set with the installation
# token (marked as a secret). When not specified, the token is written to
# stdout instead.
[Parameter(Mandatory = $false)]
[string] $OutputVariableName
)

$ErrorActionPreference = 'Stop'
$PSNativeCommandUseErrorActionPreference = $true

. $PSScriptRoot\pipeline-logging-functions.ps1

function ConvertTo-Base64Url([byte[]] $bytes) {
return [Convert]::ToBase64String($bytes).TrimEnd('=').Replace('+', '-').Replace('/', '_')
}

# Build JWT header and payload. Use [ordered] hashtables so JSON
# serialization is deterministic.
$jwtHeader = [ordered]@{
alg = 'RS256'
typ = 'JWT'
}
$now = [System.DateTimeOffset]::UtcNow
$jwtPayload = [ordered]@{
iat = $now.AddMinutes(-1).ToUnixTimeSeconds()
exp = $now.AddMinutes(5).ToUnixTimeSeconds()
iss = $AppClientId
}

$headerEncoded = ConvertTo-Base64Url ([System.Text.Encoding]::UTF8.GetBytes(($jwtHeader | ConvertTo-Json -Compress)))
$payloadEncoded = ConvertTo-Base64Url ([System.Text.Encoding]::UTF8.GetBytes(($jwtPayload | ConvertTo-Json -Compress)))
$signingInput = "$headerEncoded.$payloadEncoded"

# Key Vault `sign` expects the *digest* (base64), not the raw bytes.
$sha256 = [System.Security.Cryptography.SHA256]::Create()
$digestBytes = $sha256.ComputeHash([System.Text.Encoding]::UTF8.GetBytes($signingInput))
$digestBase64 = [Convert]::ToBase64String($digestBytes)

Write-Host "Signing JWT with key '$KeyName' in vault '$KeyVaultName'..."
$previousNativeCommandErrorPreference = $PSNativeCommandUseErrorActionPreference
try {
# Azure CLI can emit non-fatal Python warnings to stderr even when signing succeeds.
# Use the exit code to determine success for this invocation.
$PSNativeCommandUseErrorActionPreference = $false
$signatureBase64 = az keyvault key sign `
--vault-name $KeyVaultName `
--name $KeyName `
--algorithm RS256 `
--digest $digestBase64 `
--query signature `
--output tsv `
--only-show-errors
$signExitCode = $LASTEXITCODE
}
catch {
Write-PipelineTelemetryError -Category 'Build' -Message "Failed to sign the JWT via Key Vault (key '$KeyName', vault '$KeyVaultName'): $_. Verify the service connection identity has the 'Key Vault Crypto User' role (Sign action) on the key."
exit 1
}
finally {
$PSNativeCommandUseErrorActionPreference = $previousNativeCommandErrorPreference
}
if ($signExitCode -ne 0 -or [string]::IsNullOrWhiteSpace($signatureBase64)) {
Write-PipelineTelemetryError -Category 'Build' -Message "'az keyvault key sign' exited with code $signExitCode for key '$KeyName' in vault '$KeyVaultName'. Verify the service connection identity has the 'Key Vault Crypto User' role (Sign action) on the key."
exit 1
}
$signatureUrl = $signatureBase64.Trim().TrimEnd('=').Replace('+', '-').Replace('/', '_')
$jwt = "$signingInput.$signatureUrl"

$headers = @{
Authorization = "Bearer $jwt"
'X-GitHub-Api-Version' = '2022-11-28'
Accept = 'application/vnd.github+json'
'User-Agent' = 'dotnet-arcade-onelocbuild'
}

Write-Host "Looking up installation for '$InstallationOwner'..."
try {
$installations = @()
$page = 1
do {
$pageInstallations = @(Invoke-RestMethod `
-Uri "https://api.github.com/app/installations?per_page=100&page=$page" `
-Headers $headers `
-Method Get)
$installations += $pageInstallations
$page++
} while ($pageInstallations.Count -eq 100)
}
catch {
Write-PipelineTelemetryError -Category 'Build' -Message "Failed to list GitHub App installations: $_. The signed JWT may be invalid or the App's Client ID ('$AppClientId') may be incorrect."
exit 1
}
$installation = $installations | Where-Object { $_.account.login -ieq $InstallationOwner } | Select-Object -First 1
if (-not $installation) {
$found = ($installations | ForEach-Object { $_.account.login }) -join ', '
Write-PipelineTelemetryError -Category 'Build' -Message "No installation found for '$InstallationOwner'. App is installed on: $found"
exit 1
}

try {
$tokenResponse = Invoke-RestMethod `
-Uri "https://api.github.com/app/installations/$($installation.id)/access_tokens" `
-Headers $headers `
-Method Post `
-ContentType 'application/json'
}
catch {
Write-PipelineTelemetryError -Category 'Build' -Message "Failed to mint an installation access token for '$InstallationOwner' (installation $($installation.id)): $_"
exit 1
}

Write-Host "Got installation token for '$InstallationOwner' (expires $($tokenResponse.expires_at))."
if ($OutputVariableName) {
Write-Host "Setting pipeline variable '$OutputVariableName'."
Write-Host "##vso[task.setvariable variable=$OutputVariableName;issecret=true]$($tokenResponse.token)"
}
else {
Write-Host $tokenResponse.token -ForegroundColor Green
}
Loading
Loading