diff --git a/Directory.Packages.props b/Directory.Packages.props
index 98fd046..e9b983e 100644
--- a/Directory.Packages.props
+++ b/Directory.Packages.props
@@ -7,6 +7,7 @@
+
diff --git a/src/AzureSignTool/AzureSignTool.csproj b/src/AzureSignTool/AzureSignTool.csproj
index d4c3bcd..13c0e31 100644
--- a/src/AzureSignTool/AzureSignTool.csproj
+++ b/src/AzureSignTool/AzureSignTool.csproj
@@ -20,6 +20,7 @@
+
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/Program.cs b/src/AzureSignTool/Program.cs
index d492568..fb4ab0e 100644
--- a/src/AzureSignTool/Program.cs
+++ b/src/AzureSignTool/Program.cs
@@ -14,6 +14,8 @@
using Microsoft.Extensions.FileSystemGlobbing.Abstractions;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Console;
+using Polly.Retry;
+using Polly;
using XenoAtom.CommandLine;
using static AzureSignTool.HRESULT;
@@ -176,6 +178,18 @@ public SignCommand() : base("sign", "Sign a file.", null)
Action = Run;
}
+ // 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 ValueTask Run(CommandRunContext context, string[] arguments)
{
if (ValidateArguments(context))
@@ -320,7 +334,7 @@ private async ValueTask RunSign()
return (state.succeeded + 1, state.failed);
}
- var result = signer.SignFile(filePath, SignDescription, SignDescriptionUrl, performPageHashing, logger, appendSignature);
+ var result = _resiliencePipeline.Execute(() => signer.SignFile(filePath, SignDescription, SignDescriptionUrl, performPageHashing, logger, appendSignature));
switch (result)
{
case COR_E_BADIMAGEFORMAT: