Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for Standalone mode #600

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion KeyVault.Acmebot/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -261,4 +261,9 @@ paket-files/

# Python Tools for Visual Studio (PTVS)
__pycache__/
*.pyc
*.pyc

# Service dependencies
Properties/serviceDependencies.json
Properties/serviceDependencies.*.json
Properties/ServiceDependencies/
16 changes: 8 additions & 8 deletions KeyVault.Acmebot/Functions/GetCertificates.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,6 @@ public GetCertificates(IHttpContextAccessor httpContextAccessor)
{
}

[FunctionName($"{nameof(GetCertificates)}_{nameof(Orchestrator)}")]
public Task<IReadOnlyList<CertificateItem>> Orchestrator([OrchestrationTrigger] IDurableOrchestrationContext context)
{
var activity = context.CreateActivityProxy<ISharedActivity>();

return activity.GetAllCertificates();
}

[FunctionName($"{nameof(GetCertificates)}_{nameof(HttpStart)}")]
public async Task<IActionResult> HttpStart(
[HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = "api/certificates")] HttpRequest req,
Expand All @@ -50,4 +42,12 @@ public async Task<IActionResult> HttpStart(

return await starter.WaitForCompletionOrCreateCheckStatusResponseAsync(req, instanceId, TimeSpan.FromMinutes(1), returnInternalServerErrorOnFailure: true);
}

[FunctionName($"{nameof(GetCertificates)}_{nameof(Orchestrator)}")]
public Task<IReadOnlyList<CertificateItem>> Orchestrator([OrchestrationTrigger] IDurableOrchestrationContext context)
{
var activity = context.CreateActivityProxy<ISharedActivity>();

return activity.GetAllCertificates();
}
}
16 changes: 8 additions & 8 deletions KeyVault.Acmebot/Functions/GetDnsZones.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,6 @@ public GetDnsZones(IHttpContextAccessor httpContextAccessor)
{
}

[FunctionName($"{nameof(GetDnsZones)}_{nameof(Orchestrator)}")]
public Task<IReadOnlyList<string>> Orchestrator([OrchestrationTrigger] IDurableOrchestrationContext context)
{
var activity = context.CreateActivityProxy<ISharedActivity>();

return activity.GetZones();
}

[FunctionName($"{nameof(GetDnsZones)}_{nameof(HttpStart)}")]
public async Task<IActionResult> HttpStart(
[HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = "api/dns-zones")] HttpRequest req,
Expand All @@ -48,4 +40,12 @@ public async Task<IActionResult> HttpStart(

return await starter.WaitForCompletionOrCreateCheckStatusResponseAsync(req, instanceId, TimeSpan.FromMinutes(1), returnInternalServerErrorOnFailure: true);
}

[FunctionName($"{nameof(GetDnsZones)}_{nameof(Orchestrator)}")]
public Task<IReadOnlyList<string>> Orchestrator([OrchestrationTrigger] IDurableOrchestrationContext context)
{
var activity = context.CreateActivityProxy<ISharedActivity>();

return activity.GetZones();
}
}
15 changes: 5 additions & 10 deletions KeyVault.Acmebot/Functions/GetInstanceState.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,16 +35,11 @@ public async Task<IActionResult> 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),
};
}
}
4 changes: 3 additions & 1 deletion KeyVault.Acmebot/Functions/PurgeInstanceHistory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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
});
}
}
27 changes: 14 additions & 13 deletions KeyVault.Acmebot/Functions/RenewCertificate.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using DurableTask.TypedProxy;

using KeyVault.Acmebot.Internal;
using KeyVault.Acmebot.Models;

using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
Expand All @@ -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<string>();

var activity = context.CreateActivityProxy<ISharedActivity>();

// 証明書の更新処理を開始
var certificatePolicyItem = await activity.GetCertificatePolicy(certificateName);

await context.CallSubOrchestratorAsync(nameof(SharedOrchestrator.IssueCertificate), certificatePolicyItem);
}

[FunctionName($"{nameof(RenewCertificate)}_{nameof(HttpStart)}")]
public async Task<IActionResult> HttpStart(
[HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = "api/certificate/{certificateName}/renew")] HttpRequest req,
Expand All @@ -59,4 +47,17 @@ public async Task<IActionResult> HttpStart(

return AcceptedAtFunction($"{nameof(GetInstanceState)}_{nameof(GetInstanceState.HttpStart)}", new { instanceId }, null);
}

[FunctionName($"{nameof(RenewCertificate)}_{nameof(Orchestrator)}")]
public async Task<CertificateItem> Orchestrator([OrchestrationTrigger] IDurableOrchestrationContext context, ILogger log)
{
var certificateName = context.GetInput<string>();

var activity = context.CreateActivityProxy<ISharedActivity>();

// 証明書の更新処理を開始
var certificatePolicyItem = await activity.GetCertificatePolicy(certificateName);

return await context.CallSubOrchestratorAsync<CertificateItem>(nameof(SharedOrchestrator.IssueCertificate), certificatePolicyItem);
}
}
22 changes: 12 additions & 10 deletions KeyVault.Acmebot/Functions/RenewCertificates.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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)
{
Expand Down Expand Up @@ -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<CertificateItem>(nameof(SharedOrchestrator.IssueCertificate), _retryOptions, certificatePolicyItem);
}
catch (Exception ex)
{
Expand All @@ -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
Expand Down
20 changes: 10 additions & 10 deletions KeyVault.Acmebot/Functions/RevokeCertificate.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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<string>();

var activity = context.CreateActivityProxy<ISharedActivity>();

await activity.RevokeCertificate(certificateName);
}

[FunctionName($"{nameof(RevokeCertificate)}_{nameof(HttpStart)}")]
public async Task<IActionResult> HttpStart(
[HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = "api/certificate/{certificateName}/revoke")] HttpRequest req,
Expand All @@ -57,4 +47,14 @@ public async Task<IActionResult> 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<string>();

var activity = context.CreateActivityProxy<ISharedActivity>();

await activity.RevokeCertificate(certificateName);
}
}
4 changes: 3 additions & 1 deletion KeyVault.Acmebot/Functions/SharedOrchestrator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ namespace KeyVault.Acmebot.Functions;
public class SharedOrchestrator
{
[FunctionName(nameof(IssueCertificate))]
public async Task IssueCertificate([OrchestrationTrigger] IDurableOrchestrationContext context)
public async Task<CertificateItem> IssueCertificate([OrchestrationTrigger] IDurableOrchestrationContext context)
{
var certificatePolicy = context.GetInput<CertificatePolicyItem>();

Expand Down Expand Up @@ -62,5 +62,7 @@ public async Task IssueCertificate([OrchestrationTrigger] IDurableOrchestrationC

// 証明書の更新が完了後に Webhook を送信する
await activity.SendCompletedEvent((certificate.Name, certificate.ExpiresOn, certificatePolicy.DnsNames));

return certificate;
}
}
1 change: 1 addition & 0 deletions KeyVault.Acmebot/Internal/CertificateExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
6 changes: 3 additions & 3 deletions KeyVault.Acmebot/KeyVault.Acmebot.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,17 @@
<AzureFunctionsVersion>v4</AzureFunctionsVersion>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="AWSSDK.Route53" Version="3.7.104.87" />
<PackageReference Include="AWSSDK.Route53" Version="3.7.200.5" />
<PackageReference Include="Azure.Identity" Version="1.9.0" />
<PackageReference Include="Azure.ResourceManager.Dns" Version="1.0.1" />
<PackageReference Include="Azure.ResourceManager.PrivateDns" Version="1.0.1" />
<PackageReference Include="Azure.Security.KeyVault.Certificates" Version="4.5.1" />
<PackageReference Include="Azure.Security.KeyVault.Keys" Version="4.5.0" />
<PackageReference Include="DnsClient" Version="1.7.0" />
<PackageReference Include="DurableTask.TypedProxy" Version="2.2.2" />
<PackageReference Include="Google.Apis.Dns.v1" Version="1.60.0.3018" />
<PackageReference Include="Google.Apis.Dns.v1" Version="1.61.0.3114" />
<PackageReference Include="Microsoft.Azure.Functions.Extensions" Version="1.1.0" />
<PackageReference Include="Microsoft.Azure.WebJobs.Extensions.DurableTask" Version="2.9.6" />
<PackageReference Include="Microsoft.Azure.WebJobs.Extensions.DurableTask" Version="2.10.0" />
<PackageReference Include="Microsoft.Extensions.Http" Version="[6.0.*,7.0.0)" />
<PackageReference Include="Microsoft.NET.Sdk.Functions" Version="4.2.0" />
<PackageReference Include="WebJobs.Extensions.HttpApi" Version="2.0.3" />
Expand Down
5 changes: 4 additions & 1 deletion KeyVault.Acmebot/Models/CertificateItem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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; }

Expand Down Expand Up @@ -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; }
Expand Down
7 changes: 4 additions & 3 deletions KeyVault.Acmebot/host.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
"logging": {
"applicationInsights": {
"samplingSettings": {
"excludedTypes": "Request;Exception",
"isEnabled": true
"isEnabled": true,
"excludedTypes": "Request;Exception"
}
},
"logLevel": {
Expand All @@ -13,7 +13,8 @@
},
"extensions": {
"durableTask": {
"useGracefulShutdown": true
"useGracefulShutdown": true,
"useTablePartitionManagement": true
},
"http": {
"routePrefix": "",
Expand Down