diff --git a/NOTICE.txt b/NOTICE.txt new file mode 100644 index 0000000..e69de29 diff --git a/build/CopyUniqueBins.ps1 b/build/CopyUniqueBins.ps1 new file mode 100644 index 0000000..9f16541 --- /dev/null +++ b/build/CopyUniqueBins.ps1 @@ -0,0 +1,91 @@ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT license. + +# This script is used to copy unique files to a directory and saving the mapping for use later. It is intended to help reduce the burden on the ESRP signing service. +[CmdletBinding(DefaultParameterSetName = 'Find')] +Param +( + [Parameter(ParameterSetName = 'Find')][string]$MappingFileOut, + [Parameter(ParameterSetName = 'Find')][string]$SearchFilter = "*", + [Parameter(ParameterSetName = 'Find')][string]$CopyDestination, + [Parameter(ParameterSetName = 'CopyMapping')][string]$MappingFileIn, + [Parameter(ParameterSetName = 'Find')][Parameter(ParameterSetName = 'CopyMapping')][string]$CopySource +) + +# Ensure paths use consistent separator char +$MappingFileOut = $MappingFileOut.Replace('\', '/') +$MappingFileIn = $MappingFileIn.Replace('\', '/') +$CopyDestination = $CopyDestination.Replace('\', '/') +$CopySource = $CopySource.Replace('\', '/') + +Write-Host "params:" +Write-Host "MappingFileOut: $MappingFileOut" +Write-Host "SearchFilter: $SearchFilter" +Write-Host "CopyDestination: $CopyDestination" +Write-Host "MappingFileIn: $MappingFileIn" +Write-Host "CopySource: $CopySource" +$ErrorActionPreference = "stop" + +# create mapping and copy unique files +if ($PSCmdlet.ParameterSetName -eq 'Find') +{ + if ((Test-Path $CopyDestination) -eq $false) + { + $null = New-Item -Path $CopyDestination -ItemType Directory + } + + $files = Get-ChildItem $CopySource -Filter $SearchFilter -Recurse -File + # hashtable of file names & array of full paths that file is found in + $mapping = @{} + foreach ($file in $files) + { + # Find hash of file. If it's new, add new kvp to mapping & copy file with uniqified name. Else add to value array. + $hash = (Get-FileHash $file).Hash + + if ($mapping.ContainsKey("$($hash)__$($file.Name)") -eq $false) + { + Write-Host "Copying unique file $($file.FullName) wuth hash $hash to $CopyDestination\$($hash)__$($file.Name)" + $mapping.Add("$($hash)__$($file.Name)", @($file.FullName)) + Copy-Item $file "$CopyDestination\$($hash)__$($file.Name)" + } + else + { + $currentArray = $mapping["$($hash)__$($file.Name)"] + $currentArray += $file.FullName + $mapping["$($hash)__$($file.Name)"] = $currentArray + Write-Host "Adding mapping for file $($file.FullName) with hash $hash" + } + } + + Get-ChildItem $CopyDestination + + # serialize mapping to file so we can use after signing + $OutFolder = [System.IO.Path]::GetDirectoryName($MappingFileOut) + if ((Test-Path $OutFolder) -eq $false) + { + $null = New-Item -Path $OutFolder -ItemType Directory + } + Export-Clixml -InputObject $mapping -Depth 5 -Path $MappingFileOut +} +else # use mapping to copy unique files to all locations. Done after files are signed. +{ + # deserialize mapping + $mapping = Import-Clixml -Path $MappingFileIn + + # get all files to copy + $files = Get-ChildItem $CopySource -Recurse -File + Write-Host "$($files.Count) files found in $CopySource" + + foreach ($file in $files) + { + if ($mapping.ContainsKey($file.Name) -eq $true) + { + # if file is in mapping, copy to destinations specified + foreach ($dest in $mapping[$file.Name]) + { + Write-Host "Copying file $($file.FullName) to $dest" + Copy-Item $file $dest + } + } + } +} diff --git a/build/build.yml b/build/build.yml new file mode 100644 index 0000000..d8f957e --- /dev/null +++ b/build/build.yml @@ -0,0 +1,139 @@ +trigger: +- none +pr: +- none + +resources: + repositories: + - repository: ComplianceRepo + type: github + endpoint: microsoft + name: PowerShell/Compliance + ref: master + +variables: + SigningServer: "http://rfc3161.gtm.corp.microsoft.com/TSS/HttpTspServer" + BuildConfiguration: 'Release' + ${{ if or(startsWith(variables['Build.SourceBranch'], 'refs/tags/v'), eq(variables['Build.SourceBranchName'], 'main')) }}: + SKIPSIGN: 'false' + ${{ if not(or(startsWith(variables['Build.SourceBranch'], 'refs/tags/v'), eq(variables['Build.SourceBranchName'], 'main'))) }}: + SKIPSIGN: 'true' + +jobs: + - job: Build_projects_and_publish_vpack + pool: + name: Package ES Standard Build + steps: + - task: UseDotNet@2 + displayName: 'Use .NET Core 3.1 sdk' + inputs: + packageType: sdk + version: 3.1.x + installationPath: $(Agent.ToolsDirectory)\dotnet + - template: ./templates/template-set-should-sign.yml + - pwsh: | + Get-Item -Path env:* | Sort-Object Name + displayName: "Print all variables" + + # Publish app for Windows & Linux + - template: ./templates/template-dotnet-publish.yml + parameters: + BuildPlatform: 'x86' + - template: ./templates/template-dotnet-publish.yml + parameters: + BuildPlatform: 'x64' + - template: ./templates/template-dotnet-publish.yml + parameters: + BuildPlatform: 'arm' + - template: ./templates/template-dotnet-publish.yml + parameters: + BuildPlatform: 'arm64' + - template: ./templates/template-dotnet-publish.yml + parameters: + BuildPlatform: 'x64' + BuildOS: 'linux' + - template: ./templates/template-dotnet-publish.yml + parameters: + BuildPlatform: 'arm' + BuildOS: 'linux' + - template: ./templates/template-dotnet-publish.yml + parameters: + BuildPlatform: 'arm64' + BuildOS: 'linux' + + # uniqify binaries to speed up signing process by not signing dup files + - task: PowerShell@2 + inputs: + targetType: filePath + filePath: $(Build.SourcesDirectory)/build/internal/CopyUniqueBins.ps1 + arguments: '-CopySource "$(Build.ArtifactStagingDirectory)/Publish" -CopyDestination "$(System.DefaultWorkingDirectory)/unsigneduniquefiles" -MappingFileOut "$(System.DefaultWorkingDirectory)/mappingfile.xml"' + failOnStderr: true + pwsh: true + displayName: 'Copy unique files to staging directory' + + # ​​CP-230012 is for Microsoft authored binaries. Authenticode signing. + - template: EsrpSign.yml@ComplianceRepo + parameters: + buildOutputPath: '$(System.DefaultWorkingDirectory)/unsigneduniquefiles/' + signOutputPath: '$(System.DefaultWorkingDirectory)/signeduniquefiles_stage1/' + certificateId: 'CP-230012' + pattern: '*__FindDevice.dll,*__FindDevice.exe' + useMinimatch: false + shouldSign: ${{ parameters.ShouldSign }} + alwaysCopy: 'true' + signingService: 'FactoryOrchestratorSigning' + verifySignature: 'true' + pageHash: 'false' + + # CP-231522​ is for 3rd party authored binaries (OSS). + - template: EsrpSign.yml@ComplianceRepo + parameters: + buildOutputPath: '$(System.DefaultWorkingDirectory)/signeduniquefiles_stage1/' + signOutputPath: '$(System.DefaultWorkingDirectory)/signeduniquefiles_stage2/' + certificateId: 'CP-231522' + pattern: '*__Common.Logging*.dll,*__System.Net.IPNetwork.dll,*__SimpleBase.dll,*__Makaretu.*.dll' + useMinimatch: false + shouldSign: ${{ parameters.ShouldSign }} + alwaysCopy: 'true' + signingService: 'FactoryOrchestratorSigning' + verifySignature: 'true' + pageHash: 'false' + + # undo uniqify. The signed files are copied to where they were found in $(Build.ArtifactStagingDirectory). + - task: PowerShell@2 + inputs: + targetType: filePath + filePath: $(Build.SourcesDirectory)/build/internal/CopyUniqueBins.ps1 + arguments: '-CopySource "$(System.DefaultWorkingDirectory)/signeduniquefiles_stage2" -MappingFileIn "$(System.DefaultWorkingDirectory)/mappingfile.xml"' + failOnStderr: true + pwsh: true + displayName: 'Copy signed, unique files to UnsignedInput directory' + + - template: ./templates/template-zip-publish.yml + parameters: + BuildPlatform: 'x86' + - template: ./templates/template-zip-publish.yml + parameters: + BuildPlatform: 'x64' + - template: ./templates/template-zip-publish.yml + parameters: + BuildPlatform: 'arm' + - template: ./templates/template-zip-publish.yml + parameters: + BuildPlatform: 'arm64' + - template: ./templates/template-zip-publish.yml + parameters: + BuildPlatform: 'x64' + BuildOS: 'linux' + - template: ./templates/template-zip-publish.yml + parameters: + BuildPlatform: 'arm' + BuildOS: 'linux' + - template: ./templates/template-zip-publish.yml + parameters: + BuildPlatform: 'arm64' + BuildOS: 'linux' + + - publish: '$(Build.ArtifactStagingDirectory)/Zips' + artifact: 'Publish_AllPlatforms' + displayName: 'Publish app' \ No newline at end of file diff --git a/build/templates/template-dotnet-publish.yml b/build/templates/template-dotnet-publish.yml new file mode 100644 index 0000000..91ecce0 --- /dev/null +++ b/build/templates/template-dotnet-publish.yml @@ -0,0 +1,31 @@ +# publishes a variant of the Service +parameters: + BuildConfiguration: 'Release' + BuildPlatform: 'x64' + BuildOS: 'win' + +steps: +- task: DotNetCoreCLI@2 + inputs: + command: 'publish' + publishWebProjects: False + zipAfterPublish: false + arguments: '$(Build.SourcesDirectory)/src/FindDevice.csproj --nologo --self-contained --configuration ${{ parameters.BuildConfiguration }} -r ${{ parameters.BuildOS }}-${{ parameters.BuildPlatform }} --output $(Build.ArtifactStagingDirectory)/Publish/${{ parameters.BuildOS }}/FindDevice-${{ parameters.BuildOS }}-${{ parameters.BuildPlatform }}' + displayName: 'dotnet publish for ${{ parameters.BuildOS }}-${{ parameters.BuildPlatform }} runtime ${{ parameters.BuildConfiguration }}' +- task: CopyFiles@2 + displayName: 'Copy NOTICE to publish' + inputs: + SourceFolder: '$(Build.SourcesDirectory)' + Contents: 'NOTICE.txt' + TargetFolder: '$(Build.ArtifactStagingDirectory)/Publish/${{ parameters.BuildOS }}/FindDevice-${{ parameters.BuildOS }}-${{ parameters.BuildPlatform }}' +- task: CopyFiles@2 + displayName: 'Copy LICENSE to publish' + inputs: + SourceFolder: '$(Build.SourcesDirectory)' + Contents: 'LICENSE' + TargetFolder: '$(Build.ArtifactStagingDirectory)/Publish/${{ parameters.BuildOS }}/FindDevice-${{ parameters.BuildOS }}-${{ parameters.BuildPlatform }}' +- pwsh: | + $content = "FindDevice source code and documentation are all available on GitHub as MIT licensed open source!" + $content += "https://github.com/microsoft/FindDevice" + $content | out-file "$(Build.ArtifactStagingDirectory)/Publish/${{ parameters.BuildOS }}/FindDevice-${{ parameters.BuildOS }}-${{ parameters.BuildPlatform }}/README.txt" + displayName: 'Create README.txt' \ No newline at end of file diff --git a/build/templates/template-set-should-sign.yml b/build/templates/template-set-should-sign.yml new file mode 100644 index 0000000..1544f9a --- /dev/null +++ b/build/templates/template-set-should-sign.yml @@ -0,0 +1,14 @@ +steps: +- pwsh: | + if ($env:SKIPSIGN -eq 'false' -or (($null -ne $env:FORCESIGN) -and ($env:FORCESIGN -eq $true))) + { + $vstsCommandString = "vso[task.setvariable variable=SHOULDSIGN]true" + } + else + { + $vstsCommandString = "vso[task.setvariable variable=SHOULDSIGN]false" + } + Write-Host "sending " + $vstsCommandString + Write-Host "##$vstsCommandString" + displayName: 'Set SHOULDSIGN' + name: SetSHOULDSIGN diff --git a/build/templates/template-zip-publish.yml b/build/templates/template-zip-publish.yml new file mode 100644 index 0000000..5326387 --- /dev/null +++ b/build/templates/template-zip-publish.yml @@ -0,0 +1,14 @@ +# publishes a variant of the Service +parameters: + BuildConfiguration: 'Release' + BuildPlatform: 'x64' + BuildOS: 'win' + +steps: + - task: ArchiveFiles@2 + inputs: + rootFolderOrFile: '$(Build.ArtifactStagingDirectory)/Publish/${{ parameters.BuildOS }}/FindDevice-${{ parameters.BuildOS }}-${{ parameters.BuildPlatform }}' + includeRootFolder: false + archiveType: 'zip' + archiveFile: '$(Build.ArtifactStagingDirectory)/Zips/FindDevice-${{ parameters.BuildOS }}-${{ parameters.BuildPlatform }}.zip' + displayName: 'zip FindDevice-${{ parameters.BuildOS }}-${{ parameters.BuildPlatform }}' diff --git a/src/FindDevice.csproj b/src/FindDevice.csproj index 9bbb115..f32f24f 100644 --- a/src/FindDevice.csproj +++ b/src/FindDevice.csproj @@ -1,14 +1,26 @@  + 1.0.0 + Microsoft + Microsoft Corporation + © Microsoft Corporation. All rights reserved. + https://github.com/microsoft/factoryorchestrator Exe netcoreapp3.1 true + $(MSBuildThisFileDirectory)../bin/$(Configuration)/$(Platform)/$(TargetName) + + true + + true + true +