diff --git a/src/AzureSignTool/AzureSignTool.csproj b/src/AzureSignTool/AzureSignTool.csproj
index a90c5f2..1746740 100644
--- a/src/AzureSignTool/AzureSignTool.csproj
+++ b/src/AzureSignTool/AzureSignTool.csproj
@@ -22,6 +22,7 @@
all
+
diff --git a/src/AzureSignTool/HRESULT.cs b/src/AzureSignTool/HRESULT.cs
index 3f2adb3..0aae757 100644
--- a/src/AzureSignTool/HRESULT.cs
+++ b/src/AzureSignTool/HRESULT.cs
@@ -12,5 +12,7 @@ internal static class HRESULT
public const int E_ALL_FAILED = unchecked((int)0xA0000002);
public const int TRUST_E_SUBJECT_FORM_UNKNOWN = unchecked((int)0x800B0003);
+
+ public const int E_VAULT_THROTTLING = unchecked((int)0x801901AD);
}
}
diff --git a/src/AzureSignTool/SignCommand.cs b/src/AzureSignTool/SignCommand.cs
index 07175b8..365428a 100644
--- a/src/AzureSignTool/SignCommand.cs
+++ b/src/AzureSignTool/SignCommand.cs
@@ -3,6 +3,8 @@
using McMaster.Extensions.CommandLineUtils.Abstractions;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Console;
+using Polly.Retry;
+using Polly;
using RSAKeyVaultProvider;
using System;
@@ -104,6 +106,18 @@ internal sealed class SignCommand
[Argument(0, "file", "The path to the file.")]
public string[] Files { get; set; } = [];
+ // retry strategy for Keyvault throttling errors
+ // https://learn.microsoft.com/en-us/azure/key-vault/general/overview-throttling
+ private readonly ResiliencePipeline _resiliencePipeline = new ResiliencePipelineBuilder()
+ .AddRetry(new RetryStrategyOptions
+ {
+ ShouldHandle = new PredicateBuilder().HandleResult(result => (int)result == E_VAULT_THROTTLING),
+ BackoffType = DelayBackoffType.Exponential,
+ MaxRetryAttempts = 4,
+ Delay = TimeSpan.FromSeconds(2)
+ })
+ .Build();
+
private HashSet _allFiles;
public HashSet AllFiles
{
@@ -321,9 +335,10 @@ public async Task OnExecuteAsync(IConsole console)
{
logger.LogInformation("Skipping already signed file.");
return (state.succeeded + 1, state.failed);
- }
+ }
+
+ var result = _resiliencePipeline.Execute(() => signer.SignFile(filePath, Description, DescriptionUri, performPageHashing, logger, appendSignature));
- var result = signer.SignFile(filePath, Description, DescriptionUri, performPageHashing, logger, appendSignature);
switch (result)
{
case COR_E_BADIMAGEFORMAT: