diff options
Diffstat (limited to 'src')
19 files changed, 189 insertions, 108 deletions
diff --git a/src/main.lib/Clients/Acme/OrderManager.cs b/src/main.lib/Clients/Acme/OrderManager.cs index aecb184..51a30c3 100644 --- a/src/main.lib/Clients/Acme/OrderManager.cs +++ b/src/main.lib/Clients/Acme/OrderManager.cs @@ -42,7 +42,7 @@ namespace PKISharp.WACS.Clients.Acme public async Task<OrderDetails?> GetOrCreate(Order order, RunLevel runLevel)
{
var cacheKey = _certificateService.CacheKey(order);
- var existingOrder = FindRecentOrder(cacheKey);
+ var existingOrder = default(OrderDetails); // FindRecentOrder(cacheKey);
if (existingOrder != null)
{
try
diff --git a/src/main.lib/Clients/AcmeDnsClient.cs b/src/main.lib/Clients/AcmeDnsClient.cs index ff81997..fb6cd0d 100644 --- a/src/main.lib/Clients/AcmeDnsClient.cs +++ b/src/main.lib/Clients/AcmeDnsClient.cs @@ -76,7 +76,8 @@ namespace PKISharp.WACS.Clients _input.Show("Note", "Some DNS control panels add the final dot automatically. Only one is required."); if (!await _input.Wait("Please press <Enter> after you've created and verified the record")) { - throw new Exception("User aborted"); + _log.Warning("User aborted"); + return false; } if (await VerifyRegistration(domain, newReg.Fulldomain, interactive)) { @@ -111,7 +112,7 @@ namespace PKISharp.WACS.Clients } else if (interactive && _input != null) { - if (!await _input.PromptYesNo("Unable to verify acme-dns configuration, press 'Y' or <ENTER> to retry, or 'N' to skip this step.", true)) + if (!await _input.PromptYesNo("Unable to verify acme-dns configuration, press 'Y' or <Enter> to retry, or 'N' to skip this step.", true)) { _log.Warning("Verification of acme-dns configuration skipped."); return true; @@ -199,18 +200,18 @@ namespace PKISharp.WACS.Clients } } - public async Task Update(string domain, string token) + public async Task<bool> Update(string domain, string token) { var reg = RegistrationForDomain(domain); if (reg == null) { _log.Error("No registration found for domain {domain}", domain); - return; + return false; } if (reg.Fulldomain == null) { _log.Error("Registration for domain {domain} appears invalid", domain); - return; + return false; } if (!await VerifyCname(domain, reg.Fulldomain, 0)) { @@ -233,10 +234,12 @@ namespace PKISharp.WACS.Clients JsonConvert.SerializeObject(request), Encoding.UTF8, "application/json")); + return true; } catch (Exception ex) { _log.Error(ex, "Error sending update request to acme-dns server at {baseUri} for domain {domain}", _baseUri, domain); + return false; } } diff --git a/src/main.lib/Clients/DNS/LookupClientProvider.cs b/src/main.lib/Clients/DNS/LookupClientProvider.cs index 933897b..806fff7 100644 --- a/src/main.lib/Clients/DNS/LookupClientProvider.cs +++ b/src/main.lib/Clients/DNS/LookupClientProvider.cs @@ -121,14 +121,16 @@ namespace PKISharp.WACS.Clients.DNS public class DnsLookupResult { - public DnsLookupResult(string domain, IEnumerable<LookupClientWrapper> nameServers) + public DnsLookupResult(string domain, IEnumerable<LookupClientWrapper> nameServers, DnsLookupResult? cnameFrom = null) { Nameservers = nameServers; Domain = domain; + From = cnameFrom; } public IEnumerable<LookupClientWrapper> Nameservers { get; set; } public string Domain { get; set; } + public DnsLookupResult? From { get; set; } } /// <summary> @@ -137,7 +139,7 @@ namespace PKISharp.WACS.Clients.DNS /// <param name="domainName"></param> /// <param name="round"></param> /// <returns></returns> - public async Task<DnsLookupResult> GetAuthority(string domainName, int round = 0, bool followCnames = true) + public async Task<DnsLookupResult> GetAuthority(string domainName, int round = 0, bool followCnames = true, DnsLookupResult? from = null) { var key = domainName.ToLower().TrimEnd('.'); if (!_authoritativeNs.ContainsKey(key)) @@ -185,7 +187,7 @@ namespace PKISharp.WACS.Clients.DNS var cname = await client.GetCname(testZone); if (cname != null) { - return await GetAuthority(cname, round); + return await GetAuthority(cname, round, true, Produce(key, from)); } } @@ -212,7 +214,9 @@ namespace PKISharp.WACS.Clients.DNS _authoritativeNs.Add(key, _defaultNs); } } - return new DnsLookupResult(key, _authoritativeNs[key].Select(ip => Produce(ip))); + return Produce(key, from); } + + private DnsLookupResult Produce(string key, DnsLookupResult? parent = null) => new DnsLookupResult(key, _authoritativeNs[key].Select(ip => Produce(ip)), parent); } }
\ No newline at end of file diff --git a/src/main.lib/Clients/IIS/IISClient.cs b/src/main.lib/Clients/IIS/IISClient.cs index a0b82ee..6830086 100644 --- a/src/main.lib/Clients/IIS/IISClient.cs +++ b/src/main.lib/Clients/IIS/IISClient.cs @@ -201,10 +201,10 @@ namespace PKISharp.WACS.Clients.IIS public void AddBinding(IISSiteWrapper site, BindingOptions options) { var newBinding = site.Site.Bindings.CreateElement("binding"); - newBinding.Protocol = "https"; newBinding.BindingInformation = options.Binding; newBinding.CertificateStoreName = options.Store; newBinding.CertificateHash = options.Thumbprint; + newBinding.Protocol = "https"; if (options.Flags > 0) { newBinding.SetAttributeValue("sslFlags", options.Flags); @@ -223,10 +223,10 @@ namespace PKISharp.WACS.Clients.IIS "certificateHash" }; var replacement = site.Site.Bindings.CreateElement("binding"); - replacement.Protocol = existingBinding.Protocol; replacement.BindingInformation = existingBinding.BindingInformation; replacement.CertificateStoreName = options.Store; replacement.CertificateHash = options.Thumbprint; + replacement.Protocol = existingBinding.Protocol; foreach (var attr in existingBinding.Binding.Attributes) { try diff --git a/src/main.lib/Plugins/StorePlugins/CentralSsl/CentralSslOptionsFactory.cs b/src/main.lib/Plugins/StorePlugins/CentralSsl/CentralSslOptionsFactory.cs index 97a7e2d..97aaf95 100644 --- a/src/main.lib/Plugins/StorePlugins/CentralSsl/CentralSslOptionsFactory.cs +++ b/src/main.lib/Plugins/StorePlugins/CentralSsl/CentralSslOptionsFactory.cs @@ -43,7 +43,7 @@ namespace PKISharp.WACS.Plugins.StorePlugins } if (string.IsNullOrEmpty(password)) { - password = await input.ReadPassword("Password to use for the PFX files, or <ENTER> for none"); + password = await input.ReadPassword("Password to use for the .pfx files, or <Enter> for none"); } return Create(path, password, args?.KeepExisting ?? false); } diff --git a/src/main.lib/Plugins/StorePlugins/PfxFile/PfxFileOptionsFactory.cs b/src/main.lib/Plugins/StorePlugins/PfxFile/PfxFileOptionsFactory.cs index 53c3ede..8cc998e 100644 --- a/src/main.lib/Plugins/StorePlugins/PfxFile/PfxFileOptionsFactory.cs +++ b/src/main.lib/Plugins/StorePlugins/PfxFile/PfxFileOptionsFactory.cs @@ -43,7 +43,7 @@ namespace PKISharp.WACS.Plugins.StorePlugins } if (string.IsNullOrEmpty(password)) { - password = await input.ReadPassword("Password to use for the .pfx files or <ENTER> for none"); + password = await input.ReadPassword("Password to use for the .pfx files or <Enter> for none"); } return Create(path, password); } diff --git a/src/main.lib/Plugins/TargetPlugins/Csr/CsrOptionsFactory.cs b/src/main.lib/Plugins/TargetPlugins/Csr/CsrOptionsFactory.cs index 25b1e43..b631528 100644 --- a/src/main.lib/Plugins/TargetPlugins/Csr/CsrOptionsFactory.cs +++ b/src/main.lib/Plugins/TargetPlugins/Csr/CsrOptionsFactory.cs @@ -36,7 +36,7 @@ namespace PKISharp.WACS.Plugins.TargetPlugins { pkFile = await _arguments.TryGetArgument(args?.CsrFile, inputService, - "Enter the path to the corresponding private key, or <ENTER> to create a certificate without one"); + "Enter the path to the corresponding private key, or <Enter> to create a certificate without one"); } while (!(string.IsNullOrWhiteSpace(pkFile) || pkFile.ValidFile(_log))); diff --git a/src/main.lib/Plugins/TargetPlugins/IIS/IISOptionsFactory.cs b/src/main.lib/Plugins/TargetPlugins/IIS/IISOptionsFactory.cs index f382169..1ce1d1c 100644 --- a/src/main.lib/Plugins/TargetPlugins/IIS/IISOptionsFactory.cs +++ b/src/main.lib/Plugins/TargetPlugins/IIS/IISOptionsFactory.cs @@ -139,7 +139,7 @@ namespace PKISharp.WACS.Plugins.TargetPlugins description: $"{x.Name} ({x.Hosts.Count()} binding{(x.Hosts.Count() == 1 ? "" : "s")})", command: x.Id.ToString(), color: x.Https ? ConsoleColor.DarkGray : (ConsoleColor?)null))); - var raw = await input.RequestString("Site identifier(s) or <ENTER> to choose all"); + var raw = await input.RequestString("Site identifier(s) or <Enter> to choose all"); if (!ParseSiteOptions(raw, allSites, options)) { return null; diff --git a/src/main.lib/Plugins/ValidationPlugins/Dns/Acme/Acme.cs b/src/main.lib/Plugins/ValidationPlugins/Dns/Acme/Acme.cs index aa03b6e..ddcff59 100644 --- a/src/main.lib/Plugins/ValidationPlugins/Dns/Acme/Acme.cs +++ b/src/main.lib/Plugins/ValidationPlugins/Dns/Acme/Acme.cs @@ -34,10 +34,10 @@ namespace PKISharp.WACS.Plugins.ValidationPlugins.Dns /// </summary> /// <param name="recordName"></param> /// <param name="token"></param> - public override async Task CreateRecord(string recordName, string token) + public override async Task<bool> CreateRecord(string recordName, string token) { var client = new AcmeDnsClient(_dnsClient, _proxy, _log, _settings, _input, new Uri(_options.BaseUri)); - await client.Update(_identifier, token); + return await client.Update(_identifier, token); } public override Task DeleteRecord(string recordName, string token) => Task.CompletedTask; diff --git a/src/main.lib/Plugins/ValidationPlugins/Dns/DnsValidation.cs b/src/main.lib/Plugins/ValidationPlugins/Dns/DnsValidation.cs index 98c8b25..87e5273 100644 --- a/src/main.lib/Plugins/ValidationPlugins/Dns/DnsValidation.cs +++ b/src/main.lib/Plugins/ValidationPlugins/Dns/DnsValidation.cs @@ -6,6 +6,7 @@ using System.Collections.Generic; using System.Linq;
using System.Threading;
using System.Threading.Tasks;
+using static PKISharp.WACS.Clients.DNS.LookupClientProvider;
namespace PKISharp.WACS.Plugins.ValidationPlugins
{
@@ -17,7 +18,7 @@ namespace PKISharp.WACS.Plugins.ValidationPlugins protected readonly LookupClientProvider _dnsClient;
protected readonly ILogService _log;
protected readonly ISettingsService _settings;
- private string? _recordName;
+ private DnsLookupResult? _authority;
protected DnsValidation(
LookupClientProvider dnsClient,
@@ -32,29 +33,26 @@ namespace PKISharp.WACS.Plugins.ValidationPlugins public override async Task PrepareChallenge()
{
// Check for substitute domains
- if (_settings.Validation.AllowDnsSubstitution)
+ _authority = await _dnsClient.GetAuthority(
+ Challenge.DnsRecordName,
+ followCnames: _settings.Validation.AllowDnsSubstitution);
+
+ var success = false;
+ while (!success)
{
- try
+ success = await CreateRecord(_authority.Domain, Challenge.DnsRecordValue);
+ if (!success)
{
- // Resolve CNAME in DNS
- var result = await _dnsClient.GetAuthority(Challenge.DnsRecordName);
-
- // Substitute
- if (result.Domain != Challenge.DnsRecordName)
+ if (_authority.From == null)
{
- _log.Information("Detected that {DnsRecordName} is a CNAME that leads to {cname}", Challenge.DnsRecordName, result.Domain);
- _recordName = result.Domain;
+ throw new Exception("Unable to prepare for challenge answer");
+ }
+ else
+ {
+ _authority = _authority.From;
}
}
- catch (Exception ex)
- {
- _log.Debug("Error checking for substitute domains: {ex}", ex.Message);
- }
- }
-
- // Create record
- await CreateRecord(_recordName ?? Challenge.DnsRecordName, Challenge.DnsRecordValue);
- _log.Information("Answer should now be available at {answerUri}", _recordName ?? Challenge.DnsRecordName);
+ }
// Verify that the record was created succesfully and wait for possible
// propagation/caching/TTL issues to resolve themselves naturally
@@ -63,7 +61,7 @@ namespace PKISharp.WACS.Plugins.ValidationPlugins var retrySeconds = _settings.Validation.PreValidateDnsRetryInterval;
while (_settings.Validation.PreValidateDns)
{
- if (await PreValidate(retry))
+ if (await PreValidate())
{
break;
}
@@ -84,23 +82,19 @@ namespace PKISharp.WACS.Plugins.ValidationPlugins }
}
- protected async Task<bool> PreValidate(int attempt)
+ protected async Task<bool> PreValidate()
{
try
{
- var actualDomain = _recordName ?? Challenge.DnsRecordName;
- var authority = await _dnsClient.GetAuthority(actualDomain, attempt, true);
- // This should not be possible because authority was supposed to be
- // checked recursively in the PrepareChallenge phase
- if (authority.Domain != actualDomain)
+ if (_authority == null)
{
- _log.Error("Unexpected authority");
+ throw new InvalidOperationException("_recordName is null");
}
- _log.Debug("Looking for TXT value {DnsRecordValue}...", actualDomain);
- foreach (var client in authority.Nameservers)
+ _log.Debug("Looking for TXT value {DnsRecordValue}...", _authority.Domain);
+ foreach (var client in _authority.Nameservers)
{
_log.Debug("Preliminary validation asking {ip}...", client.IpAddress);
- var answers = await client.GetTxtRecords(Challenge.DnsRecordName);
+ var answers = await client.GetTxtRecords(_authority.Domain);
if (!answers.Any())
{
_log.Warning("Preliminary validation failed: no TXT records found");
@@ -129,9 +123,16 @@ namespace PKISharp.WACS.Plugins.ValidationPlugins /// </summary>
public override async Task CleanUp()
{
- if (HasChallenge)
+ if (HasChallenge && _authority != null)
{
- await DeleteRecord(_recordName ?? Challenge.DnsRecordName, Challenge.DnsRecordValue);;
+ try
+ {
+ await DeleteRecord(_authority.Domain, Challenge.DnsRecordValue);
+ }
+ catch (Exception ex)
+ {
+ _log.Warning($"Error deleting record: {ex.Message}");
+ }
}
}
@@ -146,7 +147,7 @@ namespace PKISharp.WACS.Plugins.ValidationPlugins /// </summary>
/// <param name="recordName">Name of the record</param>
/// <param name="token">Contents of the record</param>
- public abstract Task CreateRecord(string recordName, string token);
+ public abstract Task<bool> CreateRecord(string recordName, string token);
/// <summary>
/// Match DNS zone to use from a list of all zones
diff --git a/src/main.lib/Plugins/ValidationPlugins/Dns/Manual/Manual.cs b/src/main.lib/Plugins/ValidationPlugins/Dns/Manual/Manual.cs index e112ed1..c584efb 100644 --- a/src/main.lib/Plugins/ValidationPlugins/Dns/Manual/Manual.cs +++ b/src/main.lib/Plugins/ValidationPlugins/Dns/Manual/Manual.cs @@ -25,7 +25,7 @@ namespace PKISharp.WACS.Plugins.ValidationPlugins.Dns _identifier = identifier; } - public override async Task CreateRecord(string recordName, string token) + public override async Task<bool> CreateRecord(string recordName, string token) { _input.CreateSpace(); _input.Show("Domain", _identifier); @@ -33,14 +33,18 @@ namespace PKISharp.WACS.Plugins.ValidationPlugins.Dns _input.Show("Type", "TXT"); _input.Show("Content", $"\"{token}\""); _input.Show("Note", "Some DNS managers add quotes automatically. A single set is needed."); - await _input.Wait("Please press <Enter> after you've created and verified the record"); + if (!await _input.Wait("Please press <Enter> after you've created and verified the record")) + { + _log.Warning("User aborted"); + return false; + } // Pre-pre-validate, allowing the manual user to correct mistakes while (true) { - if (await PreValidate(0)) + if (await PreValidate()) { - break; + return true; } else { @@ -51,7 +55,7 @@ namespace PKISharp.WACS.Plugins.ValidationPlugins.Dns "try ACME validation anyway.", true); if (!retry) { - break; + return false; } } } diff --git a/src/main.lib/Plugins/ValidationPlugins/Dns/Script/Script.cs b/src/main.lib/Plugins/ValidationPlugins/Dns/Script/Script.cs index 6b7b34b..80ece5e 100644 --- a/src/main.lib/Plugins/ValidationPlugins/Dns/Script/Script.cs +++ b/src/main.lib/Plugins/ValidationPlugins/Dns/Script/Script.cs @@ -28,7 +28,7 @@ namespace PKISharp.WACS.Plugins.ValidationPlugins.Dns _scriptClient = client; } - public override async Task CreateRecord(string recordName, string token) + public override async Task<bool> CreateRecord(string recordName, string token) { var script = _options.Script ?? _options.CreateScript; if (!string.IsNullOrWhiteSpace(script)) @@ -39,10 +39,12 @@ namespace PKISharp.WACS.Plugins.ValidationPlugins.Dns args = _options.CreateScriptArguments; } await _scriptClient.RunScript(script, ProcessArguments(recordName, token, args, script.EndsWith(".ps1"))); + return true; } else { _log.Error("No create script configured"); + return false; } } diff --git a/src/main.lib/RenewalCreator.cs b/src/main.lib/RenewalCreator.cs index 823265d..404ee76 100644 --- a/src/main.lib/RenewalCreator.cs +++ b/src/main.lib/RenewalCreator.cs @@ -158,7 +158,7 @@ namespace PKISharp.WACS } else if (runLevel.HasFlag(RunLevel.Advanced | RunLevel.Interactive)) { - var alt = await _input.RequestString($"Suggested friendly name '{initialTarget.FriendlyName}', press <ENTER> to accept or type an alternative"); + var alt = await _input.RequestString($"Suggested friendly name '{initialTarget.FriendlyName}', press <Enter> to accept or type an alternative"); if (!string.IsNullOrEmpty(alt)) { tempRenewal.FriendlyName = alt; diff --git a/src/main.lib/Wacs.cs b/src/main.lib/Wacs.cs index d267b4c..be8faf9 100644 --- a/src/main.lib/Wacs.cs +++ b/src/main.lib/Wacs.cs @@ -235,7 +235,7 @@ namespace PKISharp.WACS.Host { var total = _renewalStore.Renewals.Count(); var due = _renewalStore.Renewals.Count(x => x.IsDue()); - var error = _renewalStore.Renewals.Count(x => !x.History.Last().Success); + var error = _renewalStore.Renewals.Count(x => !x.History.LastOrDefault()?.Success ?? false); var (allowIIS, allowIISReason) = _userRoleService.AllowIIS; var options = new List<Choice<Func<Task>>> { diff --git a/src/plugin.validation.dns.azure/Azure.cs b/src/plugin.validation.dns.azure/Azure.cs index cfaf575..2d8c1e0 100755 --- a/src/plugin.validation.dns.azure/Azure.cs +++ b/src/plugin.validation.dns.azure/Azure.cs @@ -33,11 +33,14 @@ namespace PKISharp.WACS.Plugins.ValidationPlugins.Dns _proxyService = proxyService; } - public override async Task CreateRecord(string recordName, string token) + public override async Task<bool> CreateRecord(string recordName, string token) { var client = await GetClient(); var zone = await GetHostedZone(recordName); - var subDomain = recordName.Substring(0, recordName.LastIndexOf(zone)).TrimEnd('.'); + if (zone == null) + { + return false; + } // Create record set parameters var recordSetParams = new RecordSet @@ -49,11 +52,20 @@ namespace PKISharp.WACS.Plugins.ValidationPlugins.Dns } }; - _ = await client.RecordSets.CreateOrUpdateAsync(_options.ResourceGroupName, - zone, - subDomain, - RecordType.TXT, - recordSetParams); + try + { + _ = await client.RecordSets.CreateOrUpdateAsync(_options.ResourceGroupName, + zone, + RelativeRecordName(zone, recordName), + RecordType.TXT, + recordSetParams); + } + catch (Exception ex) + { + _log.Error(ex, "Error updating record in Azure"); + return false; + } + return true; } private async Task<DnsManagementClient> GetClient() @@ -85,6 +97,12 @@ namespace PKISharp.WACS.Plugins.ValidationPlugins.Dns } return _azureDnsClient; } + private string RelativeRecordName(string zone, string recordName) + { + var ret = recordName.Substring(0, recordName.LastIndexOf(zone)).TrimEnd('.'); + return string.IsNullOrEmpty(ret) ? "@" : ret; + } + private async Task<string> GetHostedZone(string recordName) { @@ -107,19 +125,25 @@ namespace PKISharp.WACS.Plugins.ValidationPlugins.Dns "Can't find hosted zone for {recordName} in resource group {ResourceGroupName}", recordName, _options.ResourceGroupName); - throw new Exception(); + return null; } public override async Task DeleteRecord(string recordName, string token) { var client = await GetClient(); var zone = await GetHostedZone(recordName); - var subDomain = recordName.Substring(0, recordName.LastIndexOf(zone)).TrimEnd('.'); - await client.RecordSets.DeleteAsync( - _options.ResourceGroupName, - zone, - subDomain, - RecordType.TXT); + try + { + await client.RecordSets.DeleteAsync( + _options.ResourceGroupName, + zone, + RelativeRecordName(zone, recordName), + RecordType.TXT); + } + catch (Exception ex) + { + _log.Error(ex, "Error deleting record from Azure"); + } } } } diff --git a/src/plugin.validation.dns.cloudflare/Cloudflare.cs b/src/plugin.validation.dns.cloudflare/Cloudflare.cs index 380629b..e770735 100644 --- a/src/plugin.validation.dns.cloudflare/Cloudflare.cs +++ b/src/plugin.validation.dns.cloudflare/Cloudflare.cs @@ -54,22 +54,24 @@ namespace PKISharp.WACS.Plugins.ValidationPlugins.Dns return zonesResp.Unpack().First(); } - public override async Task CreateRecord(string recordName, string token) + public override async Task<bool> CreateRecord(string recordName, string token) { var ctx = GetContext(); var zone = await GetHostedZone(ctx, recordName).ConfigureAwait(false); if (zone == null) { - throw new InvalidOperationException($"The zone could not be found using the Cloudflare API, thus creating a DNS validation record is impossible. " + + _log.Error("The zone could not be found using the Cloudflare API, thus creating a DNS validation record is impossible. " + $"Please note you need to use an API Token, not the Global API Key. The token needs the permissions Zone.Zone:Read and Zone.DNS:Edit. Regarding " + $"Zone:Read it is important, that this token has access to all zones in your account (Zone Resources > Include > All zones) because we need to " + $"list your zones. Read the docs carefully for instructions."); + return false; } var dns = ctx.Zone(zone).Dns; _ = await dns.Create(DnsRecordType.TXT, recordName, token) .CallAsync(_hc) .ConfigureAwait(false); + return true; } private async Task DeleteRecord(string recordName, string token, IAuthorizedSyntax context, Zone zone) @@ -86,12 +88,21 @@ namespace PKISharp.WACS.Plugins.ValidationPlugins.Dns var record = records.FirstOrDefault(); if (record == null) { - throw new Exception($"The record {recordName} that should be deleted does not exist at Cloudflare."); + _log.Warning($"The record {recordName} that should be deleted does not exist at Cloudflare."); + return; + } + + try + { + _ = await dns.Delete(record.Id) + .CallAsync(_hc) + .ConfigureAwait(false); + } + catch (Exception ex) + { + _log.Warning($"Unable to delete record from Cloudflare: {ex.Message}"); } - _ = await dns.Delete(record.Id) - .CallAsync(_hc) - .ConfigureAwait(false); } public override async Task DeleteRecord(string recordName, string token) diff --git a/src/plugin.validation.dns.dreamhost/DreamhostDnsValidation.cs b/src/plugin.validation.dns.dreamhost/DreamhostDnsValidation.cs index 8c971b5..2e6e5db 100644 --- a/src/plugin.validation.dns.dreamhost/DreamhostDnsValidation.cs +++ b/src/plugin.validation.dns.dreamhost/DreamhostDnsValidation.cs @@ -1,6 +1,7 @@ using PKISharp.WACS.Clients.DNS; using PKISharp.WACS.Plugins.ValidationPlugins.Dreamhost; using PKISharp.WACS.Services; +using System; using System.Threading.Tasks; namespace PKISharp.WACS.Plugins.ValidationPlugins @@ -17,8 +18,29 @@ namespace PKISharp.WACS.Plugins.ValidationPlugins : base(dnsClient, logService, settings) => _client = new DnsManagementClient(options.ApiKey.Value, logService); - public override Task CreateRecord(string recordName, string token) => _client.CreateRecord(recordName, RecordType.TXT, token); + public override async Task<bool> CreateRecord(string recordName, string token) + { + try + { + await _client.CreateRecord(recordName, RecordType.TXT, token); + return true; + } + catch + { + return false; + } + } - public override Task DeleteRecord(string recordName, string token) => _client.DeleteRecord(recordName, RecordType.TXT, token); + public override async Task DeleteRecord(string recordName, string token) + { + try + { + await _client.DeleteRecord(recordName, RecordType.TXT, token); + } + catch (Exception ex) + { + _log.Warning($"Unable to delete record from Dreamhost: {ex.Message}"); + } + } } } diff --git a/src/plugin.validation.dns.luadns/luadns.cs b/src/plugin.validation.dns.luadns/luadns.cs index f7c90d4..4935681 100644 --- a/src/plugin.validation.dns.luadns/luadns.cs +++ b/src/plugin.validation.dns.luadns/luadns.cs @@ -64,7 +64,7 @@ namespace PKISharp.WACS.Plugins.ValidationPlugins.Dns _apiKey = options.APIKey.Value; } - public override async Task CreateRecord(string recordName, string token) + public override async Task<bool> CreateRecord(string recordName, string token) { _log.Information("Creating LuaDNS verification record"); @@ -72,8 +72,8 @@ namespace PKISharp.WACS.Plugins.ValidationPlugins.Dns var response = await client.GetAsync(new Uri(_LuaDnsApiEndpoint, "zones")); if (!response.IsSuccessStatusCode) { - _log.Information("Failed to get DNS zones list for account. Aborting."); - return; + _log.Error("Failed to get DNS zones list for account. Aborting."); + return false; } var payload = await response.Content.ReadAsStringAsync(); @@ -81,8 +81,8 @@ namespace PKISharp.WACS.Plugins.ValidationPlugins.Dns var targetZone = FindBestMatch(zones.ToDictionary(x => x.Name), recordName); if (targetZone == null) { - _log.Information("No matching zone found in LuaDNS account. Aborting"); - return; + _log.Error("No matching zone found in LuaDNS account. Aborting"); + return false; } var newRecord = new RecordData { Name = $"{recordName}.", Type = "TXT", Content = token, TTL = 300 }; @@ -91,24 +91,21 @@ namespace PKISharp.WACS.Plugins.ValidationPlugins.Dns response = await client.PostAsync(new Uri(_LuaDnsApiEndpoint, $"zones/{targetZone.Id}/records"), new StringContent(payload, Encoding.UTF8, "application/json")); if (!response.IsSuccessStatusCode) { - _log.Information("Failed to create DNS verification record"); - return; + _log.Error("Failed to create DNS verification record"); + return false; } payload = await response.Content.ReadAsStringAsync(); newRecord = JsonSerializer.Deserialize<RecordData>(payload); - _recordsMap[recordName] = newRecord; - - _log.Information("DNS Record created. Waiting 30 seconds to allow propagation."); - await Task.Delay(30000); + return true; } public override async Task DeleteRecord(string recordName, string token) { if (!_recordsMap.ContainsKey(recordName)) { - _log.Information($"No record with name {recordName} was created"); + _log.Warning($"No record with name {recordName} was created"); return; } @@ -118,7 +115,7 @@ namespace PKISharp.WACS.Plugins.ValidationPlugins.Dns var response = await client.DeleteAsync(new Uri(_LuaDnsApiEndpoint, $"zones/{_recordsMap[recordName].ZoneId}/records/{_recordsMap[recordName].Id}")); if (!response.IsSuccessStatusCode) { - _log.Information("Failed to delete DNS verification record"); + _log.Warning("Failed to delete DNS verification record"); return; } diff --git a/src/plugin.validation.dns.route53/Route53.cs b/src/plugin.validation.dns.route53/Route53.cs index 2db2129..a2d490c 100644 --- a/src/plugin.validation.dns.route53/Route53.cs +++ b/src/plugin.validation.dns.route53/Route53.cs @@ -48,19 +48,32 @@ namespace PKISharp.WACS.Plugins.ValidationPlugins.Dns }; } - public override async Task CreateRecord(string recordName, string token) + public override async Task<bool> CreateRecord(string recordName, string token) { - var hostedZoneId = await GetHostedZoneId(recordName); - _log.Information("Creating TXT record {recordName} with value {token}", recordName, token); - var response = await _route53Client.ChangeResourceRecordSetsAsync( - new ChangeResourceRecordSetsRequest( - hostedZoneId, - new ChangeBatch(new List<Change> { + try + { + var hostedZoneId = await GetHostedZoneId(recordName); + if (hostedZoneId == null) + { + return false; + } + _log.Information("Creating TXT record {recordName} with value {token}", recordName, token); + var response = await _route53Client.ChangeResourceRecordSetsAsync( + new ChangeResourceRecordSetsRequest( + hostedZoneId, + new ChangeBatch(new List<Change> { new Change( ChangeAction.UPSERT, CreateResourceRecordSet(recordName, token)) - }))); - await WaitChangesPropagation(response.ChangeInfo); + }))); + await WaitChangesPropagation(response.ChangeInfo); + return true; + } + catch (Exception ex) + { + _log.Warning($"Error creating TXT record: {ex.Message}"); + return false; + } } public override async Task DeleteRecord(string recordName, string token) @@ -70,9 +83,9 @@ namespace PKISharp.WACS.Plugins.ValidationPlugins.Dns _ = await _route53Client.ChangeResourceRecordSetsAsync( new ChangeResourceRecordSetsRequest(hostedZoneId, new ChangeBatch(new List<Change> { - new Change( - ChangeAction.DELETE, - CreateResourceRecordSet(recordName, token)) + new Change( + ChangeAction.DELETE, + CreateResourceRecordSet(recordName, token)) }))); } @@ -97,7 +110,7 @@ namespace PKISharp.WACS.Plugins.ValidationPlugins.Dns return hostedZone.Id; } _log.Error($"Can't find hosted zone for domain {recordName}"); - throw new Exception(); + return null; } private async Task WaitChangesPropagation(ChangeInfo changeInfo) @@ -113,7 +126,7 @@ namespace PKISharp.WACS.Plugins.ValidationPlugins.Dns while ((await _route53Client.GetChangeAsync(changeRequest)).ChangeInfo.Status == ChangeStatus.PENDING) { - await Task.Delay(5000); + await Task.Delay(2000); } } } |