diff --git a/AzureKeyVault.LetsEncrypt/Internal/RetriableActivityException.cs b/AzureKeyVault.LetsEncrypt/Internal/RetriableActivityException.cs new file mode 100644 index 00000000..d977177f --- /dev/null +++ b/AzureKeyVault.LetsEncrypt/Internal/RetriableActivityException.cs @@ -0,0 +1,25 @@ +using System; +using System.Runtime.Serialization; + +namespace AzureKeyVault.LetsEncrypt.Internal +{ + [Serializable] + public class RetriableActivityException : Exception + { + public RetriableActivityException() + { + } + + public RetriableActivityException(string message) : base(message) + { + } + + public RetriableActivityException(string message, Exception inner) : base(message, inner) + { + } + + protected RetriableActivityException(SerializationInfo info, StreamingContext context) : base(info, context) + { + } + } +} diff --git a/AzureKeyVault.LetsEncrypt/SharedFunctions.cs b/AzureKeyVault.LetsEncrypt/SharedFunctions.cs index d92bb425..478b5363 100644 --- a/AzureKeyVault.LetsEncrypt/SharedFunctions.cs +++ b/AzureKeyVault.LetsEncrypt/SharedFunctions.cs @@ -54,7 +54,7 @@ public static async Task IssueCertificate([OrchestrationTrigger] DurableOrchestr var result = await context.CallActivityAsync(nameof(Dns01Authorization), authorization); // Azure DNS で正しくレコードが引けるか確認 - await context.CallActivityWithRetryAsync(nameof(CheckIsDnsRecord), new RetryOptions(TimeSpan.FromSeconds(10), 6), result); + await context.CallActivityWithRetryAsync(nameof(CheckDnsChallenge), new RetryOptions(TimeSpan.FromSeconds(10), 6), result); challenges.Add(result); } @@ -197,8 +197,8 @@ public static async Task Dns01Authorization([ActivityTrigger] D }; } - [FunctionName(nameof(CheckIsDnsRecord))] - public static async Task CheckIsDnsRecord([ActivityTrigger] DurableActivityContext context, ILogger log) + [FunctionName(nameof(CheckDnsChallenge))] + public static async Task CheckDnsChallenge([ActivityTrigger] DurableActivityContext context, ILogger log) { var challenge = context.GetInput(); @@ -212,27 +212,13 @@ public static async Task CheckIsDnsRecord([ActivityTrigger] DurableActivityConte // レコードが存在しなかった場合はエラー if (txtRecords.Length == 0) { - throw new InvalidOperationException($"{challenge.DnsRecordName} did not resolve."); + throw new RetriableActivityException($"{challenge.DnsRecordName} did not resolve."); } // レコードに今回のチャレンジが含まれていない場合もエラー if (!txtRecords.Any(x => x.Text.Contains(challenge.DnsRecordValue))) { - throw new InvalidOperationException($"{challenge.DnsRecordName} value is not correct."); - } - } - - [FunctionName(nameof(AnswerChallenges))] - public static async Task AnswerChallenges([ActivityTrigger] DurableActivityContext context, ILogger log) - { - var challenges = context.GetInput>(); - - var acme = await CreateAcmeClientAsync(); - - // Answer の準備が出来たことを通知 - foreach (var challenge in challenges) - { - await acme.AnswerChallengeAsync(challenge.Url); + throw new RetriableActivityException($"{challenge.DnsRecordName} value is not correct."); } } @@ -247,8 +233,8 @@ public static async Task CheckIsReady([ActivityTrigger] DurableActivityContext c if (orderDetails.Payload.Status == "pending") { - // pending の場合は何もしない - throw new InvalidOperationException("ACME domain validation is pending."); + // pending の場合はリトライする + throw new RetriableActivityException("ACME domain validation is pending."); } if (orderDetails.Payload.Status == "invalid") @@ -266,10 +252,25 @@ public static async Task CheckIsReady([ActivityTrigger] DurableActivityContext c } } + // invalid の場合は最初から実行が必要なので失敗させる throw new InvalidOperationException("Invalid order status. Required retry at first."); } } + [FunctionName(nameof(AnswerChallenges))] + public static async Task AnswerChallenges([ActivityTrigger] DurableActivityContext context, ILogger log) + { + var challenges = context.GetInput>(); + + var acme = await CreateAcmeClientAsync(); + + // Answer の準備が出来たことを通知 + foreach (var challenge in challenges) + { + await acme.AnswerChallengeAsync(challenge.Url); + } + } + [FunctionName(nameof(FinalizeOrder))] public static async Task FinalizeOrder([ActivityTrigger] DurableActivityContext context, ILogger log) {