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: