Решение проблемы - переопределить встроенную задачу SignFile. Интересно, что задача SignFile использует встроенную функцию в Microsoft.Build.Tasks.Deployment.ManifestUtilities.SecurityUtilities.SignFile
, которая имеет две перегрузки, одна с отпечатком большого пальца, а другая с файлом и паролем.
Решение состоит в том, чтобы создать новую задачу, которая может ссылаться на другую перегрузку. Поскольку мы не можем изменить вызывающий SignFile, нам нужно поддерживать ту же сигнатуру и помещать соответствующие переменные в переменные окружения. В этом случае «CertificateFile» и «CertificatePassword».
Затем обратитесь к этим двум в перезаписанном SignFile. Я создал новый целевой файл (filesign.targets) и поместил туда код. Проверял это в моем репозитории и ссылался на него из основного файла (ов) проекта.
<Import Project="filesign.targets" />
Таким образом, мы также можем хранить наши файлы ключей в хранилище ключей Azure, загружать их при сборке и давать им уникальный пароль только для этой сборки.
Файл целей содержит новую задачу FileSign:
<?xml version="1.0" encoding="Windows-1252"?>
<!--
***********************************************************************************************
Microsoft.VisualStudio.Tools.Office.targets
WARNING: DO NOT MODIFY this file unless you are knowledgeable about MSBuild and have
created a backup copy. Incorrect changes to this file will make it
impossible to load or build your projects from the command-line or the IDE.
This file defines the steps in the standard build process specific for Visual Studio Tools for
Office projects.
Copyright (C) Microsoft Corporation. All rights reserved.
***********************************************************************************************
-->
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<UsingTask TaskName="SignFile" TaskFactory="CodeTaskFactory" AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.Core.dll">
<ParameterGroup>
<SigningTarget Required="true" ParameterType="Microsoft.Build.Framework.ITaskItem" />
<CertificateThumbprint ParameterType="System.String" />
<TargetFrameworkVersion ParameterType="System.String" />
<TimestampUrl ParameterType="System.String" />
<CertificateFile ParameterType="System.String" />
<CertificatePassword ParameterType="System.String" />
</ParameterGroup>
<Task>
<Reference Include="mscorlib" />
<Reference Include="Microsoft.Build.Tasks.Core" />
<Using Namespace="System" />
<Code Type="Fragment" Language="cs">
<![CDATA[
var EnvCertFile = System.Environment.GetEnvironmentVariable("CertificateFile");
Log.LogMessage("CertFile:!!" + EnvCertFile);
if (string.IsNullOrWhiteSpace(CertificateFile) && string.IsNullOrWhiteSpace(EnvCertFile)) {
var signFile = new Microsoft.Build.Tasks.SignFile();
signFile.CertificateThumbprint = CertificateThumbprint;
signFile.SigningTarget = SigningTarget;
signFile.TargetFrameworkVersion = TargetFrameworkVersion;
signFile.TimestampUrl = TimestampUrl;
return signFile.Execute();
} else {
var certificate = string.IsNullOrWhiteSpace(CertificateFile) ? EnvCertFile : CertificateFile;
var EnvCertPassword = System.Environment.GetEnvironmentVariable("CertificatePassword");
var certificatePassword = string.IsNullOrWhiteSpace(CertificatePassword) ? EnvCertPassword : CertificatePassword;
var testString = new System.Security.SecureString();
// Use the AppendChar method to add each char value to the secure string.
if (!string.IsNullOrWhiteSpace(certificatePassword))
foreach (char ch in certificatePassword)
testString.AppendChar(ch);
Microsoft.Build.Tasks.Deployment.ManifestUtilities.SecurityUtilities.SignFile(certificate, testString,
TimestampUrl == null ? null : new Uri(TimestampUrl),
SigningTarget.ItemSpec);
return true;
}
]]>
</Code>
</Task>
</UsingTask>
</Project>
Код основан на:
https://gist.github.com/KirillOsenkov/4cd32c40bffd3045f77e
Ссылка:
https://github.com/Microsoft/msbuild/blob/fc10ea8ce260b764bb9fa5033b327af9fefcaabe/src/Tasks/ManifestUtil/SecurityUtil.cs
https://github.com/Microsoft/msbuild/blob/master/src/Tasks/SignFile.cs