Skip to content

Commit 9b24fb6

Browse files
authored
Sign the DAC and DBI during the build process instead of in separate steps (#111416)
1 parent 3ee4c41 commit 9b24fb6

21 files changed

+271
-237
lines changed

eng/native/functions.cmake

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -678,3 +678,15 @@ function(adhoc_sign_with_entitlements targetName entitlementsFile)
678678
POST_BUILD
679679
COMMAND codesign -s - -f --entitlements ${entitlementsFile} $<TARGET_FILE:${targetName}>)
680680
endfunction()
681+
682+
function(esrp_sign targetName)
683+
if ("${CLR_CMAKE_ESRP_CLIENT}" STREQUAL "")
684+
return()
685+
endif()
686+
687+
add_custom_command(
688+
TARGET ${targetName}
689+
POST_BUILD
690+
COMMAND powershell -ExecutionPolicy ByPass -NoProfile "${CMAKE_CURRENT_FUNCTION_LIST_DIR}/sign-with-dac-certificate.ps1" -esrpClient ${CLR_CMAKE_ESRP_CLIENT} $<TARGET_FILE:${targetName}>
691+
)
692+
endfunction()
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
[CmdletBinding()]
2+
param(
3+
[string]
4+
[Parameter(Mandatory)]
5+
$esrpClient,
6+
[Parameter(ValueFromRemainingArguments=$true)][string[]]$filesToSign
7+
)
8+
9+
$inputFile = Get-Content -Raw $PSScriptRoot/signing/input.template.json | ConvertFrom-Json
10+
$inputFile.SignBatches.SignRequestFiles = $filesToSign | ForEach-Object {
11+
@{
12+
SourceLocation = $_
13+
}
14+
}
15+
16+
$inputJson = [System.IO.Path]::GetTempFileName()
17+
# Our JSON goes up to 6 levels deep, so we need to set the depth to 6
18+
# to successfully round-trip our JSON through ConvertTo-Json
19+
$inputFile | ConvertTo-Json -Depth 6 | Out-File -FilePath $inputJson -Encoding utf8
20+
21+
$outputJson = Resolve-Path "$PSScriptRoot/../../artifacts/log/Release/signing-$(New-Guid).json.log"
22+
23+
Write-Host "Signing files with DAC certificate"
24+
Write-Host "Logging output to $outputJson"
25+
26+
& $esrpClient sign -a $PSScriptRoot/signing/auth.json -c $PSScriptRoot/signing/config.json -i $inputJson -o $outputJson -p $PSScriptRoot/signing/policy.json
27+
28+
# Validate that the files are signed correctly
29+
foreach ($file in $filesToSign) {
30+
$signingCert = $(Get-AuthenticodeSignature $file).SignerCertificate
31+
if ($null -eq $signingCert)
32+
{
33+
throw "File $file does not contain a signature."
34+
}
35+
36+
if ($signingCert.Subject -ne "CN=.NET DAC, O=Microsoft Corporation, L=Redmond, S=Washington, C=US" `
37+
-or $signingCert.Issuer -ne "CN=Microsoft Code Signing PCA 2010, O=Microsoft Corporation, L=Redmond, S=Washington, C=US")
38+
{
39+
throw "File $file not in expected trust chain."
40+
}
41+
42+
$certEKU = $signingCert.Extensions.Where({ $_.Oid.FriendlyName -eq "Enhanced Key Usage" }) | Select-Object -First 1
43+
44+
if ($certEKU.EnhancedKeyUsages.Where({ $_.Value -eq "1.3.6.1.4.1.311.84.4.1" }).Count -ne 1)
45+
{
46+
throw "Signature for $file does not contain expected EKU."
47+
}
48+
49+
Write-Host "$file is correctly signed."
50+
}

eng/native/signing/auth.json

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
{
2+
"Version" : "1.0.0",
3+
"AuthenticationType" : "AAD_CERT",
4+
"TenantId" : "72f988bf-86f1-41af-91ab-2d7cd011db47",
5+
"ClientId" : "2234cdec-a13f-4bb2-aa63-04c57fd7a1f9",
6+
"AuthCert" :
7+
{
8+
"SubjectName" : "CN=2234cdec-a13f-4bb2-aa63-04c57fd7a1f9.microsoft.com",
9+
"StoreLocation" : "CurrentUser",
10+
"StoreName": "My",
11+
"SendX5c" : "true"
12+
},
13+
"RequestSigningCert" : {
14+
"SubjectName" : "CN=2234cdec-a13f-4bb2-aa63-04c57fd7a1f9",
15+
"StoreLocation" : "CurrentUser",
16+
"StoreName" : "My"
17+
}
18+
}

eng/native/signing/config.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"Version" : "1.0.0",
3+
"MaxDegreeOfParallelism" : "50",
4+
"ExponentialRetryCount" : "5",
5+
"EsrpSessionTimeoutInSec" : "1800"
6+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
{
2+
"Version": "1.0.0",
3+
"UseMinimatch" : false,
4+
"SignBatches": [
5+
{
6+
"SigningInfo" : {
7+
"Operations" : [
8+
{
9+
"keyCode": "CP-471322",
10+
"operationCode": "SigntoolSign",
11+
"parameters": {
12+
"OpusName": "Microsoft",
13+
"OpusInfo": "http://www.microsoft.com",
14+
"PageHash": "/NPH",
15+
"FileDigest": "/fd sha256",
16+
"TimeStamp": "/tr \"http://rfc3161.gtm.corp.microsoft.com/TSS/HttpTspServer\" /td sha256"
17+
},
18+
"toolName": "sign",
19+
"toolVersion": "1.0"
20+
},
21+
{
22+
"KeyCode": "CP-471322",
23+
"OperationCode": "SigntoolVerify",
24+
"Parameters": {},
25+
"ToolName": "sign",
26+
"ToolVersion": "1.0"
27+
}
28+
]
29+
},
30+
"SourceLocationType" : "UNC",
31+
"DestinationLocationType": "UNC",
32+
"SignRequestFiles" : [
33+
]
34+
}
35+
]
36+
}

eng/native/signing/policy.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"Version": "1.0.0"
3+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
parameters:
2+
isOfficialBuild:
3+
type: boolean
4+
displayName: 'Is Official Build'
5+
certNames:
6+
type: array
7+
displayName: 'Certificate Name'
8+
vaultName:
9+
type: string
10+
displayName: 'Key Vault Name'
11+
azureSubscription:
12+
type: string
13+
displayName: 'Azure Subscription'
14+
15+
steps:
16+
- ${{ if and(eq(parameters.isOfficialBuild, true), ne(variables['Build.Reason'], 'PullRequest'), or(startswith(variables['Build.SourceBranch'], 'refs/heads/release/'), startswith(variables['Build.SourceBranch'], 'refs/heads/internal/release/'), startswith(variables['Build.SourceBranch'], 'refs/heads/reltest/')), not(endsWith(variables['Build.SourceBranch'], '-staging'))) }}:
17+
- task: AzureKeyVault@2
18+
inputs:
19+
azureSubscription: ${{ parameters.azureSubscription }}
20+
KeyVaultName: ${{ parameters.vaultName }}
21+
SecretsFilter: ${{ join(',', parameters.certNames) }}
22+
displayName: 'Download secrets: Diagnostic Certificates'
23+
24+
- task: EsrpClientTool@2
25+
displayName: Download ESRPClient
26+
27+
- powershell: |
28+
eng/pipelines/install-diagnostic-certs.ps1 "${{ join(',', parameters.certNames) }}"
29+
$signArgs = '/p:DotNetEsrpToolPath=$(esrpclient.toolpath)\$(esrpclient.toolname)'
30+
echo "##vso[task.setvariable variable=_SignDiagnosticFilesArgs;]$signArgs"
31+
displayName: 'Install diagnostic certificates'
32+
env:
33+
${{ each cert in parameters.certNames }}:
34+
${{ cert }}: $(${{ cert }})
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
parameters:
2+
isOfficialBuild:
3+
type: boolean
4+
displayName: 'Is Official Build'
5+
6+
steps:
7+
- ${{ if and(eq(parameters.isOfficialBuild, true), ne(variables['Build.Reason'], 'PullRequest'), or(startswith(variables['Build.SourceBranch'], 'refs/heads/release/'), startswith(variables['Build.SourceBranch'], 'refs/heads/internal/release/'), startswith(variables['Build.SourceBranch'], 'refs/heads/reltest/')), not(endsWith(variables['Build.SourceBranch'], '-staging'))) }}:
8+
- powershell: |
9+
eng/pipelines/remove-diagnostic-certs.ps1 "$(DacCertificateThumbprints)"
10+
displayName: 'Remove Diagnostic Certificates'
11+
condition: always()

eng/pipelines/coreclr/templates/sign-diagnostic-files.yml

Lines changed: 0 additions & 86 deletions
This file was deleted.
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
[CmdletBinding()]
2+
param(
3+
[string]
4+
[Parameter(Mandatory)]
5+
$certList
6+
)
7+
# Required for the pipeline logging functions
8+
$ci = $true
9+
. $PSScriptRoot/../common/pipeline-logging-functions.ps1
10+
11+
$certs = $certList -split ','
12+
$thumbprints = @()
13+
$certCollection = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2Collection
14+
foreach ($cert in $certs)
15+
{
16+
$certBytes = [System.Convert]::FromBase64String($(Get-Item "Env:$cert").Value)
17+
$certCollection.Import($certBytes,$null, [System.Security.Cryptography.X509Certificates.X509KeyStorageFlags]::PersistKeySet)
18+
}
19+
20+
foreach ($cert in $certCollection)
21+
{
22+
Write-Host "Installed certificate '$($cert.Thumbprint)' with subject: '$($cert.Subject)'"
23+
$thumbprints += $cert.Thumbprint
24+
}
25+
26+
$store = Get-Item -Path Cert:\CurrentUser\My
27+
$store.Open([System.Security.Cryptography.X509Certificates.OpenFlags]::ReadWrite)
28+
$store.AddRange($certCollection)
29+
$store.Close()
30+
31+
Write-PipelineSetVariable -name "DacCertificateThumbprints" -Value "$($thumbprints -join ',')" -IsMultiJobVariable $false
32+
Write-Host "Successfully installed diagnostic certificates"

0 commit comments

Comments
 (0)