Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve Post-Build Signing Validation in the VMR #47744

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 0 additions & 3 deletions eng/pipelines/templates/stages/vmr-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -998,7 +998,6 @@ stages:
steps:
- template: ../steps/vmr-validate-signing.yml
parameters:
artifactName: PackageArtifacts
continueOnError: true
OS: Windows_NT
- job: ValidateSigning_Mac
Expand All @@ -1008,7 +1007,6 @@ stages:
steps:
- template: ../steps/vmr-validate-signing.yml
parameters:
artifactName: BlobArtifacts
continueOnError: true
OS: Darwin
- job: ValidateSigning_Linux
Expand All @@ -1018,6 +1016,5 @@ stages:
steps:
- template: ../steps/vmr-validate-signing.yml
parameters:
artifactName: BlobArtifacts
continueOnError: true
OS: Linux
64 changes: 48 additions & 16 deletions eng/pipelines/templates/steps/vmr-validate-signing.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
parameters:
- name: artifactName
type: string

- name: continueOnError
type: boolean
default: false
Expand All @@ -13,13 +10,35 @@ parameters:
- Linux
- Darwin

## Internal properties not to be set by the user ##
- name: engDirectory
type: string
default: '$(Build.SourcesDirectory)/eng'

- name: outputDirectory
type: string
default: '$(Build.ArtifactStagingDirectory)/SigningValidation'

- name: msbuildCommand
type: string
default: |
MSBuild -restore ${{ parameters.engDirectory}}/signing-validation.proj /t:SigningValidation \
/p:AzureDevopsToken=$(System.AccessToken) \
/p:AzureDevOpsBaseUri=$(System.CollectionUri) \
/p:AzureDevOpsProject=$(System.TeamProject) \
/p:ArtifactDownloadDirectory=$(Build.ArtifactStagingDirectory) \
/p:BuildId=$(Build.BuildId) \
/p:DotNetRootDirectory=$(Build.SourcesDirectory) \
/p:MergedManifest=$(Build.ArtifactStagingDirectory)/AssetManifests/MergedManifest.xml \
/p:OutputLogsDirectory=${{ parameters.outputDirectory }}

steps:
- task: DownloadBuildArtifacts@1
- task: DownloadPipelineArtifact@1
inputs:
artifactName: ${{ parameters.artifactName }}
downloadPath: $(Build.ArtifactStagingDirectory)
checkDownloadedFiles: true
displayName: Download Artifacts
artifact: AssetManifests
itemPattern: '**/MergedManifest.xml'
downloadPath: $(Build.ArtifactStagingDirectory)/AssetManifests
displayName: Download Asset Manifest

# This is necessary whenever we want to publish/restore to an AzDO private feed
# Since sdk-task.ps1 tries to restore packages we need to do this authentication here
Expand All @@ -30,17 +49,30 @@ steps:
- ${{ if eq(parameters.OS, 'Windows_NT') }}:
- task: PowerShell@2
inputs:
filePath: eng\common\sdk-task.ps1
arguments: -task SigningValidation -restore -msbuildEngine vs
/p:PackageBasePath='$(Build.ArtifactStagingDirectory)/${{ parameters.artifactName }}'
displayName: Validate Signing of Packages
targetType: 'inline'
script: |
. ${{ parameters.engDirectory}}\common\tools.ps1

${{ parameters.msbuildCommand }}
displayName: Validate Signing
continueOnError: ${{ parameters.continueOnError }}

- ${{ else }}:
- task: Bash@3
inputs:
filePath: eng/common/sdk-task.sh
arguments: --task SigningValidation --restore
/p:PackageBasePath='$(Build.ArtifactStagingDirectory)/${{ parameters.artifactName }}'
displayName: Validate - ${{ parameters.OS }}
targetType: 'inline'
script: |
. ${{ parameters.engDirectory}}/common/tools.sh

${{ parameters.msbuildCommand }}
displayName: Validate Signing
continueOnError: ${{ parameters.continueOnError }}

- task: 1ES.PublishPipelineArtifact@1
displayName: Publish SignCheck Logs
continueOnError: true
inputs:
path: ${{ parameters.outputDirectory }}
artifactName: SignCheck_${{ parameters.OS }}
artifactType: Container
parallel: true
7 changes: 7 additions & 0 deletions src/SourceBuild/content/eng/SignCheckExclusionsFile.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
;; Exclusions for SignCheck. Corresponds to info in Signing.props.
;; Format: https://github.com/dotnet/arcade/blob/397316e195639450b6c76bfeb9823b40bee72d6d/src/SignCheck/Microsoft.SignCheck/Verification/Exclusion.cs#L23-L35

*apphost.exe;;Template, DO-NOT-SIGN, https://github.com/dotnet/core-setup/pull/7549
*singlefilehost.exe;;Template, DO-NOT-SIGN, https://github.com/dotnet/core-setup/pull/7549
*comhost.dll;;Template, DO-NOT-SIGN, https://github.com/dotnet/core-setup/pull/7549
*apphosttemplateapphostexe.exe;;Template, DO-NOT-SIGN, https://github.com/dotnet/core-setup/pull/7549
35 changes: 35 additions & 0 deletions src/SourceBuild/content/eng/signing-validation.proj
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<Project Sdk="Microsoft.Build.Traversal">

<PropertyGroup>
<TargetFramework>$(NetCurrent)</TargetFramework>
</PropertyGroup>

<ItemGroup>
<ProjectReference Include="$(TasksDir)Microsoft.DotNet.UnifiedBuild.Tasks\Microsoft.DotNet.UnifiedBuild.Tasks.csproj" />
</ItemGroup>

<UsingTask TaskName="Microsoft.DotNet.UnifiedBuild.Tasks.SigningValidation" AssemblyFile="$(MicrosoftDotNetUnifiedBuildTasksAssembly)" TaskFactory="TaskHostFactory" />
<Target Name="SigningValidation"
DependsOnTargets="ResolveProjectReferences"
BeforeTargets="Build">
<Error Condition="'$(AzureDevOpsBaseUri)' == ''" Text="AzureDevOpsBaseUri is not set." />
<Error Condition="'$(AzureDevOpsProject)' == ''" Text="AzureDevOpsProject is not set." />
<Error Condition="'$(ArtifactDownloadDirectory)' == ''" Text="ArtifactDownloadDirectory is not set." />
<Error Condition="'$(BuildId)' == ''" Text="BuildId is not set." />
<Error Condition="'$(DotNetRootDirectory)' == ''" Text="DotNetRootDirectory is not set." />
<Error Condition="'$(MergedManifest)' == ''" Text="MergedManifest is not set." />
<Error Condition="'$(OutputLogsDirectory)' == ''" Text="OutputLogsDirectory is not set." />

<!-- AzureDevOpsToken shouldn't be set when running in dnceng-public -->
<Microsoft.DotNet.UnifiedBuild.Tasks.SigningValidation
AzureDevOpsToken="$(AzureDevOpsToken)"
AzureDevOpsBaseUri="$(AzureDevOpsBaseUri)"
AzureDevOpsProject="$(AzureDevOpsProject)"
BuildId="$(BuildId)"
DotNetRootDirectory="$(DotNetRootDirectory)"
MergedManifest="$(MergedManifest)"
OutputLogsDirectory="$(OutputLogsDirectory)"
ArtifactDownloadDirectory="$(ArtifactDownloadDirectory)" />
</Target>

</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ public class AzureDevOpsClient : IDisposable
private const string _azureDevOpsApiVersion = "7.1-preview.5";
// download in 100 MB chunks
private const int _downloadBufferSize = 1024 * 1024 * 100;
private const int _httpTimeoutSeconds = 300;
private const int _httpTimeoutSeconds = 1800; // 30 minutes

public AzureDevOpsClient(
string? azureDevOpsToken,
Expand Down Expand Up @@ -52,9 +52,17 @@ public AzureDevOpsClient(
/// <summary>
/// Downloads a build artifact as zip file
/// </summary>
public async Task DownloadArtifactZip(string buildId, string artifactName, string downloadPath, int retryCount)
public async Task DownloadArtifactZip(
string buildId,
string artifactName,
string downloadPath,
int retryCount,
AzureDevOpsArtifactInformation? artifactInformation = null)
{
var artifactInformation = await GetArtifactInformation(buildId, artifactName, retryCount);
if (artifactInformation == null)
{
artifactInformation = await GetArtifactInformation(buildId, artifactName, retryCount);
}
string downloadUrl = artifactInformation.Resource.DownloadUrl;

_logger.LogMessage(MessageImportance.High, $"Downloading artifact zip from {downloadUrl}");
Expand Down Expand Up @@ -95,9 +103,23 @@ public async Task DownloadSingleFileFromArtifact(string buildId, string artifact
}
}

public async Task<ArtifactFiles> GetArtifactFilesInformation(string buildId, string artifactName, int retryCount)
public async Task<ArtifactFiles> GetArtifactFilesInformation(
string buildId,
string artifactName,
int retryCount,
AzureDevOpsArtifactInformation? artifactInformation = null)
{
var artifactInformation = await GetArtifactInformation(buildId, artifactName, retryCount);
if (artifactInformation == null)
{
artifactInformation = await GetArtifactInformation(buildId, artifactName, retryCount);
}

if (artifactInformation.Resource.Type == "Container")
{
throw new InvalidOperationException($"Artifact {artifactName} is a container." +
$"In order to get the list of files, please download and unzip the artifact.");
}

string artifactId = artifactInformation.Resource.Data;

var getManifestUrl = $"build/builds/{buildId}/artifacts?artifactName={artifactName}&fileId={artifactId}&fileName={artifactName}&api-version={_azureDevOpsApiVersion}";
Expand Down
Loading