public async Task IssueCertificate([OrchestrationTrigger] IDurableOrchestrationContext context) { var dnsNames = context.GetInput <string[]>(); var activity = context.CreateActivityProxy <ISharedFunctions>(); // 前提条件をチェック await activity.Dns01Precondition(dnsNames); // 新しく ACME Order を作成する var orderDetails = await activity.Order(dnsNames); // 複数の Authorizations を処理する var challenges = new List <ChallengeResult>(); foreach (var authorization in orderDetails.Payload.Authorizations) { // ACME Challenge を実行 var result = await activity.Dns01Authorization((authorization, context.ParentInstanceId ?? context.InstanceId)); // Azure DNS で正しくレコードが引けるか確認 await activity.CheckDnsChallenge(result); challenges.Add(result); } // ACME Answer を実行 await activity.AnswerChallenges(challenges); // Order のステータスが ready になるまで 60 秒待機 await activity.CheckIsReady(orderDetails); await activity.FinalizeOrder((dnsNames, orderDetails)); }
public async Task IssueCertificate([OrchestrationTrigger] IDurableOrchestrationContext context) { var dnsNames = context.GetInput <string[]>(); var activity = context.CreateActivityProxy <ISharedFunctions>(); // 前提条件をチェック await activity.Dns01Precondition(dnsNames); // 新しく ACME Order を作成する var orderDetails = await activity.Order(dnsNames); // ACME Challenge を実行 var challengeResults = await activity.Dns01Authorization(orderDetails.Payload.Authorizations); // DNS で正しくレコードが引けるか確認 await activity.CheckDnsChallenge(challengeResults); // ACME Answer を実行 await activity.AnswerChallenges(challengeResults); // Order のステータスが ready になるまで 60 秒待機 await activity.CheckIsReady(orderDetails); var certificate = await activity.FinalizeOrder((dnsNames, orderDetails)); // 証明書の更新が完了後に Webhook を送信する await activity.SendCompletedEvent((certificate.Name, certificate.ExpiresOn, dnsNames)); }
public async Task IssueCertificate([OrchestrationTrigger] IDurableOrchestrationContext context) { var dnsNames = context.GetInput <string[]>(); var activity = context.CreateActivityProxy <ISharedFunctions>(); // Check prerequisites await activity.Dns01Precondition(dnsNames); // Create a new ACME Order var orderDetails = await activity.Order(dnsNames); // Run ACME Challenge var challengeResults = await activity.Dns01Authorization(orderDetails.Payload.Authorizations); // Verify that DNS can write records correctly await activity.CheckDnsChallenge(challengeResults); // Run ACME Answer await activity.AnswerChallenges(challengeResults); // Wait 60 seconds for order status to ready await activity.CheckIsReady(orderDetails); var certificate = await activity.FinalizeOrder((dnsNames, orderDetails)); // Send a webhook after the certificate renewal is complete await activity.SendCompletedEvent((certificate.SecretIdentifier.Name, certificate.Attributes.Expires, dnsNames)); }
public static async Task RunOrchestrator( [OrchestrationTrigger] IDurableOrchestrationContext context) { var activity = context.CreateActivityProxy <INullActivity>(); await activity.Nop(); }
public async Task Orchestrator([OrchestrationTrigger] IDurableOrchestrationContext context, ILogger log) { var activity = context.CreateActivityProxy <ISharedActivity>(); // 期限切れまで 30 日以内の証明書を取得する var certificates = await activity.GetExpiringCertificates(context.CurrentUtcDateTime); foreach (var certificate in certificates) { log.LogInformation($"{certificate.SubjectName} - {certificate.ExpirationDate}"); } // 更新対象となる証明書がない場合は終わる if (certificates.Count == 0) { log.LogInformation("Certificates are not found"); return; } // スロットリング対策として 120 秒以内でジッターを追加する var jitter = (uint)context.NewGuid().GetHashCode() % 120; await context.CreateTimer(context.CurrentUtcDateTime.AddSeconds(jitter), CancellationToken.None); // リソースグループ単位で証明書の更新を行う var resourceGroups = await activity.GetResourceGroups(); foreach (var resourceGroup in resourceGroups) { // App Service を取得 var sites = await activity.GetSites((resourceGroup.Name, true)); // サイト単位で証明書の更新を行う foreach (var site in sites) { // 期限切れが近い証明書がバインドされているか確認 var boundCertificates = certificates.Where(x => site.HostNameSslStates.Any(xs => xs.Thumbprint == x.Thumbprint)) .ToArray(); // 対象となる証明書が存在しない場合はスキップ if (boundCertificates.Length == 0) { continue; } try { // 証明書の更新処理を開始 await context.CallSubOrchestratorAsync(nameof(RenewCertificates) + "_" + nameof(SubOrchestrator), (site, boundCertificates)); } catch (Exception ex) { // 失敗した場合はログに詳細を書き出して続きを実行する log.LogError($"Failed sub orchestration with Certificates = {string.Join(",", boundCertificates.Select(x => x.Thumbprint))}"); log.LogError(ex.Message); } } } }
public async Task Orchestrator([OrchestrationTrigger] IDurableOrchestrationContext context, ILogger log) { var activity = context.CreateActivityProxy <ISharedActivity>(); // 期限切れまで 30 日以内の証明書を取得する var certificates = await activity.GetExpiringCertificates(context.CurrentUtcDateTime); // 更新対象となる証明書がない場合は終わる if (certificates.Count == 0) { log.LogInformation("Certificates are not found"); return; } // 証明書の更新を行う foreach (var certificate in certificates) { var dnsNames = certificate.DnsNames; log.LogInformation($"{certificate.Id} - {certificate.ExpiresOn}"); try { // 証明書の更新処理を開始 await context.CallSubOrchestratorWithRetryAsync(nameof(SharedOrchestrator.IssueCertificate), _retryOptions, dnsNames); } catch (Exception ex) { // 失敗した場合はログに詳細を書き出して続きを実行する log.LogError($"Failed sub orchestration with DNS names = {string.Join(",", dnsNames)}"); log.LogError(ex.Message); } } }
public static async Task <string> RunOrchestrator( [OrchestrationTrigger] IDurableOrchestrationContext context) { var activity = context.CreateActivityProxy <IAliasActivity>(); return(await activity.SayHello("buchizo")); }
public async Task Orchestrator([OrchestrationTrigger] IDurableOrchestrationContext context, ILogger log) { var certificateName = context.GetInput <string>(); var activity = context.CreateActivityProxy <ISharedActivity>(); await activity.RevokeCertificate(certificateName); }
public async Task <IList <GetCertificateResponse> > GetCertificates([OrchestrationTrigger] IDurableOrchestrationContext context) { var activity = context.CreateActivityProxy <ISharedFunctions>(); var certificates = await activity.GetAllCertificates(); return(certificates.Select(x => new GetCertificateResponse(x)).ToArray()); }
public async Task <IList <string> > GetDnsZones([OrchestrationTrigger] IDurableOrchestrationContext context) { var activity = context.CreateActivityProxy <ISharedFunctions>(); var zones = await activity.GetZones(); return(zones.Select(x => x.Name).ToArray()); }
public async Task <IReadOnlyList <string> > Orchestrator([OrchestrationTrigger] IDurableOrchestrationContext context) { var activity = context.CreateActivityProxy <ISharedActivity>(); var zones = await activity.GetZones(); return(zones); }
public async Task <IList <ResourceGroupInformation> > GetResourceGroupsInformation([OrchestrationTrigger] IDurableOrchestrationContext context) { var activity = context.CreateActivityProxy <ISharedFunctions>(); var resourceGroups = await activity.GetResourceGroups(); return(resourceGroups.Select(x => new ResourceGroupInformation { Name = x.Name }).ToArray()); }
public async Task Orchestrator([OrchestrationTrigger] IDurableOrchestrationContext context, ILogger log) { var request = context.GetInput <AddCertificateRequest>(); var activity = context.CreateActivityProxy <ISharedActivity>(); var site = await activity.GetSite((request.ResourceGroupName, request.AppName, request.SlotName)); if (site == null) { log.LogError($"{request.AppName} is not found"); return; } var hostNameSslStates = site.HostNameSslStates .Where(x => request.DnsNames.Contains(x.Name)) .ToArray(); if (hostNameSslStates.Length != request.DnsNames.Length) { foreach (var dnsName in request.DnsNames.Except(hostNameSslStates.Select(x => x.Name))) { log.LogError($"{dnsName} is not found"); } return; } var asciiDnsNames = request.DnsNames.Select(Punycode.Encode).ToArray(); try { // 証明書を発行し Azure にアップロード var certificate = await context.CallSubOrchestratorAsync <Certificate>(nameof(SharedOrchestrator.IssueCertificate), (site, asciiDnsNames, request.ForceDns01Challenge ?? false)); // App Service のホスト名に証明書をセットする foreach (var hostNameSslState in hostNameSslStates) { hostNameSslState.Thumbprint = certificate.Thumbprint; hostNameSslState.SslState = request.UseIpBasedSsl ?? false ? SslState.IpBasedEnabled : SslState.SniEnabled; hostNameSslState.ToUpdate = true; } await activity.UpdateSiteBinding(site); // 証明書の更新が完了後に Webhook を送信する await activity.SendCompletedEvent((site, certificate.ExpirationDate, asciiDnsNames)); } finally { // クリーンアップ処理を実行 await activity.CleanupVirtualApplication(site); } }
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); }
public async Task <string> RunOrchestrator( [OrchestrationTrigger] IDurableOrchestrationContext context) { var activity = context.CreateActivityProxy <IHttpGetActivity>(); // ブチザッキのタイトルを取る var content = await activity.HttpGet("https://blog.azure.moe/"); var match = Regex.Match(content, @"<title>(.+?)<\/title>"); return(match.Success ? match.Groups[1].Value : ""); }
public async Task IssueCertificate([OrchestrationTrigger] IDurableOrchestrationContext context) { var dnsNames = context.GetInput <string[]>(); var certificateName = dnsNames[0].Replace("*", "wildcard").Replace(".", "-"); var activity = context.CreateActivityProxy <ISharedActivity>(); // 前提条件をチェック await activity.Dns01Precondition(dnsNames); // 新しく ACME Order を作成する var orderDetails = await activity.Order(dnsNames); // 既に確認済みの場合は Challenge をスキップする if (orderDetails.Payload.Status != "ready") { // ACME Challenge を実行 var(challengeResults, propagationSeconds) = await activity.Dns01Authorization(orderDetails.Payload.Authorizations); // DNS Provider が指定した分だけ遅延させる await context.CreateTimer(context.CurrentUtcDateTime.AddSeconds(propagationSeconds), CancellationToken.None); // DNS で正しくレコードが引けるか確認 await activity.CheckDnsChallenge(challengeResults); // ACME Answer を実行 await activity.AnswerChallenges(challengeResults); // Order のステータスが ready になるまで 60 秒待機 await activity.CheckIsReady((orderDetails, challengeResults)); // 作成した DNS レコードを削除 await activity.CleanupDnsChallenge(challengeResults); } // Key Vault で CSR を作成し Finalize を実行 orderDetails = await activity.FinalizeOrder((certificateName, dnsNames, orderDetails)); // Finalize の時点でステータスが valid の時点はスキップ if (orderDetails.Payload.Status != "valid") { // Finalize 後のステータスが valid になるまで 60 秒待機 await activity.CheckIsValid(orderDetails); } // 証明書をダウンロードし Key Vault に保存 var certificate = await activity.MergeCertificate((certificateName, orderDetails)); // 証明書の更新が完了後に Webhook を送信する await activity.SendCompletedEvent((certificate.Name, certificate.ExpiresOn, dnsNames)); }
public async Task <Certificate> IssueCertificate([OrchestrationTrigger] IDurableOrchestrationContext context) { var(site, dnsNames) = context.GetInput <(Site, string[])>(); var activity = context.CreateActivityProxy <ISharedFunctions>(); // ワイルドカード、コンテナ、Linux の場合は DNS-01 を利用する var useDns01Auth = dnsNames.Any(x => x.StartsWith("*")) || site.Kind.Contains("container") || site.Kind.Contains("linux"); // 前提条件をチェック if (useDns01Auth) { await activity.Dns01Precondition(dnsNames); } else { await activity.Http01Precondition(site); } // 新しく ACME Order を作成する var orderDetails = await activity.Order(dnsNames); // 複数の Authorizations を処理する IList <AcmeChallengeResult> challengeResults; // ACME Challenge を実行 if (useDns01Auth) { challengeResults = await activity.Dns01Authorization(orderDetails.Payload.Authorizations); // Azure DNS で正しくレコードが引けるか確認 await activity.CheckDnsChallenge(challengeResults); } else { challengeResults = await activity.Http01Authorization((site, orderDetails.Payload.Authorizations)); // HTTP で正しくアクセスできるか確認 await activity.CheckHttpChallenge(challengeResults); } // ACME Answer を実行 await activity.AnswerChallenges(challengeResults); // Order のステータスが ready になるまで 60 秒待機 await activity.CheckIsReady(orderDetails); // Order の最終処理を実行し PFX を作成 var(thumbprint, pfxBlob) = await activity.FinalizeOrder((dnsNames, orderDetails)); return(await activity.UploadCertificate((site, $"{dnsNames[0]}-{thumbprint}", pfxBlob)));
public async Task <IReadOnlyList <SiteItem> > Orchestrator([OrchestrationTrigger] IDurableOrchestrationContext context) { var resourceGroup = context.GetInput <string>(); var activity = context.CreateActivityProxy <ISharedActivity>(); var result = new List <SiteItem>(); var certificates = await activity.GetAllCertificates(); // App Service を取得 var sites = await activity.GetSites((resourceGroup, true)); foreach (var site in sites.ToLookup(x => x.SplitName().appName)) { var siteInformation = new SiteItem { Name = site.Key, Slots = new List <SlotItem>() }; foreach (var slot in site) { var(_, slotName) = slot.SplitName(); var hostNameSslStates = slot.HostNameSslStates .Where(x => !x.Name.EndsWith(_environment.AppService) && !x.Name.EndsWith(_environment.TrafficManager)); var slotInformation = new SlotItem { Name = slotName ?? "production", DnsNames = hostNameSslStates.Select(x => new DnsNameItem { Name = x.Name, Issuer = certificates.FirstOrDefault(xs => xs.Thumbprint == x.Thumbprint)?.Issuer ?? "None" }).ToArray() }; if (slotInformation.DnsNames.Count != 0) { siteInformation.Slots.Add(slotInformation); } } if (siteInformation.Slots.Count != 0) { result.Add(siteInformation); } } return(result); }
public async Task RenewCertificates([OrchestrationTrigger] IDurableOrchestrationContext context, ILogger log) { var activity = context.CreateActivityProxy <ISharedFunctions>(); // 期限切れまで 30 日以内の証明書を取得する var certificates = await activity.GetCertificates(context.CurrentUtcDateTime); foreach (var certificate in certificates) { log.LogInformation($"{certificate.SubjectName} - {certificate.ExpirationDate}"); } // 更新対象となる証明書がない場合は終わる if (certificates.Count == 0) { log.LogInformation("Certificates are not found"); return; } // App Service を取得 var sites = await activity.GetSites(); // サイト単位で証明書の更新を行う foreach (var site in sites) { // 期限切れが近い証明書がバインドされているか確認 var boundCertificates = certificates.Where(x => site.HostNameSslStates.Any(xs => xs.Thumbprint == x.Thumbprint)) .ToArray(); // 対象となる証明書が存在しない場合はスキップ if (boundCertificates.Length == 0) { continue; } try { // 証明書の更新処理を開始 await context.CallSubOrchestratorAsync(nameof(RenewSiteCertificates), (site, boundCertificates)); } catch (Exception ex) { // 失敗した場合はログに詳細を書き出して続きを実行する log.LogError($"Failed sub orchestration with Certificates = {string.Join(",", boundCertificates.Select(x => x.Thumbprint))}"); log.LogError(ex.Message); } } }
public async Task <List <string> > RunOrchestrator( [OrchestrationTrigger] IDurableOrchestrationContext context) { var outputs = new List <string>(); var activity = context.CreateActivityProxy <IHelloActivity>(); // Replace "hello" with the name of your Durable Activity Function. outputs.Add(await activity.SayHello("Tokyo")); outputs.Add(await activity.SayHello("Seattle")); outputs.Add(await activity.SayHello("London")); // returns ["Hello Tokyo!", "Hello Seattle!", "Hello London!"] return(outputs); }
public async Task <IReadOnlyList <ResourceGroupItem> > Orchestrator([OrchestrationTrigger] IDurableOrchestrationContext context) { var activity = context.CreateActivityProxy <ISharedActivity>(); try { var resourceGroups = await activity.GetResourceGroups(); return(resourceGroups.Select(x => new ResourceGroupItem { Name = x.Name }).ToArray()); } catch { return(Array.Empty <ResourceGroupItem>()); } }
public async Task RenewCertificates([OrchestrationTrigger] IDurableOrchestrationContext context, ILogger log) { var activity = context.CreateActivityProxy <ISharedFunctions>(); // 期限切れまで 30 日以内の証明書を取得する var certificates = await activity.GetCertificates(context.CurrentUtcDateTime); foreach (var certificate in certificates) { log.LogInformation($"{certificate.SubjectName} - {certificate.ExpirationDate}"); } // 更新対象となる証明書がない場合は終わる if (certificates.Count == 0) { log.LogInformation("Certificates are not found"); return; } // App Service を取得 var sites = await activity.GetSites(); var tasks = new List <Task>(); // サイト単位で証明書の更新を行う foreach (var site in sites) { // 期限切れが近い証明書がバインドされているか確認 var boundCertificates = certificates.Where(x => site.HostNameSslStates.Any(xs => xs.Thumbprint == x.Thumbprint)) .ToArray(); // 対象となる証明書が存在しない場合はスキップ if (boundCertificates.Length == 0) { continue; } // 証明書の更新処理を開始 tasks.Add(context.CallSubOrchestratorAsync(nameof(RenewSiteCertificates), (site, boundCertificates))); } // サブオーケストレーターの完了を待つ await Task.WhenAll(tasks); }
public async Task <List <string> > RunOrchestrator( [OrchestrationTrigger] IDurableOrchestrationContext context) { var activity = context.CreateActivityProxy <IHelloActivity>(); var input = new[] { "Tokyo", "Seattle", "London" }; var tasks = new Task <string> [input.Length]; for (int i = 0; i < input.Length; i++) { tasks[i] = activity.SayHello(input[i]); } await Task.WhenAll(tasks); return(tasks.Select(x => x.Result).ToList()); }
public async Task PurgeCertificates([OrchestrationTrigger] IDurableOrchestrationContext context, ILogger log) { var activity = context.CreateActivityProxy <ISharedFunctions>(); // 期限切れまで 30 日以内の証明書を取得する var certificates = await activity.GetExpiringCertificates(context.CurrentUtcDateTime); foreach (var certificate in certificates) { log.LogInformation($"{certificate.SubjectName} - {certificate.ExpirationDate}"); } // 対象となる証明書がない場合は終わる if (certificates.Count == 0) { log.LogInformation("Certificates are not found"); return; } var resourceGroups = await activity.GetResourceGroups(); foreach (var resourceGroup in resourceGroups) { // App Service を取得 var sites = await activity.GetSites((resourceGroup.Name, false)); // App Service にバインド済み証明書のサムプリントを取得 var boundCertificates = sites.SelectMany(x => x.HostNameSslStates.Select(xs => xs.Thumbprint)) .ToArray(); var tasks = new List <Task>(); // バインドされていない証明書を削除 foreach (var certificate in certificates.Where(x => !boundCertificates.Contains(x.Thumbprint))) { tasks.Add(activity.DeleteCertificate(certificate)); } // アクティビティの完了を待つ await Task.WhenAll(tasks); } }
public async Task Orchestrator([OrchestrationTrigger] IDurableOrchestrationContext context, ILogger log) { var activity = context.CreateActivityProxy <ISharedActivity>(); // 期限切れまで 30 日以内の証明書を取得する var certificates = await activity.GetExpiringCertificates(context.CurrentUtcDateTime); // 更新対象となる証明書がない場合は終わる if (certificates.Count == 0) { log.LogInformation("Certificates are not found"); return; } // スロットリング対策として 120 秒以内でジッターを追加する var jitter = (uint)context.NewGuid().GetHashCode() % 120; await context.CreateTimer(context.CurrentUtcDateTime.AddSeconds(jitter), CancellationToken.None); // 証明書の更新を行う foreach (var certificate in certificates) { log.LogInformation($"{certificate.Id} - {certificate.ExpiresOn}"); try { // 証明書の更新処理を開始 var certificatePolicyItem = await activity.GetCertificatePolicy(certificate.Name); await context.CallSubOrchestratorWithRetryAsync(nameof(SharedOrchestrator.IssueCertificate), _retryOptions, certificatePolicyItem); } catch (Exception ex) { // 失敗した場合はログに詳細を書き出して続きを実行する log.LogError($"Failed sub orchestration with DNS names = {string.Join(",", certificate.DnsNames)}"); log.LogError(ex.Message); } } }
public async Task RenewCertificates([OrchestrationTrigger] IDurableOrchestrationContext context, ILogger log) { var activity = context.CreateActivityProxy <ISharedFunctions>(); // 期限切れまで 30 日以内の証明書を取得する var certificates = await activity.GetCertificates(context.CurrentUtcDateTime); // 更新対象となる証明書がない場合は終わる if (certificates.Count == 0) { log.LogInformation("Certificates are not found"); return; } // 証明書の更新を行う foreach (var certificate in certificates) { log.LogInformation($"{certificate.Id} - {certificate.Attributes.Expires}"); // 証明書の更新処理を開始 await context.CallSubOrchestratorAsync(nameof(SharedFunctions.IssueCertificate), certificate.Policy.X509CertificateProperties.SubjectAlternativeNames.DnsNames); } }
public async Task IssueCertificate([OrchestrationTrigger] IDurableOrchestrationContext context) { var dnsNames = context.GetInput <string[]>(); var activity = context.CreateActivityProxy <ISharedFunctions>(); // 前提条件をチェック await activity.Dns01Precondition(dnsNames); // 新しく ACME Order を作成する var orderDetails = await activity.Order(dnsNames); // ACME Challenge を実行 var challengeResults = await activity.Dns01Authorization(orderDetails.Payload.Authorizations); // DNS Provider が指定した分だけ遅延させる await context.CreateTimer(context.CurrentUtcDateTime.AddSeconds(_dnsProvider.PropagationSeconds), CancellationToken.None); // DNS で正しくレコードが引けるか確認 await activity.CheckDnsChallenge(challengeResults); // ACME Answer を実行 await activity.AnswerChallenges(challengeResults); // Order のステータスが ready になるまで 60 秒待機 await activity.CheckIsReady((orderDetails, challengeResults)); // 証明書を作成し Key Vault に保存 var certificate = await activity.FinalizeOrder((dnsNames, orderDetails)); // 作成した DNS レコードを削除 await activity.CleanupDnsChallenge(challengeResults); // 証明書の更新が完了後に Webhook を送信する await activity.SendCompletedEvent((certificate.Name, certificate.ExpiresOn, dnsNames)); }
public async Task AddCertificate([OrchestrationTrigger] IDurableOrchestrationContext context, ILogger log) { var request = context.GetInput <AddCertificateRequest>(); var activity = context.CreateActivityProxy <ISharedFunctions>(); var site = await activity.GetSite((request.ResourceGroupName, request.AppName, request.SlotName)); if (site == null) { log.LogError($"{request.AppName} is not found"); return; } var hostNameSslStates = site.HostNameSslStates .Where(x => request.Domains.Contains(x.Name)) .ToArray(); if (hostNameSslStates.Length != request.Domains.Length) { foreach (var hostName in request.Domains.Except(hostNameSslStates.Select(x => x.Name))) { log.LogError($"{hostName} is not found"); } return; } // ワイルドカード、コンテナ、Linux の場合は DNS-01 を利用する var useDns01Auth = request.Domains.Any(x => x.StartsWith("*")) || site.Kind.Contains("container") || site.Kind.Contains("linux"); // 前提条件をチェック if (useDns01Auth) { await activity.Dns01Precondition(request.Domains); } else { await activity.Http01Precondition(site); } // 新しく ACME Order を作成する var orderDetails = await activity.Order(request.Domains); IList <AcmeChallengeResult> challengeResults; // ACME Challenge を実行 if (useDns01Auth) { // DNS-01 を使う challengeResults = await activity.Dns01Authorization(orderDetails.Payload.Authorizations); // Azure DNS で正しくレコードが引けるか確認 await activity.CheckDnsChallenge(challengeResults); } else { // HTTP-01 を使う challengeResults = await activity.Http01Authorization((site, orderDetails.Payload.Authorizations)); // HTTP で正しくアクセスできるか確認 await activity.CheckHttpChallenge(challengeResults); } // ACME Answer を実行 await activity.AnswerChallenges(challengeResults); // Order のステータスが ready になるまで 60 秒待機 await activity.CheckIsReady(orderDetails); // Order の最終処理を実行し PFX を作成 var(thumbprint, pfxBlob) = await activity.FinalizeOrder((request.Domains, orderDetails)); await activity.UpdateCertificate((site, $"{request.Domains[0]}-{thumbprint}", pfxBlob)); foreach (var hostNameSslState in hostNameSslStates) { hostNameSslState.Thumbprint = thumbprint; hostNameSslState.SslState = request.UseIpBasedSsl ?? false ? SslState.IpBasedEnabled : SslState.SniEnabled; hostNameSslState.ToUpdate = true; } await activity.UpdateSiteBinding(site); // クリーンアップ処理を実行 await activity.CleanupVirtualApplication(site); }
public Task <IList <CertificateItem> > GetCertificates([OrchestrationTrigger] IDurableOrchestrationContext context) { var activity = context.CreateActivityProxy <ISharedFunctions>(); return(activity.GetAllCertificates()); }
public async Task <Certificate> IssueCertificate([OrchestrationTrigger] IDurableOrchestrationContext context) { var(site, dnsNames, forceDns01Challenge) = context.GetInput <(Site, string[], bool)>(); var activity = context.CreateActivityProxy <ISharedActivity>(); // ワイルドカード、コンテナ、Linux の場合は DNS-01 を利用する var useDns01Auth = forceDns01Challenge || dnsNames.Any(x => x.StartsWith("*")) || site.Kind.Contains("container") || site.Kind.Contains("linux"); // 前提条件をチェック if (useDns01Auth) { await activity.Dns01Precondition(dnsNames); } else { await activity.Http01Precondition(site); } // 新しく ACME Order を作成する var orderDetails = await activity.Order(dnsNames); // 既に確認済みの場合は Challenge をスキップする if (orderDetails.Payload.Status != "ready") { // 複数の Authorizations を処理する IReadOnlyList <AcmeChallengeResult> challengeResults; // ACME Challenge を実行 if (useDns01Auth) { challengeResults = await activity.Dns01Authorization(orderDetails.Payload.Authorizations); // DNS レコードの変更が伝搬するまで 10 秒遅延させる await context.CreateTimer(context.CurrentUtcDateTime.AddSeconds(10), CancellationToken.None); // Azure DNS で正しくレコードが引けるか確認 await activity.CheckDnsChallenge(challengeResults); } else { challengeResults = await activity.Http01Authorization((site, orderDetails.Payload.Authorizations)); // HTTP で正しくアクセスできるか確認 await activity.CheckHttpChallenge(challengeResults); } // ACME Answer を実行 await activity.AnswerChallenges(challengeResults); // Order のステータスが ready になるまで 60 秒待機 await activity.CheckIsReady((orderDetails, challengeResults)); if (useDns01Auth) { // 作成した DNS レコードを削除 await activity.CleanupDnsChallenge(challengeResults); } } // CSR を作成し Finalize を実行 var(finalize, rsaParameters) = await activity.FinalizeOrder((dnsNames, orderDetails)); // Finalize の時点でステータスが valid の時点はスキップ if (finalize.Payload.Status != "valid") { // Finalize 後のステータスが valid になるまで 60 秒待機 finalize = await activity.CheckIsValid(finalize); } // 証明書をダウンロードし App Service へアップロード var certificate = await activity.UploadCertificate((site, dnsNames[0], forceDns01Challenge, finalize, rsaParameters));