dotnet / sign

Code Signing CLI tool supporting Authenticode, NuGet, VSIX, and ClickOnce
MIT License
439 stars 84 forks source link

Signing failed with error -2147012744. #709

Open janstaelensskyline opened 2 weeks ago

janstaelensskyline commented 2 weeks ago

Describe the Bug

Environments:

When executing dotnet sign on a .nupkg file using Azure Key Vault, we encounter the following error:

Signing failed with error -2147012744.

Interestingly, this issue does not occur when running the code from an Azure Pipeline on a provided Windows machine. It suggests we might be missing a prerequisite on our personal computers. It does happen on our Jenkins setup running on the above specified windows 2019 server.

After some investigation, it appears the error originates from deep within the code, specifically from calls to the Windows OS to sign the assemblies inside the .nupkg.

// Example of the error code
logger?.LogTrace("Calling SignerSignEx3");
var result = mssign32.SignerSignEx3;

// Signing code snippet
try
{
    using (var ctx = new Kernel32.ActivationContext(manifestFile))
    {
        code = signer.SignFile(
            file.FullName,
            options.Description,
            options.DescriptionUrl?.AbsoluteUri,
            pageHashing: null,
            _logger);
        success = code == S_OK;
    }
}
catch (Exception e)
{
    _logger.LogError(e, e.Message);
}

if (success)
{
    _logger.LogInformation(Resources.SigningSucceeded, file.FullName);
    return true;
}

_logger.LogError(Resources.SigningFailedWithError, code);

The problem is that I'm not familiar enough with the SignerSignEx3 WinAPI call and it seems like documentation will be private to Microsoft. At this point, it's likely that I've gone too deep and am missing a more obvious issue.

Repro Steps

  1. Create a .nupkg that includes .net462 assemblies.
  2. Execute the following C# code (assuming dotnet is a class that starts dotnet.exe as a process with the provided string as an argument):
dotnet.Run("new tool-manifest");
dotnet.Run("tool install sign --version 0.9.1-beta.24312.3");

string command = $"sign code azure-key-vault \"{packageAbsolutePath}\" " +
"--publisher-name \"Fake Company\" " +
"--description \"Fake Signing\" " +
"--description-url \"https://www.fakecompany.be/\" " +
"--azure-key-vault-tenant-id \"123-fake-id\" " +
"--azure-key-vault-client-id \"123-fake-id\" " +
$"--azure-key-vault-client-secret \"{nugetStore.NuGetCertificatePassword}\" " +
"--azure-key-vault-certificate \"CompanyDefault\" " +
"--azure-key-vault-url \"https://common-certificates.vault.azure.net/\" " +
$"--output \"{resultDirectory}\"";

dotnet.Run(command);

Expected Behavior

Expecting to see a signed .nupkg with all content signed.

Actual Behavior

Signing starts, then it retries over and over again until it throws an exception.

Standard Output:

Tool 'sign' is up to date (version '0.9.1-beta.24312.3' manifest file C:\GIT\Solutions\Internal\CICD\SysDev\NuGetSigningIntegrationTests\bin\Debug\.config\dotnet-tools.json).
fail: Sign.Core.ISignatureProvider[0]
      Signing failed with error -2147012744.
      (repeats multiple times)
fail: Sign.Core.ISignatureProvider[0]
      Failed to sign. Attempts exceeded.
fail: Sign.Core.ISigner[0]
      Could not sign C:\Users\JANS\AppData\Local\Temp\dno54dl1.xna\lib\Newtonsoft.Json.dll.
      System.Exception: Could not sign C:\Users\JANS\AppData\Local\Temp\dno54dl1.xna\lib\Newtonsoft.Json.dll.
         at Sign.Core.AzureSignToolSignatureProvider.<>c__DisplayClass7_0.<<SignAsync>b__0>d.MoveNext() in /_/src/Sign.Core/SignatureProviders/AzureSignToolSignatureProvider.cs:line 110
      --- End of stack trace from previous location ---
         at System.Threading.Tasks.Parallel.<>c__53`1.<<ForEachAsync>b__53_0>d.MoveNext()
      --- End of stack trace from previous location ---
         at Sign.Core.AzureSignToolSignatureProvider.SignAsync(IEnumerable`1 files, SignOptions options) in /_/src/Sign.Core/SignatureProviders/AzureSignToolSignatureProvider.cs:line 104
         at Sign.Core.AggregatingSignatureProvider.SignAsync(IEnumerable`1 files, SignOptions options) in /_/src/Sign.Core/SignatureProviders/AggregatingSignatureProvider.cs:line 204
         at Sign.Core.AggregatingSignatureProvider.SignAsync(IEnumerable`1 files, SignOptions options) in /_/src/Sign.Core/SignatureProviders/AggregatingSignatureProvider.cs:line 92
         at Sign.Core.Signer.<>c__DisplayClass3_0.<<SignAsync>b__0>d.MoveNext() in /_/src/Sign.Core/Signer.cs:line 156
      --- End of stack trace from previous location ---
         at System.Threading.Tasks.Parallel.<>c__53`1.<<ForEachAsync>b__53_0>d.MoveNext()
      --- End of stack trace from previous location ---
         at Sign.Core.Signer.SignAsync(IReadOnlyList`1 inputFiles, String outputFile, FileInfo fileList, DirectoryInfo baseDirectory, String applicationName, String publisherName, String description, Uri descriptionUrl, Uri timestampUrl, Int32 maxConcurrency, HashAlgorithmName fileHashAlgorithm, HashAlgorithmName timestampHashAlgorithm) in /_/src/Sign.Core/Signer.cs:line 85

Additional Context

.NET SDKs Installed

.NET Runtimes Installed

Other Architectures Found

Environment Variables

global.json File

Learn More

Download .NET

clairernovotny commented 2 weeks ago

Hi @janstaelensskyline unfortunately, those versions of Windows are both out of the mainstream support lifecycle, so there's not a lot we can do for those.

That said Sign CLI carries its own copies of the Authenticode signing libraries and that activation context should be forcing the tool to use those versions instead of the ones the OS carries. @dtivel, looks like there may be an issue here? Can we confirm that the correct libraries are being loaded and used at runtime?

janstaelensskyline commented 1 week ago

Hello @clairernovotny , understood. Do you have a list with the mainstream support for what version of windows OS is supported and part of your QA cycle for the signing of .nupkg?

janstaelensskyline commented 1 week ago

Update on this issue. I've continued debugging this on my end. It's been strange... I tested running the AzureSign Tool on an assembly and the KeyVaultSign tool on a .nupkg directly with our same azure keyvault settings and both those tools worked on every PC and Server. Only the sign tool itself kept failing.

Up to an including 19/06/2024

Using the exact same sign command as mentioned in the first post, version of the tool and the same .nupkg package. All the servers & pc's have .NET8 installed.

On azure pipelines using windows host: WORKS On Github pipelines using windows host: WORKS

On 2 Pc's with Windows 10: FAILS WITH ERROR -2147012744

On 1 PC with Windows 11: FAILS WITH ERROR -2147012744

On Windows Server 2019: FAILS WITH ERROR -2147012744

On Windows Server 2022: FAILS WITH ERROR -2146762749

Today on 20/06/2024

the command suddenly started working on 2 PC's with Windows 10: 1 PC with Windows 11:

Both the servers are still failing (2019 and 2022) but with different error codes.

what changed

I spend a while checking to see what 'changed' on the PC's that didn't on the servers but I'm not finding much. I saw a windows update for microsoft defender: KB2267602. But when I installed that on the server nothing changed. There was no reboot or restart for one of the win10 pc's for over 7 days so I'm not immediately seeing other windows updates being a factor there.

On applications I didn't see any updates that every PC had and that the servers might've been missing.

current status

Currently I'm not able to really figure this out. I'll setup our self-hosted jenkins pipelines to use the NuGetKeyVault tool directly for now, but we'd prefer to use the same dotnet sign tool on all our CI/CD.