From e1829a195ca760d16e62f67a86b6e601d92106d6 Mon Sep 17 00:00:00 2001 From: Tatsuro Shibamura Date: Sun, 11 Jun 2023 21:49:54 +0900 Subject: [PATCH 1/2] Improvement REST API response --- KeyVault.Acmebot/.gitignore | 7 ++++- KeyVault.Acmebot/Functions/GetCertificates.cs | 16 +++++------ KeyVault.Acmebot/Functions/GetDnsZones.cs | 16 +++++------ .../Functions/GetInstanceState.cs | 15 ++++------- .../Functions/PurgeInstanceHistory.cs | 4 ++- .../Functions/RenewCertificate.cs | 27 ++++++++++--------- .../Functions/RenewCertificates.cs | 22 ++++++++------- .../Functions/RevokeCertificate.cs | 20 +++++++------- .../Functions/SharedOrchestrator.cs | 4 ++- .../Internal/CertificateExtensions.cs | 1 + KeyVault.Acmebot/KeyVault.Acmebot.csproj | 2 +- KeyVault.Acmebot/Models/CertificateItem.cs | 5 +++- KeyVault.Acmebot/host.json | 4 --- 13 files changed, 75 insertions(+), 68 deletions(-) diff --git a/KeyVault.Acmebot/.gitignore b/KeyVault.Acmebot/.gitignore index ff5b00c5..72423fc0 100644 --- a/KeyVault.Acmebot/.gitignore +++ b/KeyVault.Acmebot/.gitignore @@ -261,4 +261,9 @@ paket-files/ # Python Tools for Visual Studio (PTVS) __pycache__/ -*.pyc \ No newline at end of file +*.pyc + +# Service dependencies +Properties/serviceDependencies.json +Properties/serviceDependencies.*.json +Properties/ServiceDependencies/ diff --git a/KeyVault.Acmebot/Functions/GetCertificates.cs b/KeyVault.Acmebot/Functions/GetCertificates.cs index 8af79f78..b938950e 100644 --- a/KeyVault.Acmebot/Functions/GetCertificates.cs +++ b/KeyVault.Acmebot/Functions/GetCertificates.cs @@ -24,14 +24,6 @@ public GetCertificates(IHttpContextAccessor httpContextAccessor) { } - [FunctionName($"{nameof(GetCertificates)}_{nameof(Orchestrator)}")] - public Task> Orchestrator([OrchestrationTrigger] IDurableOrchestrationContext context) - { - var activity = context.CreateActivityProxy(); - - return activity.GetAllCertificates(); - } - [FunctionName($"{nameof(GetCertificates)}_{nameof(HttpStart)}")] public async Task HttpStart( [HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = "api/certificates")] HttpRequest req, @@ -50,4 +42,12 @@ public async Task HttpStart( return await starter.WaitForCompletionOrCreateCheckStatusResponseAsync(req, instanceId, TimeSpan.FromMinutes(1), returnInternalServerErrorOnFailure: true); } + + [FunctionName($"{nameof(GetCertificates)}_{nameof(Orchestrator)}")] + public Task> Orchestrator([OrchestrationTrigger] IDurableOrchestrationContext context) + { + var activity = context.CreateActivityProxy(); + + return activity.GetAllCertificates(); + } } diff --git a/KeyVault.Acmebot/Functions/GetDnsZones.cs b/KeyVault.Acmebot/Functions/GetDnsZones.cs index bc22512a..a629914d 100644 --- a/KeyVault.Acmebot/Functions/GetDnsZones.cs +++ b/KeyVault.Acmebot/Functions/GetDnsZones.cs @@ -22,14 +22,6 @@ public GetDnsZones(IHttpContextAccessor httpContextAccessor) { } - [FunctionName($"{nameof(GetDnsZones)}_{nameof(Orchestrator)}")] - public Task> Orchestrator([OrchestrationTrigger] IDurableOrchestrationContext context) - { - var activity = context.CreateActivityProxy(); - - return activity.GetZones(); - } - [FunctionName($"{nameof(GetDnsZones)}_{nameof(HttpStart)}")] public async Task HttpStart( [HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = "api/dns-zones")] HttpRequest req, @@ -48,4 +40,12 @@ public async Task HttpStart( return await starter.WaitForCompletionOrCreateCheckStatusResponseAsync(req, instanceId, TimeSpan.FromMinutes(1), returnInternalServerErrorOnFailure: true); } + + [FunctionName($"{nameof(GetDnsZones)}_{nameof(Orchestrator)}")] + public Task> Orchestrator([OrchestrationTrigger] IDurableOrchestrationContext context) + { + var activity = context.CreateActivityProxy(); + + return activity.GetZones(); + } } diff --git a/KeyVault.Acmebot/Functions/GetInstanceState.cs b/KeyVault.Acmebot/Functions/GetInstanceState.cs index 21405d40..286a7d0f 100644 --- a/KeyVault.Acmebot/Functions/GetInstanceState.cs +++ b/KeyVault.Acmebot/Functions/GetInstanceState.cs @@ -35,16 +35,11 @@ public async Task HttpStart( return BadRequest(); } - if (status.RuntimeStatus == OrchestrationRuntimeStatus.Failed) + return status.RuntimeStatus switch { - return Problem(status.Output.ToString()); - } - - if (status.RuntimeStatus is OrchestrationRuntimeStatus.Running or OrchestrationRuntimeStatus.Pending or OrchestrationRuntimeStatus.ContinuedAsNew) - { - return AcceptedAtFunction($"{nameof(GetInstanceState)}_{nameof(HttpStart)}", new { instanceId }, null); - } - - return Ok(); + OrchestrationRuntimeStatus.Completed => Ok(status.Output), + OrchestrationRuntimeStatus.Failed or OrchestrationRuntimeStatus.Canceled or OrchestrationRuntimeStatus.Terminated => Problem(status.Output.ToString()), + _ => AcceptedAtFunction($"{nameof(GetInstanceState)}_{nameof(HttpStart)}", new { instanceId }, null), + }; } } diff --git a/KeyVault.Acmebot/Functions/PurgeInstanceHistory.cs b/KeyVault.Acmebot/Functions/PurgeInstanceHistory.cs index 355bd042..f186c70b 100644 --- a/KeyVault.Acmebot/Functions/PurgeInstanceHistory.cs +++ b/KeyVault.Acmebot/Functions/PurgeInstanceHistory.cs @@ -19,7 +19,9 @@ public Task Timer([TimerTrigger("0 0 0 1 * *")] TimerInfo timer, [DurableClient] new[] { OrchestrationStatus.Completed, - OrchestrationStatus.Failed + OrchestrationStatus.Failed, + OrchestrationStatus.Canceled, + OrchestrationStatus.Terminated }); } } diff --git a/KeyVault.Acmebot/Functions/RenewCertificate.cs b/KeyVault.Acmebot/Functions/RenewCertificate.cs index 8d37d5a9..01798e86 100644 --- a/KeyVault.Acmebot/Functions/RenewCertificate.cs +++ b/KeyVault.Acmebot/Functions/RenewCertificate.cs @@ -5,6 +5,7 @@ using DurableTask.TypedProxy; using KeyVault.Acmebot.Internal; +using KeyVault.Acmebot.Models; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; @@ -22,19 +23,6 @@ public RenewCertificate(IHttpContextAccessor httpContextAccessor) { } - [FunctionName($"{nameof(RenewCertificate)}_{nameof(Orchestrator)}")] - public async Task Orchestrator([OrchestrationTrigger] IDurableOrchestrationContext context, ILogger log) - { - var certificateName = context.GetInput(); - - var activity = context.CreateActivityProxy(); - - // 証明書の更新処理を開始 - var certificatePolicyItem = await activity.GetCertificatePolicy(certificateName); - - await context.CallSubOrchestratorAsync(nameof(SharedOrchestrator.IssueCertificate), certificatePolicyItem); - } - [FunctionName($"{nameof(RenewCertificate)}_{nameof(HttpStart)}")] public async Task HttpStart( [HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = "api/certificate/{certificateName}/renew")] HttpRequest req, @@ -59,4 +47,17 @@ public async Task HttpStart( return AcceptedAtFunction($"{nameof(GetInstanceState)}_{nameof(GetInstanceState.HttpStart)}", new { instanceId }, null); } + + [FunctionName($"{nameof(RenewCertificate)}_{nameof(Orchestrator)}")] + public async Task Orchestrator([OrchestrationTrigger] IDurableOrchestrationContext context, ILogger log) + { + var certificateName = context.GetInput(); + + var activity = context.CreateActivityProxy(); + + // 証明書の更新処理を開始 + var certificatePolicyItem = await activity.GetCertificatePolicy(certificateName); + + return await context.CallSubOrchestratorAsync(nameof(SharedOrchestrator.IssueCertificate), certificatePolicyItem); + } } diff --git a/KeyVault.Acmebot/Functions/RenewCertificates.cs b/KeyVault.Acmebot/Functions/RenewCertificates.cs index 1f015703..91ccab83 100644 --- a/KeyVault.Acmebot/Functions/RenewCertificates.cs +++ b/KeyVault.Acmebot/Functions/RenewCertificates.cs @@ -4,6 +4,8 @@ using DurableTask.TypedProxy; +using KeyVault.Acmebot.Models; + using Microsoft.Azure.WebJobs; using Microsoft.Azure.WebJobs.Extensions.DurableTask; using Microsoft.Extensions.Logging; @@ -12,6 +14,15 @@ namespace KeyVault.Acmebot.Functions; public class RenewCertificates { + [FunctionName($"{nameof(RenewCertificates)}_{nameof(Timer)}")] + public async Task Timer([TimerTrigger("0 0 0 * * *")] TimerInfo timer, [DurableClient] IDurableClient starter, ILogger log) + { + // Function input comes from the request content. + var instanceId = await starter.StartNewAsync($"{nameof(RenewCertificates)}_{nameof(Orchestrator)}"); + + log.LogInformation($"Started orchestration with ID = '{instanceId}'."); + } + [FunctionName($"{nameof(RenewCertificates)}_{nameof(Orchestrator)}")] public async Task Orchestrator([OrchestrationTrigger] IDurableOrchestrationContext context, ILogger log) { @@ -43,7 +54,7 @@ public async Task Orchestrator([OrchestrationTrigger] IDurableOrchestrationConte // 証明書の更新処理を開始 var certificatePolicyItem = await activity.GetCertificatePolicy(certificate.Name); - await context.CallSubOrchestratorWithRetryAsync(nameof(SharedOrchestrator.IssueCertificate), _retryOptions, certificatePolicyItem); + await context.CallSubOrchestratorWithRetryAsync(nameof(SharedOrchestrator.IssueCertificate), _retryOptions, certificatePolicyItem); } catch (Exception ex) { @@ -54,15 +65,6 @@ public async Task Orchestrator([OrchestrationTrigger] IDurableOrchestrationConte } } - [FunctionName($"{nameof(RenewCertificates)}_{nameof(Timer)}")] - public async Task Timer([TimerTrigger("0 0 0 * * *")] TimerInfo timer, [DurableClient] IDurableClient starter, ILogger log) - { - // Function input comes from the request content. - var instanceId = await starter.StartNewAsync($"{nameof(RenewCertificates)}_{nameof(Orchestrator)}"); - - log.LogInformation($"Started orchestration with ID = '{instanceId}'."); - } - private readonly RetryOptions _retryOptions = new(TimeSpan.FromHours(3), 2) { Handle = ex => ex.InnerException?.InnerException is RetriableOrchestratorException diff --git a/KeyVault.Acmebot/Functions/RevokeCertificate.cs b/KeyVault.Acmebot/Functions/RevokeCertificate.cs index bdcab248..e3baa765 100644 --- a/KeyVault.Acmebot/Functions/RevokeCertificate.cs +++ b/KeyVault.Acmebot/Functions/RevokeCertificate.cs @@ -23,16 +23,6 @@ public RevokeCertificate(IHttpContextAccessor httpContextAccessor) { } - [FunctionName($"{nameof(RevokeCertificate)}_{nameof(Orchestrator)}")] - public async Task Orchestrator([OrchestrationTrigger] IDurableOrchestrationContext context, ILogger log) - { - var certificateName = context.GetInput(); - - var activity = context.CreateActivityProxy(); - - await activity.RevokeCertificate(certificateName); - } - [FunctionName($"{nameof(RevokeCertificate)}_{nameof(HttpStart)}")] public async Task HttpStart( [HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = "api/certificate/{certificateName}/revoke")] HttpRequest req, @@ -57,4 +47,14 @@ public async Task HttpStart( return await starter.WaitForCompletionOrCreateCheckStatusResponseAsync(req, instanceId, TimeSpan.FromMinutes(1), returnInternalServerErrorOnFailure: true); } + + [FunctionName($"{nameof(RevokeCertificate)}_{nameof(Orchestrator)}")] + public async Task Orchestrator([OrchestrationTrigger] IDurableOrchestrationContext context, ILogger log) + { + var certificateName = context.GetInput(); + + var activity = context.CreateActivityProxy(); + + await activity.RevokeCertificate(certificateName); + } } diff --git a/KeyVault.Acmebot/Functions/SharedOrchestrator.cs b/KeyVault.Acmebot/Functions/SharedOrchestrator.cs index f915a757..321eed5c 100644 --- a/KeyVault.Acmebot/Functions/SharedOrchestrator.cs +++ b/KeyVault.Acmebot/Functions/SharedOrchestrator.cs @@ -13,7 +13,7 @@ namespace KeyVault.Acmebot.Functions; public class SharedOrchestrator { [FunctionName(nameof(IssueCertificate))] - public async Task IssueCertificate([OrchestrationTrigger] IDurableOrchestrationContext context) + public async Task IssueCertificate([OrchestrationTrigger] IDurableOrchestrationContext context) { var certificatePolicy = context.GetInput(); @@ -62,5 +62,7 @@ public async Task IssueCertificate([OrchestrationTrigger] IDurableOrchestrationC // 証明書の更新が完了後に Webhook を送信する await activity.SendCompletedEvent((certificate.Name, certificate.ExpiresOn, certificatePolicy.DnsNames)); + + return certificate; } } diff --git a/KeyVault.Acmebot/Internal/CertificateExtensions.cs b/KeyVault.Acmebot/Internal/CertificateExtensions.cs index ce03e88d..03f32ff1 100644 --- a/KeyVault.Acmebot/Internal/CertificateExtensions.cs +++ b/KeyVault.Acmebot/Internal/CertificateExtensions.cs @@ -39,6 +39,7 @@ public static CertificateItem ToCertificateItem(this KeyVaultCertificateWithPoli return new CertificateItem { Id = certificate.Id, + SecretId = certificate.SecretId, Name = certificate.Name, DnsNames = dnsNames is { Length: > 0 } ? dnsNames : new[] { certificate.Policy.Subject[3..] }, CreatedOn = certificate.Properties.CreatedOn.Value, diff --git a/KeyVault.Acmebot/KeyVault.Acmebot.csproj b/KeyVault.Acmebot/KeyVault.Acmebot.csproj index 95ab3374..03fb3e2d 100644 --- a/KeyVault.Acmebot/KeyVault.Acmebot.csproj +++ b/KeyVault.Acmebot/KeyVault.Acmebot.csproj @@ -4,7 +4,7 @@ v4 - + diff --git a/KeyVault.Acmebot/Models/CertificateItem.cs b/KeyVault.Acmebot/Models/CertificateItem.cs index 98d6ab10..a24a1b8f 100644 --- a/KeyVault.Acmebot/Models/CertificateItem.cs +++ b/KeyVault.Acmebot/Models/CertificateItem.cs @@ -10,6 +10,9 @@ public class CertificateItem [JsonProperty("id")] public Uri Id { get; set; } + [JsonProperty("secretId")] + public Uri SecretId { get; set; } + [JsonProperty("name")] public string Name { get; set; } @@ -38,7 +41,7 @@ public class CertificateItem public bool? ReuseKey { get; set; } [JsonProperty("isManaged")] - public bool IsManaged { get; set; } + public bool IsManaged { get; set; } = true; [JsonProperty("isExpired")] public bool IsExpired { get; set; } diff --git a/KeyVault.Acmebot/host.json b/KeyVault.Acmebot/host.json index c811cde0..1d509164 100644 --- a/KeyVault.Acmebot/host.json +++ b/KeyVault.Acmebot/host.json @@ -12,10 +12,6 @@ } }, "extensions": { - "durableTask": { - "extendedSessionsEnabled": true, - "extendedSessionIdleTimeoutInSeconds": 120 - }, "http": { "routePrefix": "", "customHeaders": { From bce03b817d09bb5a152fd49a703cf16801af9334 Mon Sep 17 00:00:00 2001 From: Tatsuro Shibamura Date: Mon, 31 Jul 2023 17:13:54 +0900 Subject: [PATCH 2/2] Update nuget package --- KeyVault.Acmebot/KeyVault.Acmebot.csproj | 6 +++--- KeyVault.Acmebot/host.json | 7 ++++--- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/KeyVault.Acmebot/KeyVault.Acmebot.csproj b/KeyVault.Acmebot/KeyVault.Acmebot.csproj index 0b2ea938..ca2421a8 100644 --- a/KeyVault.Acmebot/KeyVault.Acmebot.csproj +++ b/KeyVault.Acmebot/KeyVault.Acmebot.csproj @@ -4,7 +4,7 @@ v4 - + @@ -12,9 +12,9 @@ - + - + diff --git a/KeyVault.Acmebot/host.json b/KeyVault.Acmebot/host.json index ebb4995b..6c5661e8 100644 --- a/KeyVault.Acmebot/host.json +++ b/KeyVault.Acmebot/host.json @@ -3,8 +3,8 @@ "logging": { "applicationInsights": { "samplingSettings": { - "excludedTypes": "Request;Exception", - "isEnabled": true + "isEnabled": true, + "excludedTypes": "Request;Exception" } }, "logLevel": { @@ -13,7 +13,8 @@ }, "extensions": { "durableTask": { - "useGracefulShutdown": true + "useGracefulShutdown": true, + "useTablePartitionManagement": true }, "http": { "routePrefix": "",