mirror of
https://github.com/MAKS-IT-COM/maksit-certs-ui.git
synced 2025-12-31 04:00:03 +01:00
(feature): auto renewal service implementation
This commit is contained in:
parent
7378996d19
commit
d046bcecd9
@ -36,4 +36,20 @@ public static class StringExtensions {
|
|||||||
? JsonSerializer.Deserialize<T>(s, options)
|
? JsonSerializer.Deserialize<T>(s, options)
|
||||||
: default;
|
: default;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Guid? ToNullabeGuid(this string? s) {
|
||||||
|
if (Guid.TryParse(s, out var result)) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Guid ToGuid(this string s) {
|
||||||
|
if (Guid.TryParse(s, out var result)) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Guid.Empty;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Security.Cryptography.X509Certificates;
|
|
||||||
using System.Security.Cryptography;
|
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using System.Security.Cryptography;
|
||||||
|
using System.Security.Cryptography.X509Certificates;
|
||||||
|
|
||||||
using MaksIT.LetsEncrypt.Entities.Jws;
|
using MaksIT.LetsEncrypt.Entities.Jws;
|
||||||
|
|
||||||
namespace MaksIT.LetsEncrypt.Entities;
|
namespace MaksIT.LetsEncrypt.Entities;
|
||||||
@ -17,6 +17,7 @@ public class RegistrationCache {
|
|||||||
/// Field used to identify cache by account id
|
/// Field used to identify cache by account id
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public Guid AccountId { get; set; }
|
public Guid AccountId { get; set; }
|
||||||
|
public string[]? Contacts { get; set; }
|
||||||
|
|
||||||
|
|
||||||
public Dictionary<string, CertificateCache>? CachedCerts { get; set; }
|
public Dictionary<string, CertificateCache>? CachedCerts { get; set; }
|
||||||
@ -28,10 +29,7 @@ public class RegistrationCache {
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns a list of hosts with upcoming SSL expiry
|
/// Returns a list of hosts with upcoming SSL expiry
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string[] HostsWithUpcomingSslExpiry {
|
public string[] GetHostsWithUpcomingSslExpiry(int days = 30) {
|
||||||
|
|
||||||
get {
|
|
||||||
|
|
||||||
var hostsWithUpcomingSslExpiry = new List<string>();
|
var hostsWithUpcomingSslExpiry = new List<string>();
|
||||||
|
|
||||||
if (CachedCerts == null)
|
if (CachedCerts == null)
|
||||||
@ -44,14 +42,13 @@ public class RegistrationCache {
|
|||||||
var cert = new X509Certificate2(Encoding.ASCII.GetBytes(cachedChert.Cert));
|
var cert = new X509Certificate2(Encoding.ASCII.GetBytes(cachedChert.Cert));
|
||||||
|
|
||||||
// if it is about to expire, we need to refresh
|
// if it is about to expire, we need to refresh
|
||||||
if ((cert.NotAfter - DateTime.UtcNow).TotalDays < 30)
|
if ((cert.NotAfter - DateTime.UtcNow).TotalDays < days)
|
||||||
hostsWithUpcomingSslExpiry.Add(subject);
|
hostsWithUpcomingSslExpiry.Add(subject);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return hostsWithUpcomingSslExpiry.ToArray();
|
return hostsWithUpcomingSslExpiry.ToArray();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns cached certificate. Certs older than 30 days are not returned
|
/// Returns cached certificate. Certs older than 30 days are not returned
|
||||||
|
|||||||
@ -25,6 +25,7 @@ public interface ILetsEncryptService {
|
|||||||
Task<IDomainResult> CompleteChallenges(Guid sessionId);
|
Task<IDomainResult> CompleteChallenges(Guid sessionId);
|
||||||
Task<IDomainResult> GetOrder(Guid sessionId, string[] hostnames);
|
Task<IDomainResult> GetOrder(Guid sessionId, string[] hostnames);
|
||||||
Task<IDomainResult> GetCertificate(Guid sessionId, string subject);
|
Task<IDomainResult> GetCertificate(Guid sessionId, string subject);
|
||||||
|
(string[]?, IDomainResult) HostsWithUpcomingSslExpiry(Guid sessionId);
|
||||||
(CachedCertificateResult?, IDomainResult) TryGetCachedCertificate(Guid sessionId, string subject);
|
(CachedCertificateResult?, IDomainResult) TryGetCachedCertificate(Guid sessionId, string subject);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -128,6 +129,7 @@ public class LetsEncryptService : ILetsEncryptService {
|
|||||||
|
|
||||||
state.Cache = new RegistrationCache {
|
state.Cache = new RegistrationCache {
|
||||||
AccountId = accountId,
|
AccountId = accountId,
|
||||||
|
Contacts = contacts,
|
||||||
|
|
||||||
Location = account.Result.Location,
|
Location = account.Result.Location,
|
||||||
AccountKey = accountKey.ExportCspBlob(true),
|
AccountKey = accountKey.ExportCspBlob(true),
|
||||||
@ -432,6 +434,15 @@ public class LetsEncryptService : ILetsEncryptService {
|
|||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region TryGetCachedCertificate
|
#region TryGetCachedCertificate
|
||||||
|
public (string[]?, IDomainResult) HostsWithUpcomingSslExpiry(Guid sessionId) {
|
||||||
|
|
||||||
|
var state = GetOrCreateState(sessionId);
|
||||||
|
if (state.Cache == null)
|
||||||
|
return IDomainResult.Failed<string[]?>();
|
||||||
|
|
||||||
|
return IDomainResult.Success(state.Cache.GetHostsWithUpcomingSslExpiry());
|
||||||
|
}
|
||||||
|
|
||||||
public (CachedCertificateResult?, IDomainResult) TryGetCachedCertificate(Guid sessionId, string subject) {
|
public (CachedCertificateResult?, IDomainResult) TryGetCachedCertificate(Guid sessionId, string subject) {
|
||||||
|
|
||||||
var state = GetOrCreateState(sessionId);
|
var state = GetOrCreateState(sessionId);
|
||||||
@ -567,10 +578,10 @@ public class LetsEncryptService : ILetsEncryptService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var response = await _httpClient.SendAsync(request);
|
var response = await _httpClient.SendAsync(request);
|
||||||
await UpdateStateNonceIfNeededAsync(response, state, method);
|
UpdateStateNonceIfNeededAsync(response, state, method);
|
||||||
|
|
||||||
var responseText = await response.Content.ReadAsStringAsync();
|
var responseText = await response.Content.ReadAsStringAsync();
|
||||||
await HandleProblemResponseAsync(response, responseText);
|
HandleProblemResponseAsync(response, responseText);
|
||||||
|
|
||||||
var result = ProcessResponseContent<TResult>(response, responseText);
|
var result = ProcessResponseContent<TResult>(response, responseText);
|
||||||
return IDomainResult.Success(result);
|
return IDomainResult.Success(result);
|
||||||
@ -634,13 +645,13 @@ public class LetsEncryptService : ILetsEncryptService {
|
|||||||
request.Content.Headers.ContentType = new MediaTypeHeaderValue(contentType);
|
request.Content.Headers.ContentType = new MediaTypeHeaderValue(contentType);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task UpdateStateNonceIfNeededAsync(HttpResponseMessage response, State state, HttpMethod method) {
|
private void UpdateStateNonceIfNeededAsync(HttpResponseMessage response, State state, HttpMethod method) {
|
||||||
if (method == HttpMethod.Post && response.Headers.Contains("Replay-Nonce")) {
|
if (method == HttpMethod.Post && response.Headers.Contains("Replay-Nonce")) {
|
||||||
state.Nonce = response.Headers.GetValues("Replay-Nonce").First();
|
state.Nonce = response.Headers.GetValues("Replay-Nonce").First();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task HandleProblemResponseAsync(HttpResponseMessage response, string responseText) {
|
private void HandleProblemResponseAsync(HttpResponseMessage response, string responseText) {
|
||||||
if (response.Content.Headers.ContentType?.MediaType == "application/problem+json") {
|
if (response.Content.Headers.ContentType?.MediaType == "application/problem+json") {
|
||||||
throw new LetsEncrytException(responseText.ToObject<Problem>(), response);
|
throw new LetsEncrytException(responseText.ToObject<Problem>(), response);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,17 +1,136 @@
|
|||||||
namespace LetsEncryptServer.BackgroundServices {
|
using DomainResults.Common;
|
||||||
|
using MaksIT.LetsEncryptServer.Services;
|
||||||
|
using MaksIT.Models.LetsEncryptServer.Requests;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using Microsoft.Extensions.Options;
|
||||||
|
|
||||||
|
namespace MaksIT.LetsEncryptServer.BackgroundServices {
|
||||||
public class AutoRenewal : BackgroundService {
|
public class AutoRenewal : BackgroundService {
|
||||||
|
|
||||||
|
private readonly IOptions<Configuration> _appSettings;
|
||||||
|
private readonly ILogger<AutoRenewal> _logger;
|
||||||
|
private readonly ICacheService _cacheService;
|
||||||
|
private readonly ICertsFlowService _certsFlowService;
|
||||||
|
|
||||||
|
public AutoRenewal(
|
||||||
|
IOptions<Configuration> appSettings,
|
||||||
|
ILogger<AutoRenewal> logger,
|
||||||
|
ICacheService cacheService,
|
||||||
|
ICertsFlowService certsFlowService
|
||||||
|
) {
|
||||||
|
_appSettings = appSettings;
|
||||||
|
_logger = logger;
|
||||||
|
_cacheService = cacheService;
|
||||||
|
_certsFlowService = certsFlowService;
|
||||||
|
}
|
||||||
|
|
||||||
protected override async Task ExecuteAsync(CancellationToken stoppingToken) {
|
protected override async Task ExecuteAsync(CancellationToken stoppingToken) {
|
||||||
while (!stoppingToken.IsCancellationRequested) {
|
while (!stoppingToken.IsCancellationRequested) {
|
||||||
// Your background task logic here
|
_logger.LogInformation("Background service is running.");
|
||||||
Console.WriteLine("Background service is running.");
|
|
||||||
|
|
||||||
// Simulate some work by delaying for 5 seconds
|
var (accountIds, getAccountIdsResult) = await _cacheService.ListCachedAccountsAsync();
|
||||||
await Task.Delay(TimeSpan.FromSeconds(5), stoppingToken);
|
if (!getAccountIdsResult.IsSuccess || accountIds == null) {
|
||||||
|
LogErrors(getAccountIdsResult.Errors);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var accountId in accountIds) {
|
||||||
|
await ProcessAccountAsync(accountId);
|
||||||
|
}
|
||||||
|
|
||||||
|
await Task.Delay(TimeSpan.FromMinutes(5), stoppingToken);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<IDomainResult> ProcessAccountAsync(Guid accountId) {
|
||||||
|
var (cache, loadResult) = await _cacheService.LoadFromCacheAsync(accountId);
|
||||||
|
if (!loadResult.IsSuccess || cache == null) {
|
||||||
|
LogErrors(loadResult.Errors);
|
||||||
|
return loadResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
var hostnames = cache.GetHostsWithUpcomingSslExpiry();
|
||||||
|
if (hostnames == null || !hostnames.Any()) {
|
||||||
|
_logger.LogError("No hosts found with upcoming SSL expiry");
|
||||||
|
return IDomainResult.Success();
|
||||||
|
}
|
||||||
|
|
||||||
|
var renewResult = await RenewCertificatesForHostnames(accountId, cache.Contacts, hostnames);
|
||||||
|
if (!renewResult.IsSuccess)
|
||||||
|
return renewResult;
|
||||||
|
|
||||||
|
_logger.LogInformation($"Certificates renewed for account {accountId}");
|
||||||
|
|
||||||
|
return IDomainResult.Success();
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<IDomainResult> RenewCertificatesForHostnames(Guid accountId, string[] contacts, string[] hostnames) {
|
||||||
|
var (sessionId, configureClientResult) = await _certsFlowService.ConfigureClientAsync();
|
||||||
|
if (!configureClientResult.IsSuccess || sessionId == null) {
|
||||||
|
LogErrors(configureClientResult.Errors);
|
||||||
|
return configureClientResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
var sessionIdValue = sessionId.Value;
|
||||||
|
|
||||||
|
var (_, initResult) = await _certsFlowService.InitAsync(sessionIdValue, accountId, new InitRequest {
|
||||||
|
Contacts = contacts
|
||||||
|
});
|
||||||
|
if (!initResult.IsSuccess) {
|
||||||
|
LogErrors(initResult.Errors);
|
||||||
|
return initResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
var (_, newOrderResult) = await _certsFlowService.NewOrderAsync(sessionIdValue, new NewOrderRequest {
|
||||||
|
Hostnames = hostnames,
|
||||||
|
ChallengeType = "http-01"
|
||||||
|
});
|
||||||
|
if (!newOrderResult.IsSuccess) {
|
||||||
|
LogErrors(newOrderResult.Errors);
|
||||||
|
return newOrderResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
var challengeResult = await _certsFlowService.CompleteChallengesAsync(sessionIdValue);
|
||||||
|
if (!challengeResult.IsSuccess) {
|
||||||
|
LogErrors(challengeResult.Errors);
|
||||||
|
return challengeResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
var getOrderResult = await _certsFlowService.GetOrderAsync(sessionIdValue, new GetOrderRequest {
|
||||||
|
Hostnames = hostnames
|
||||||
|
});
|
||||||
|
if (!getOrderResult.IsSuccess) {
|
||||||
|
LogErrors(getOrderResult.Errors);
|
||||||
|
return getOrderResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
var certs = await _certsFlowService.GetCertificatesAsync(sessionIdValue, new GetCertificatesRequest {
|
||||||
|
Hostnames = hostnames
|
||||||
|
});
|
||||||
|
if (!certs.IsSuccess) {
|
||||||
|
LogErrors(certs.Errors);
|
||||||
|
return certs;
|
||||||
|
}
|
||||||
|
|
||||||
|
var (_, applyCertsResult) = await _certsFlowService.ApplyCertificatesAsync(sessionIdValue, new GetCertificatesRequest {
|
||||||
|
Hostnames = hostnames
|
||||||
|
});
|
||||||
|
if (!applyCertsResult.IsSuccess) {
|
||||||
|
LogErrors(applyCertsResult.Errors);
|
||||||
|
return applyCertsResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
return IDomainResult.Success();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void LogErrors(IEnumerable<string> errors) {
|
||||||
|
foreach (var error in errors) {
|
||||||
|
_logger.LogError(error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override Task StopAsync(CancellationToken stoppingToken) {
|
public override Task StopAsync(CancellationToken stoppingToken) {
|
||||||
Console.WriteLine("Background service is stopping.");
|
_logger.LogInformation("Background service is stopping.");
|
||||||
return base.StopAsync(stoppingToken);
|
return base.StopAsync(stoppingToken);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -108,7 +108,18 @@ public class CertsFlowController : ControllerBase {
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
[HttpPost("[action]/{sessionId}")]
|
[HttpPost("[action]/{sessionId}")]
|
||||||
public async Task<IActionResult> ApplyCertificates(Guid sessionId, [FromBody] GetCertificatesRequest requestData) {
|
public async Task<IActionResult> ApplyCertificates(Guid sessionId, [FromBody] GetCertificatesRequest requestData) {
|
||||||
var result = await _certsFlowService.ApplyCertificates(sessionId, requestData);
|
var result = await _certsFlowService.ApplyCertificatesAsync(sessionId, requestData);
|
||||||
|
return result.ToActionResult();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns a list of hosts with upcoming SSL expiry
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="sessionId"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
[HttpGet("[action]/{sessionId}")]
|
||||||
|
public IActionResult HostsWithUpcomingSslExpiry(Guid sessionId) {
|
||||||
|
var result = _certsFlowService.HostsWithUpcomingSslExpiry(sessionId);
|
||||||
return result.ToActionResult();
|
return result.ToActionResult();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
using MaksIT.LetsEncryptServer;
|
using MaksIT.LetsEncryptServer;
|
||||||
using MaksIT.LetsEncrypt.Services;
|
using MaksIT.LetsEncrypt.Services;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
|
||||||
using MaksIT.LetsEncryptServer.Services;
|
using MaksIT.LetsEncryptServer.Services;
|
||||||
|
using MaksIT.LetsEncryptServer.BackgroundServices;
|
||||||
|
|
||||||
var builder = WebApplication.CreateBuilder(args);
|
var builder = WebApplication.CreateBuilder(args);
|
||||||
|
|
||||||
@ -26,9 +26,10 @@ builder.Services.AddSwaggerGen();
|
|||||||
builder.Services.AddMemoryCache();
|
builder.Services.AddMemoryCache();
|
||||||
|
|
||||||
builder.Services.AddHttpClient<ILetsEncryptService, LetsEncryptService>();
|
builder.Services.AddHttpClient<ILetsEncryptService, LetsEncryptService>();
|
||||||
builder.Services.AddScoped<ICertsFlowService, CertsFlowService>();
|
builder.Services.AddSingleton<ICertsFlowService, CertsFlowService>();
|
||||||
builder.Services.AddSingleton<ICacheService, CacheService>();
|
builder.Services.AddSingleton<ICacheService, CacheService>();
|
||||||
builder.Services.AddHttpClient<IAgentService, AgentService>();
|
builder.Services.AddHttpClient<IAgentService, AgentService>();
|
||||||
|
builder.Services.AddHostedService<AutoRenewal>();
|
||||||
|
|
||||||
var app = builder.Build();
|
var app = builder.Build();
|
||||||
|
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
using System.Text.Json;
|
using System.Text.Json;
|
||||||
|
|
||||||
using DomainResults.Common;
|
using DomainResults.Common;
|
||||||
|
using MaksIT.Core.Extensions;
|
||||||
using MaksIT.LetsEncrypt.Entities;
|
using MaksIT.LetsEncrypt.Entities;
|
||||||
|
|
||||||
namespace MaksIT.LetsEncryptServer.Services;
|
namespace MaksIT.LetsEncryptServer.Services;
|
||||||
@ -10,6 +10,7 @@ public interface ICacheService {
|
|||||||
Task<(RegistrationCache?, IDomainResult)> LoadFromCacheAsync(Guid accountId);
|
Task<(RegistrationCache?, IDomainResult)> LoadFromCacheAsync(Guid accountId);
|
||||||
Task<IDomainResult> SaveToCacheAsync(Guid accountId, RegistrationCache cache);
|
Task<IDomainResult> SaveToCacheAsync(Guid accountId, RegistrationCache cache);
|
||||||
Task<IDomainResult> DeleteFromCacheAsync(Guid accountId);
|
Task<IDomainResult> DeleteFromCacheAsync(Guid accountId);
|
||||||
|
Task<(Guid[]?, IDomainResult)> ListCachedAccountsAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
public class CacheService : ICacheService, IDisposable {
|
public class CacheService : ICacheService, IDisposable {
|
||||||
@ -117,6 +118,29 @@ public class CacheService : ICacheService, IDisposable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task<(Guid[]?, IDomainResult)> ListCachedAccountsAsync() {
|
||||||
|
await _cacheLock.WaitAsync();
|
||||||
|
|
||||||
|
try {
|
||||||
|
var cacheFiles = Directory.GetFiles(_cacheDirectory);
|
||||||
|
if (cacheFiles == null)
|
||||||
|
return IDomainResult.Success(new Guid[0]);
|
||||||
|
|
||||||
|
var accountIds = cacheFiles.Select(x => Path.GetFileNameWithoutExtension(x).ToGuid()).ToArray();
|
||||||
|
|
||||||
|
return IDomainResult.Success(accountIds);
|
||||||
|
}
|
||||||
|
catch (Exception ex) {
|
||||||
|
var message = "Error listing cache files";
|
||||||
|
_logger.LogError(ex, message);
|
||||||
|
|
||||||
|
return IDomainResult.Failed<Guid[]?> (message);
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
_cacheLock.Release();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void Dispose() {
|
public void Dispose() {
|
||||||
_cacheLock?.Dispose();
|
_cacheLock?.Dispose();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -23,7 +23,8 @@ public interface ICertsFlowService : ICertsFlowServiceBase {
|
|||||||
Task<IDomainResult> CompleteChallengesAsync(Guid sessionId);
|
Task<IDomainResult> CompleteChallengesAsync(Guid sessionId);
|
||||||
Task<IDomainResult> GetOrderAsync(Guid sessionId, GetOrderRequest requestData);
|
Task<IDomainResult> GetOrderAsync(Guid sessionId, GetOrderRequest requestData);
|
||||||
Task<IDomainResult> GetCertificatesAsync(Guid sessionId, GetCertificatesRequest requestData);
|
Task<IDomainResult> GetCertificatesAsync(Guid sessionId, GetCertificatesRequest requestData);
|
||||||
Task<(Dictionary<string, string>?, IDomainResult)> ApplyCertificates(Guid sessionId, GetCertificatesRequest requestData);
|
Task<(Dictionary<string, string>?, IDomainResult)> ApplyCertificatesAsync(Guid sessionId, GetCertificatesRequest requestData);
|
||||||
|
(string[]?, IDomainResult) HostsWithUpcomingSslExpiry(Guid sessionId);
|
||||||
}
|
}
|
||||||
|
|
||||||
public class CertsFlowService : ICertsFlowService {
|
public class CertsFlowService : ICertsFlowService {
|
||||||
@ -140,7 +141,7 @@ public class CertsFlowService : ICertsFlowService {
|
|||||||
return IDomainResult.Success();
|
return IDomainResult.Success();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<(Dictionary<string, string>?, IDomainResult)> ApplyCertificates(Guid sessionId, GetCertificatesRequest requestData) {
|
public async Task<(Dictionary<string, string>?, IDomainResult)> ApplyCertificatesAsync(Guid sessionId, GetCertificatesRequest requestData) {
|
||||||
var results = new Dictionary<string, string>();
|
var results = new Dictionary<string, string>();
|
||||||
|
|
||||||
foreach (var subject in requestData.Hostnames) {
|
foreach (var subject in requestData.Hostnames) {
|
||||||
@ -164,6 +165,28 @@ public class CertsFlowService : ICertsFlowService {
|
|||||||
return IDomainResult.Success(results);
|
return IDomainResult.Success(results);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public (string[]?, IDomainResult) HostsWithUpcomingSslExpiry(Guid sessionId) {
|
||||||
|
|
||||||
|
var (hostnames, hostnamesResult) = _letsEncryptService.HostsWithUpcomingSslExpiry(sessionId);
|
||||||
|
if(!hostnamesResult.IsSuccess)
|
||||||
|
return (null, hostnamesResult);
|
||||||
|
|
||||||
|
return IDomainResult.Success(hostnames);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public (string?, IDomainResult) AcmeChallenge(string fileName) {
|
public (string?, IDomainResult) AcmeChallenge(string fileName) {
|
||||||
DeleteExporedChallenges();
|
DeleteExporedChallenges();
|
||||||
|
|
||||||
|
|||||||
@ -11,7 +11,7 @@
|
|||||||
"Production": "https://acme-v02.api.letsencrypt.org/directory",
|
"Production": "https://acme-v02.api.letsencrypt.org/directory",
|
||||||
"Staging": "https://acme-staging-v02.api.letsencrypt.org/directory",
|
"Staging": "https://acme-staging-v02.api.letsencrypt.org/directory",
|
||||||
|
|
||||||
"DevMode": true,
|
"DevMode": false,
|
||||||
|
|
||||||
"Agent": {
|
"Agent": {
|
||||||
"AgentHostname": "http://lblsrv0001.corp.maks-it.com",
|
"AgentHostname": "http://lblsrv0001.corp.maks-it.com",
|
||||||
|
|||||||
@ -474,6 +474,38 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"response": []
|
"response": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "host with upcoming ssl expire",
|
||||||
|
"request": {
|
||||||
|
"method": "GET",
|
||||||
|
"header": [
|
||||||
|
{
|
||||||
|
"key": "Content-Type",
|
||||||
|
"value": "application/json",
|
||||||
|
"disabled": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "Accept",
|
||||||
|
"value": "application/json",
|
||||||
|
"disabled": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"url": {
|
||||||
|
"raw": "http://localhost:8080/CertsFlow/HostsWithUpcomingSslExpiry/{{sessionId}}",
|
||||||
|
"protocol": "http",
|
||||||
|
"host": [
|
||||||
|
"localhost"
|
||||||
|
],
|
||||||
|
"port": "8080",
|
||||||
|
"path": [
|
||||||
|
"CertsFlow",
|
||||||
|
"HostsWithUpcomingSslExpiry",
|
||||||
|
"{{sessionId}}"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"response": []
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@ -476,6 +476,38 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"response": []
|
"response": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "host with upcoming ssl expire Copy",
|
||||||
|
"request": {
|
||||||
|
"method": "GET",
|
||||||
|
"header": [
|
||||||
|
{
|
||||||
|
"key": "Content-Type",
|
||||||
|
"value": "application/json",
|
||||||
|
"disabled": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "Accept",
|
||||||
|
"value": "application/json",
|
||||||
|
"disabled": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"url": {
|
||||||
|
"raw": "http://localhost:8080/CertsFlow/HostsWithUpcomingSslExpiry/{{sessionId}}",
|
||||||
|
"protocol": "http",
|
||||||
|
"host": [
|
||||||
|
"localhost"
|
||||||
|
],
|
||||||
|
"port": "8080",
|
||||||
|
"path": [
|
||||||
|
"CertsFlow",
|
||||||
|
"HostsWithUpcomingSslExpiry",
|
||||||
|
"{{sessionId}}"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"response": []
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
Loading…
Reference in New Issue
Block a user