summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWouter Tinus <wouter.tinus@gmail.com>2020-06-17 20:01:43 +0200
committerWouter Tinus <wouter.tinus@gmail.com>2020-06-17 20:01:43 +0200
commit8edfefc8fe0ce3c145a7370df9fa26ce7e167bca (patch)
treef0853c8a010d19b7a86ba73b0d6c78150401552b
parentf9d62aba18af98ac7758918b0d0e712f195bff8e (diff)
downloadletsencrypt-win-simple-8edfefc8fe0ce3c145a7370df9fa26ce7e167bca.zip
letsencrypt-win-simple-8edfefc8fe0ce3c145a7370df9fa26ce7e167bca.tar.gz
letsencrypt-win-simple-8edfefc8fe0ce3c145a7370df9fa26ce7e167bca.tar.bz2
make HttpValidation support parallel validation
-rw-r--r--src/main.lib/Plugins/ValidationPlugins/Http/FileSystem/FileSystem.cs13
-rw-r--r--src/main.lib/Plugins/ValidationPlugins/Http/Ftp/Ftp.cs9
-rw-r--r--src/main.lib/Plugins/ValidationPlugins/Http/HttpValidation.cs136
-rw-r--r--src/main.lib/Plugins/ValidationPlugins/Http/Sftp/Sftp.cs9
-rw-r--r--src/main.lib/Plugins/ValidationPlugins/Http/WebDav/WebDav.cs8
-rw-r--r--src/main.lib/RenewalCreator.cs2
6 files changed, 78 insertions, 99 deletions
diff --git a/src/main.lib/Plugins/ValidationPlugins/Http/FileSystem/FileSystem.cs b/src/main.lib/Plugins/ValidationPlugins/Http/FileSystem/FileSystem.cs
index ff23950..8dfccb4 100644
--- a/src/main.lib/Plugins/ValidationPlugins/Http/FileSystem/FileSystem.cs
+++ b/src/main.lib/Plugins/ValidationPlugins/Http/FileSystem/FileSystem.cs
@@ -3,6 +3,7 @@ using PKISharp.WACS.DomainObjects;
using System;
using System.IO;
using System.Linq;
+using System.Threading.Tasks;
namespace PKISharp.WACS.Plugins.ValidationPlugins.Http
{
@@ -12,7 +13,7 @@ namespace PKISharp.WACS.Plugins.ValidationPlugins.Http
public FileSystem(FileSystemOptions options, IIISClient iisClient, RunLevel runLevel, HttpValidationParameters pars) : base(options, runLevel, pars) => _iisClient = iisClient;
- protected override void DeleteFile(string path)
+ protected override Task DeleteFile(string path)
{
var fi = new FileInfo(path);
if (fi.Exists)
@@ -24,9 +25,10 @@ namespace PKISharp.WACS.Plugins.ValidationPlugins.Http
{
_log.Warning("File {path} already deleted", path);
}
+ return Task.CompletedTask;
}
- protected override void DeleteFolder(string path)
+ protected override Task DeleteFolder(string path)
{
var di = new DirectoryInfo(path);
if (di.Exists)
@@ -38,11 +40,12 @@ namespace PKISharp.WACS.Plugins.ValidationPlugins.Http
{
_log.Warning("Folder {path} already deleted", path);
}
+ return Task.CompletedTask;
}
- protected override bool IsEmpty(string path) => !new DirectoryInfo(path).EnumerateFileSystemInfos().Any();
+ protected override Task<bool> IsEmpty(string path) => Task.FromResult(!new DirectoryInfo(path).EnumerateFileSystemInfos().Any());
- protected override void WriteFile(string path, string content)
+ protected override async Task WriteFile(string path, string content)
{
var fi = new FileInfo(path);
if (!fi.Directory.Exists)
@@ -50,7 +53,7 @@ namespace PKISharp.WACS.Plugins.ValidationPlugins.Http
fi.Directory.Create();
}
_log.Verbose("Writing file to {path}", path);
- File.WriteAllText(path, content);
+ await File.WriteAllTextAsync(path, content);
}
/// <summary>
diff --git a/src/main.lib/Plugins/ValidationPlugins/Http/Ftp/Ftp.cs b/src/main.lib/Plugins/ValidationPlugins/Http/Ftp/Ftp.cs
index 1084b07..c9aa07e 100644
--- a/src/main.lib/Plugins/ValidationPlugins/Http/Ftp/Ftp.cs
+++ b/src/main.lib/Plugins/ValidationPlugins/Http/Ftp/Ftp.cs
@@ -1,5 +1,6 @@
using PKISharp.WACS.Clients;
using System.Linq;
+using System.Threading.Tasks;
namespace PKISharp.WACS.Plugins.ValidationPlugins.Http
{
@@ -11,12 +12,12 @@ namespace PKISharp.WACS.Plugins.ValidationPlugins.Http
protected override char PathSeparator => '/';
- protected override void DeleteFile(string path) => _ftpClient.Delete(path, FtpClient.FileType.File);
+ protected override async Task DeleteFile(string path) => _ftpClient.Delete(path, FtpClient.FileType.File);
- protected override void DeleteFolder(string path) => _ftpClient.Delete(path, FtpClient.FileType.Directory);
+ protected override async Task DeleteFolder(string path) => _ftpClient.Delete(path, FtpClient.FileType.Directory);
- protected override bool IsEmpty(string path) => !_ftpClient.GetFiles(path).Any();
+ protected override async Task<bool> IsEmpty(string path) => !_ftpClient.GetFiles(path).Any();
- protected override void WriteFile(string path, string content) => _ftpClient.Upload(path, content);
+ protected override async Task WriteFile(string path, string content) => _ftpClient.Upload(path, content);
}
}
diff --git a/src/main.lib/Plugins/ValidationPlugins/Http/HttpValidation.cs b/src/main.lib/Plugins/ValidationPlugins/Http/HttpValidation.cs
index 6c2c48b..768fcce 100644
--- a/src/main.lib/Plugins/ValidationPlugins/Http/HttpValidation.cs
+++ b/src/main.lib/Plugins/ValidationPlugins/Http/HttpValidation.cs
@@ -4,6 +4,7 @@ using PKISharp.WACS.DomainObjects;
using PKISharp.WACS.Plugins.Interfaces;
using PKISharp.WACS.Services;
using System;
+using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
@@ -20,10 +21,7 @@ namespace PKISharp.WACS.Plugins.ValidationPlugins
where TOptions : HttpValidationOptions<TPlugin>
where TPlugin : IValidationPlugin
{
-
- private bool _webConfigWritten = false;
- private bool _challengeWritten = false;
- private Http01ChallengeValidationDetails? _challenge = null;
+ private readonly List<string> _filesWritten = new List<string>();
protected TOptions _options;
protected ILogService _log;
@@ -32,6 +30,10 @@ namespace PKISharp.WACS.Plugins.ValidationPlugins
protected Renewal _renewal;
protected RunLevel _runLevel;
+ /// <summary>
+ /// Multiple http-01 validation challenges can be answered at the same time
+ /// </summary>
+ public override ParallelOperations Parallelism => ParallelOperations.Answer;
/// <summary>
/// Path used for the current renewal, may not be same as _options.Path
@@ -160,9 +162,12 @@ namespace PKISharp.WACS.Plugins.ValidationPlugins
{
throw new InvalidOperationException();
}
- WriteFile(CombinePath(_path, challenge.HttpResourcePath), challenge.HttpResourceValue);
- _challengeWritten = true;
- _challenge = challenge;
+ var path = CombinePath(_path, challenge.HttpResourcePath);
+ WriteFile(path, challenge.HttpResourceValue);
+ if (!_filesWritten.Contains(path))
+ {
+ _filesWritten.Add(path);
+ }
}
/// <summary>
@@ -181,12 +186,15 @@ namespace PKISharp.WACS.Plugins.ValidationPlugins
{
try
{
- _log.Debug("Writing web.config");
var partialPath = challenge.HttpResourcePath.Split('/').Last();
var destination = CombinePath(_path, challenge.HttpResourcePath.Replace(partialPath, "web.config"));
- var content = GetWebConfig();
- WriteFile(destination, content);
- _webConfigWritten = true;
+ if (!_filesWritten.Contains(destination))
+ {
+ _log.Debug("Writing web.config");
+ var content = GetWebConfig();
+ WriteFile(destination, content);
+ _filesWritten.Add(destination);
+ }
}
catch (Exception ex)
{
@@ -202,65 +210,6 @@ namespace PKISharp.WACS.Plugins.ValidationPlugins
private string GetWebConfig() => File.ReadAllText(TemplateWebConfig);
/// <summary>
- /// Can be used to write out server specific configuration, to handle extensionless files etc.
- /// </summary>
- /// <param name="target"></param>
- /// <param name="answerPath"></param>
- /// <param name="token"></param>
- private void DeleteWebConfig()
- {
- if (_path == null)
- {
- throw new InvalidOperationException();
- }
- if (_webConfigWritten && _challenge != null)
- {
- _log.Debug("Deleting web.config");
- var partialPath = _challenge.HttpResourcePath.Split('/').Last();
- var destination = CombinePath(_path, _challenge.HttpResourcePath.Replace(partialPath, "web.config"));
- DeleteFile(destination);
- }
- }
-
- /// <summary>
- /// Should delete any authorizations
- /// </summary>
- /// <param name="answerPath">where the answerFile should be located</param>
- /// <param name="token">the token</param>
- /// <param name="webRootPath">the website root path</param>
- /// <param name="filePath">the file path for the authorization file</param>
- private void DeleteAuthorization()
- {
- try
- {
- if (_path != null && _challengeWritten && _challenge != null)
- {
- _log.Debug("Deleting answer");
- var path = CombinePath(_path, _challenge.HttpResourcePath);
- var partialPath = _challenge.HttpResourcePath.Split('/').Last();
- DeleteFile(path);
- if (_settings.Validation.CleanupFolders)
- {
- path = path.Replace($"{PathSeparator}{partialPath}", "");
- if (DeleteFolderIfEmpty(path))
- {
- var idx = path.LastIndexOf(PathSeparator);
- if (idx >= 0)
- {
- path = path.Substring(0, path.LastIndexOf(PathSeparator));
- DeleteFolderIfEmpty(path);
- }
- }
- }
- }
- }
- catch (Exception ex)
- {
- _log.Warning("Error occured while deleting folder structure. Error: {@ex}", ex);
- }
- }
-
- /// <summary>
/// Combine root path with relative path
/// </summary>
/// <param name="root"></param>
@@ -279,11 +228,11 @@ namespace PKISharp.WACS.Plugins.ValidationPlugins
/// </summary>
/// <param name="path"></param>
/// <returns></returns>
- private bool DeleteFolderIfEmpty(string path)
+ private async Task<bool> DeleteFolderIfEmpty(string path)
{
- if (IsEmpty(path))
+ if (await IsEmpty(path))
{
- DeleteFolder(path);
+ await DeleteFolder(path);
return true;
}
else
@@ -299,28 +248,28 @@ namespace PKISharp.WACS.Plugins.ValidationPlugins
/// <param name="root"></param>
/// <param name="path"></param>
/// <param name="content"></param>
- protected abstract void WriteFile(string path, string content);
+ protected abstract Task WriteFile(string path, string content);
/// <summary>
/// Delete file from specific location
/// </summary>
/// <param name="root"></param>
/// <param name="path"></param>
- protected abstract void DeleteFile(string path);
+ protected abstract Task DeleteFile(string path);
/// <summary>
/// Check if folder is empty
/// </summary>
/// <param name="root"></param>
/// <param name="path"></param>
- protected abstract bool IsEmpty(string path);
+ protected abstract Task<bool> IsEmpty(string path);
/// <summary>
/// Delete folder if not empty
/// </summary>
/// <param name="root"></param>
/// <param name="path"></param>
- protected abstract void DeleteFolder(string path);
+ protected abstract Task DeleteFolder(string path);
/// <summary>
/// Refresh
@@ -332,11 +281,36 @@ namespace PKISharp.WACS.Plugins.ValidationPlugins
/// <summary>
/// Dispose
/// </summary>
- public override Task CleanUp()
+ public override async Task CleanUp()
{
- DeleteWebConfig();
- DeleteAuthorization();
- return Task.CompletedTask;
+ try
+ {
+ if (_path != null)
+ {
+ foreach (var file in _filesWritten)
+ {
+ _log.Debug("Deleting answer");
+ await DeleteFile(file);
+ if (_settings.Validation.CleanupFolders)
+ {
+ var folder = file.Substring(0, file.LastIndexOf(PathSeparator));
+ if (await DeleteFolderIfEmpty(folder))
+ {
+ var idx = file.LastIndexOf(PathSeparator);
+ if (idx >= 0)
+ {
+ folder = folder.Substring(0, folder.LastIndexOf(PathSeparator));
+ await DeleteFolderIfEmpty(folder);
+ }
+ }
+ }
+ }
+ }
+ }
+ catch (Exception ex)
+ {
+ _log.Warning("Error occured while deleting folder structure. Error: {@ex}", ex);
+ }
}
}
}
diff --git a/src/main.lib/Plugins/ValidationPlugins/Http/Sftp/Sftp.cs b/src/main.lib/Plugins/ValidationPlugins/Http/Sftp/Sftp.cs
index c3d5c08..a7a88ee 100644
--- a/src/main.lib/Plugins/ValidationPlugins/Http/Sftp/Sftp.cs
+++ b/src/main.lib/Plugins/ValidationPlugins/Http/Sftp/Sftp.cs
@@ -1,5 +1,6 @@
using PKISharp.WACS.Clients;
using System.Linq;
+using System.Threading.Tasks;
namespace PKISharp.WACS.Plugins.ValidationPlugins.Http
{
@@ -11,12 +12,12 @@ namespace PKISharp.WACS.Plugins.ValidationPlugins.Http
protected override char PathSeparator => '/';
- protected override void DeleteFile(string path) => _sshFtpClient.Delete(path, SshFtpClient.FileType.File);
+ protected override async Task DeleteFile(string path) => _sshFtpClient.Delete(path, SshFtpClient.FileType.File);
- protected override void DeleteFolder(string path) => _sshFtpClient.Delete(path, SshFtpClient.FileType.Directory);
+ protected override async Task DeleteFolder(string path) => _sshFtpClient.Delete(path, SshFtpClient.FileType.Directory);
- protected override bool IsEmpty(string path) => !_sshFtpClient.GetFiles(path).Any();
+ protected override async Task<bool> IsEmpty(string path) => !_sshFtpClient.GetFiles(path).Any();
- protected override void WriteFile(string path, string content) => _sshFtpClient.Upload(path, content);
+ protected override async Task WriteFile(string path, string content) => _sshFtpClient.Upload(path, content);
}
}
diff --git a/src/main.lib/Plugins/ValidationPlugins/Http/WebDav/WebDav.cs b/src/main.lib/Plugins/ValidationPlugins/Http/WebDav/WebDav.cs
index c34149d..f1adaea 100644
--- a/src/main.lib/Plugins/ValidationPlugins/Http/WebDav/WebDav.cs
+++ b/src/main.lib/Plugins/ValidationPlugins/Http/WebDav/WebDav.cs
@@ -15,15 +15,15 @@ namespace PKISharp.WACS.Plugins.ValidationPlugins.Http
RunLevel runLevel, ProxyService proxy) :
base(options, runLevel, pars) => _webdavClient = new WebDavClientWrapper(_options.Credential, pars.LogService, proxy);
- protected override void DeleteFile(string path) => _webdavClient.Delete(path);
+ protected override async Task DeleteFile(string path) => _webdavClient.Delete(path);
- protected override void DeleteFolder(string path) => _webdavClient.Delete(path);
+ protected override async Task DeleteFolder(string path) => _webdavClient.Delete(path);
- protected override bool IsEmpty(string path) => !_webdavClient.IsEmpty(path);
+ protected override async Task<bool> IsEmpty(string path) => !_webdavClient.IsEmpty(path);
protected override char PathSeparator => '/';
- protected override void WriteFile(string path, string content) => _webdavClient.Upload(path, content);
+ protected override async Task WriteFile(string path, string content) => _webdavClient.Upload(path, content);
public override Task CleanUp()
{
base.CleanUp();
diff --git a/src/main.lib/RenewalCreator.cs b/src/main.lib/RenewalCreator.cs
index 4a198db..0210ca2 100644
--- a/src/main.lib/RenewalCreator.cs
+++ b/src/main.lib/RenewalCreator.cs
@@ -363,7 +363,7 @@ namespace PKISharp.WACS
{
goto retry;
}
- _exceptionHandler.HandleException(message: $"Create certificate failed: {string.Join(", ", result.ErrorMessages)}");
+ _exceptionHandler.HandleException(message: $"Create certificate failed: {string.Join("\n\t- ", result.ErrorMessages)}");
}
else
{