summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/main.lib/Plugins/Base/OptionsFactories/ValidationPluginOptionsFactory.cs1
-rw-r--r--src/main.lib/Plugins/Resolvers/InteractiveResolver.cs75
-rw-r--r--src/main.lib/Plugins/Resolvers/UnattendedResolver.cs273
-rw-r--r--src/main.lib/Services/ArgumentsParser.cs4
-rw-r--r--src/main.lib/Services/AutofacBuilder.cs2
-rw-r--r--src/main.lib/Services/Interfaces/IPluginService.cs20
-rw-r--r--src/main.lib/Services/PluginService.cs121
-rw-r--r--src/main.lib/Services/SettingsService.cs2
-rw-r--r--src/main.test/Mock/Clients/IISClient.cs2
-rw-r--r--src/main.test/Tests/BindingTests/Bindings.cs20
-rw-r--r--src/main.test/Tests/InstallationPluginTests/MultipleInstallerTests.cs23
-rw-r--r--src/main/settings.json2
12 files changed, 248 insertions, 297 deletions
diff --git a/src/main.lib/Plugins/Base/OptionsFactories/ValidationPluginOptionsFactory.cs b/src/main.lib/Plugins/Base/OptionsFactories/ValidationPluginOptionsFactory.cs
index 690c89a..131bd7f 100644
--- a/src/main.lib/Plugins/Base/OptionsFactories/ValidationPluginOptionsFactory.cs
+++ b/src/main.lib/Plugins/Base/OptionsFactories/ValidationPluginOptionsFactory.cs
@@ -16,7 +16,6 @@ namespace PKISharp.WACS.Plugins.Base.Factories
{
private readonly string _challengeType;
string IValidationPluginOptionsFactory.ChallengeType => _challengeType;
- public virtual bool Hidden => false;
public ValidationPluginOptionsFactory(string challengeType = Constants.Http01ChallengeType) => _challengeType = challengeType;
public abstract Task<TOptions?> Aquire(Target target, IInputService inputService, RunLevel runLevel);
diff --git a/src/main.lib/Plugins/Resolvers/InteractiveResolver.cs b/src/main.lib/Plugins/Resolvers/InteractiveResolver.cs
index c7f98fa..2c682ec 100644
--- a/src/main.lib/Plugins/Resolvers/InteractiveResolver.cs
+++ b/src/main.lib/Plugins/Resolvers/InteractiveResolver.cs
@@ -1,5 +1,6 @@
using Autofac;
using PKISharp.WACS.DomainObjects;
+using PKISharp.WACS.Extensions;
using PKISharp.WACS.Plugins.Base.Factories.Null;
using PKISharp.WACS.Plugins.CsrPlugins;
using PKISharp.WACS.Plugins.InstallationPlugins;
@@ -39,8 +40,6 @@ namespace PKISharp.WACS.Plugins.Resolvers
private async Task<T> GetPlugin<T>(
ILifetimeScope scope,
- IEnumerable<T> options,
- Func<ILifetimeScope, string, string?, T> resolver,
Type defaultType,
Type defaultTypeFallback,
T nullResult,
@@ -49,6 +48,8 @@ namespace PKISharp.WACS.Plugins.Resolvers
string longDescription,
string? defaultParam1 = null,
string? defaultParam2 = null,
+ Func<IEnumerable<T>, IEnumerable<T>>? sort = null,
+ Func<IEnumerable<T>, IEnumerable<T>>? filter = null,
Func<T, (bool, string?)>? unusable = null,
Func<T, string>? description = null,
bool allowAbort = true) where T : IPluginOptionsFactory
@@ -72,10 +73,10 @@ namespace PKISharp.WACS.Plugins.Resolvers
};
// Apply default sorting when no sorting has been provided yet
- if (!(options is IOrderedEnumerable<T>))
- {
- options = options.OrderBy(x => x.Order).ThenBy(x => x.Description);
- }
+ var options = _plugins.GetFactories<T>(scope);
+ options = filter != null ? filter(options) : options.Where(x => !(x is INull));
+ options = sort != null ? sort(options) : options.OrderBy(x => x.Order).ThenBy(x => x.Description);
+
var localOptions = options.
Select(x => new {
plugin = x,
@@ -84,7 +85,9 @@ namespace PKISharp.WACS.Plugins.Resolvers
});
// Default out when there are no reasonable options to pick
- if (!localOptions.Any() || localOptions.All(x => x.disabled.Item1))
+ if (!localOptions.Any() ||
+ localOptions.All(x => x.disabled.Item1) ||
+ localOptions.All(x => x.plugin is INull))
{
return nullResult;
}
@@ -94,7 +97,7 @@ namespace PKISharp.WACS.Plugins.Resolvers
var showMenu = _runLevel.HasFlag(RunLevel.Advanced);
if (!string.IsNullOrEmpty(defaultParam1))
{
- var defaultPlugin = resolver(scope, defaultParam1, defaultParam2);
+ var defaultPlugin = _plugins.GetFactory<T>(scope, defaultParam1, defaultParam2);
if (defaultPlugin == null)
{
_log.Error("Unable to find {n} plugin {p}", className, defaultParam1);
@@ -106,10 +109,14 @@ namespace PKISharp.WACS.Plugins.Resolvers
}
}
- var defaultTypeDisabled = localOptions.First(x => x.type == defaultType).disabled;
+ var defaultOption = localOptions.First(x => x.type == defaultType);
+ var defaultTypeDisabled = defaultOption.disabled;
if (defaultTypeDisabled.Item1)
{
- _log.Warning("Default {n} plugin not available: {m}", className, defaultTypeDisabled.Item2);
+ _log.Warning("{n} plugin {x} not available: {m}",
+ char.ToUpper(className[0]) + className.Substring(1),
+ defaultOption.plugin.Name,
+ defaultTypeDisabled.Item2);
defaultType = defaultTypeFallback;
showMenu = true;
}
@@ -158,10 +165,8 @@ namespace PKISharp.WACS.Plugins.Resolvers
/// <returns></returns>
public override async Task<ITargetPluginOptionsFactory> GetTargetPlugin(ILifetimeScope scope)
{
- return await GetPlugin(
+ return await GetPlugin<ITargetPluginOptionsFactory>(
scope,
- _plugins.TargetPluginFactories(scope).Where(x => !(x is INull)),
- (ILifetimeScope s, string p1, string? p2) => _plugins.TargetPluginFactory(s, p1),
defaultParam1: _settings.Target.DefaultTarget,
defaultType: typeof(IISOptionsFactory),
defaultTypeFallback: typeof(ManualOptionsFactory),
@@ -179,11 +184,12 @@ namespace PKISharp.WACS.Plugins.Resolvers
/// <returns></returns>
public override async Task<IValidationPluginOptionsFactory> GetValidationPlugin(ILifetimeScope scope, Target target)
{
- return await GetPlugin(
+ return await GetPlugin<IValidationPluginOptionsFactory>(
scope,
- _plugins.ValidationPluginFactories(scope).
- Where(x => !(x is INull)).
- OrderBy(x => {
+ sort: x =>
+ x.
+ OrderBy(x =>
+ {
return x.ChallengeType switch
{
Constants.Http01ChallengeType => 0,
@@ -192,9 +198,8 @@ namespace PKISharp.WACS.Plugins.Resolvers
_ => 3,
};
}).
- ThenBy(x => x.Order).
- ThenBy(x => x.Description),
- (ILifetimeScope s, string p1, string? p2) => _plugins.ValidationPluginFactory(s, p1, p2),
+ ThenBy(x => x.Order).
+ ThenBy(x => x.Description),
unusable: x => (!x.CanValidate(target), "Unsuppored target. Most likely this is because you have included a wildcard identifier (*.example.com), which requires DNS validation."),
description: x => $"[{x.ChallengeType}] {x.Description}",
defaultParam1: _settings.Validation.DefaultValidation,
@@ -212,10 +217,8 @@ namespace PKISharp.WACS.Plugins.Resolvers
public override async Task<ICsrPluginOptionsFactory> GetCsrPlugin(ILifetimeScope scope)
{
- return await GetPlugin(
+ return await GetPlugin<ICsrPluginOptionsFactory>(
scope,
- _plugins.CsrPluginOptionsFactories(scope).Where(x => !(x is INull)),
- (ILifetimeScope s, string p1, string? p2) => _plugins.CsrPluginFactory(s, p1),
defaultParam1: _settings.Csr.DefaultCsr,
defaultType: typeof(RsaOptionsFactory),
defaultTypeFallback: typeof(EcOptionsFactory),
@@ -245,11 +248,15 @@ namespace PKISharp.WACS.Plugins.Resolvers
shortDescription = "Would you like to store it in another way too?";
defaultType = typeof(NullStoreOptionsFactory);
}
- return await GetPlugin(
+ var defaultParam1 = _settings.Store.DefaultStore;
+ var csv = defaultParam1.ParseCsv();
+ defaultParam1 = csv?.Count > chosen.Count() ?
+ csv[chosen.Count()] :
+ "";
+ return await GetPlugin<IStorePluginOptionsFactory>(
scope,
- _plugins.StorePluginFactories(scope).Except(chosen),
- (ILifetimeScope s, string p1, string? p2) => _plugins.StorePluginFactory(s, p1),
- defaultParam1: _settings.Csr.DefaultCsr,
+ filter: (x) => x.Except(chosen),
+ defaultParam1: defaultParam1,
defaultType: defaultType,
defaultTypeFallback: typeof(PemFilesOptionsFactory),
nullResult: new NullStoreOptionsFactory(),
@@ -283,12 +290,16 @@ namespace PKISharp.WACS.Plugins.Resolvers
shortDescription = "Add another installation step?";
defaultType = typeof(NullInstallationOptionsFactory);
}
- return await GetPlugin(
+ var defaultParam1 = _settings.Installation.DefaultInstallation;
+ var csv = defaultParam1.ParseCsv();
+ defaultParam1 = csv?.Count > chosen.Count() ?
+ csv[chosen.Count()] :
+ "";
+ return await GetPlugin<IInstallationPluginOptionsFactory>(
scope,
- _plugins.InstallationPluginFactories(scope).Except(chosen),
- (ILifetimeScope s, string p1, string? p2) => _plugins.InstallationPluginFactory(s, p1),
- unusable: x => (!x.CanInstall(storeTypes), "This step be used with the specified stores"),
- defaultParam1: _settings.Installation.DefaultInstallation,
+ filter: (x) => x.Except(chosen),
+ unusable: x => (!x.CanInstall(storeTypes), "This step cannot be used in combination with the specified store(s)"),
+ defaultParam1: defaultParam1,
defaultType: defaultType,
defaultTypeFallback: typeof(NullInstallationOptionsFactory),
nullResult: new NullInstallationOptionsFactory(),
diff --git a/src/main.lib/Plugins/Resolvers/UnattendedResolver.cs b/src/main.lib/Plugins/Resolvers/UnattendedResolver.cs
index 0c7a73f..a4d0d09 100644
--- a/src/main.lib/Plugins/Resolvers/UnattendedResolver.cs
+++ b/src/main.lib/Plugins/Resolvers/UnattendedResolver.cs
@@ -6,6 +6,7 @@ using PKISharp.WACS.Plugins.CsrPlugins;
using PKISharp.WACS.Plugins.Interfaces;
using PKISharp.WACS.Plugins.OrderPlugins;
using PKISharp.WACS.Plugins.StorePlugins;
+using PKISharp.WACS.Plugins.TargetPlugins;
using PKISharp.WACS.Plugins.ValidationPlugins.Http;
using PKISharp.WACS.Services;
using System;
@@ -30,9 +31,84 @@ namespace PKISharp.WACS.Plugins.Resolvers
_settings = settings;
}
+ private async Task<T> GetPlugin<T>(
+ ILifetimeScope scope,
+ Type defaultType,
+ T nullResult,
+ string className,
+ string? defaultParam1 = null,
+ string? defaultParam2 = null,
+ Func<IEnumerable<T>, IEnumerable<T>>? filter = null,
+ Func<T, (bool, string?)>? unusable = null) where T: IPluginOptionsFactory
+ {
+ // Helper method to determine final usability state
+ // combination of plugin being enabled (e.g. due to missing
+ // administrator rights) and being a right fit for the current
+ // renewal (e.g. cannot validate wildcards using http-01)
+ (bool, string?) disabledOrUnusable(T plugin)
+ {
+ var disabled = (plugin as IPluginOptionsFactory)?.Disabled ?? (true, "Invalid plugin");
+ if (disabled.Item1)
+ {
+ return disabled;
+ }
+ else if (unusable != null)
+ {
+ return unusable(plugin);
+ }
+ return (false, null);
+ };
+
+ // Apply default sorting when no sorting has been provided yet
+ var options = _plugins.GetFactories<T>(scope);
+ options = filter != null ? filter(options) : options.Where(x => !(x is INull));
+ var localOptions = options.
+ Select(x => new {
+ plugin = x,
+ type = x?.GetType(),
+ disabled = disabledOrUnusable(x)
+ });
+
+ // Default out when there are no reasonable options to pick
+ if (!localOptions.Any() ||
+ localOptions.All(x => x.disabled.Item1) ||
+ localOptions.All(x => x.plugin is INull))
+ {
+ return nullResult;
+ }
+
+ var changeInstructions = $"Choose another plugin using the --{className} switch or change the default in settings.json";
+ if (!string.IsNullOrEmpty(defaultParam1))
+ {
+ var defaultPlugin = _plugins.GetFactory<T>(scope, defaultParam1, defaultParam2);
+ if (defaultPlugin == null)
+ {
+ _log.Error("Unable to find {n} plugin {p}. " + changeInstructions, className, defaultParam1);
+ return nullResult;
+ }
+ else
+ {
+ defaultType = defaultPlugin.GetType();
+ }
+ }
+
+ var defaultOption = localOptions.First(x => x.type == defaultType);
+ var defaultTypeDisabled = defaultOption.disabled;
+ if (defaultTypeDisabled.Item1)
+ {
+ _log.Error("{n} plugin {x} not available: {m}. " + changeInstructions,
+ char.ToUpper(className[0]) + className.Substring(1),
+ (defaultOption.plugin as IPluginOptionsFactory)?.Name ?? "Unknown",
+ defaultTypeDisabled.Item2);
+ return nullResult;
+ }
+
+ return (T)scope.Resolve(defaultType);
+ }
+
/// <summary>
/// Get the TargetPlugin which was used (or can be assumed to have been used) to create this
- /// ScheduledRenewal
+ /// Renewal
/// </summary>
/// <returns></returns>
public virtual async Task<ITargetPluginOptionsFactory> GetTargetPlugin(ILifetimeScope scope)
@@ -41,58 +117,32 @@ namespace PKISharp.WACS.Plugins.Resolvers
// sense because MainArguments.Target is what triggers
// unattended mode in the first place. We woudn't even
// get into this code unless it was specified.
-
- // Get plugin factory
- if (string.IsNullOrEmpty(_arguments.MainArguments.Target))
- {
- return new NullTargetFactory();
- }
- var targetPluginFactory = _plugins.TargetPluginFactory(scope, _arguments.MainArguments.Target);
- if (targetPluginFactory == null)
- {
- _log.Error("Unable to find target plugin {PluginName}", _arguments.MainArguments.Target);
- return new NullTargetFactory();
- }
- var (disabled, disabledReason) = targetPluginFactory.Disabled;
- if (disabled)
- {
- _log.Error($"Target plugin {{PluginName}} is not available. {disabledReason}", _arguments.MainArguments.Target);
- return new NullTargetFactory();
- }
- return targetPluginFactory;
+ return await GetPlugin<ITargetPluginOptionsFactory>(
+ scope,
+ defaultParam1: _arguments.MainArguments.Target,
+ defaultType: typeof(ManualOptionsFactory),
+ nullResult: new NullTargetFactory(),
+ className: "target");
}
/// <summary>
/// Get the ValidationPlugin which was used (or can be assumed to have been used)
- /// to validate this ScheduledRenewal
+ /// to validate this Renewal
/// </summary>
/// <returns></returns>
public virtual async Task<IValidationPluginOptionsFactory> GetValidationPlugin(ILifetimeScope scope, Target target)
{
- // Get plugin factory
- var validationPluginFactory = string.IsNullOrEmpty(_arguments.MainArguments.Validation)
- ? scope.Resolve<SelfHostingOptionsFactory>()
- : _plugins.ValidationPluginFactory(scope,
- _arguments.MainArguments.ValidationMode ?? Constants.Http01ChallengeType,
- _arguments.MainArguments.Validation);
-
- if (validationPluginFactory == null)
- {
- _log.Error("Unable to find validation plugin {PluginName}", _arguments.MainArguments.Validation);
- return new NullValidationFactory();
- }
- var (disabled, disabledReason) = validationPluginFactory.Disabled;
- if (disabled)
- {
- _log.Error($"Validation plugin {{PluginName}} is not available. {disabledReason}", validationPluginFactory.Name);
- return new NullValidationFactory();
- }
- if (!validationPluginFactory.CanValidate(target))
- {
- _log.Error("Validation plugin {PluginName} cannot validate this target", validationPluginFactory.Name);
- return new NullValidationFactory();
- }
- return validationPluginFactory;
+ return await GetPlugin<IValidationPluginOptionsFactory>(
+ scope,
+ defaultParam1: _arguments.MainArguments.Validation ??
+ _settings.Validation.DefaultValidation,
+ defaultParam2: _arguments.MainArguments.ValidationMode ??
+ _settings.Validation.DefaultValidationMode ??
+ Constants.Http01ChallengeType,
+ defaultType: typeof(SelfHostingOptionsFactory),
+ nullResult: new NullValidationFactory(),
+ unusable: (c) => (!c.CanValidate(target), "Unsuppored target. Most likely this is because you have included a wildcard identifier (*.example.com), which requires DNS validation."),
+ className: "validation");
}
/// <summary>
@@ -102,24 +152,12 @@ namespace PKISharp.WACS.Plugins.Resolvers
/// <returns></returns>
public virtual async Task<IOrderPluginOptionsFactory> GetOrderPlugin(ILifetimeScope scope, Target target)
{
- var pluginName = _arguments.MainArguments.Order ?? _settings.Order.DefaultPlugin;
- if (string.IsNullOrEmpty(pluginName))
- {
- return scope.Resolve<SingleOptionsFactory>();
- }
- var factory = _plugins.OrderPluginFactory(scope, pluginName);
- var changeInstructions = "choose another plugin using the --order switch or change the default in settings.json";
- if (factory == null)
- {
- _log.Error("Unable to find order plugin {PluginName}, " + changeInstructions, pluginName);
- return new NullOrderOptionsFactory();
- }
- if (!factory.CanProcess(target))
- {
- _log.Error("Order plugin {PluginName} cannot process this target, " + changeInstructions, factory.Name);
- return new NullOrderOptionsFactory();
- }
- return factory;
+ return await GetPlugin<IOrderPluginOptionsFactory>(
+ scope,
+ defaultParam1: _arguments.MainArguments.Order,
+ defaultType: typeof(SingleOptionsFactory),
+ nullResult: new NullOrderOptionsFactory(),
+ className: "order");
}
/// <summary>
@@ -129,24 +167,12 @@ namespace PKISharp.WACS.Plugins.Resolvers
/// <returns></returns>
public virtual async Task<ICsrPluginOptionsFactory> GetCsrPlugin(ILifetimeScope scope)
{
- var pluginName = _arguments.MainArguments.Csr;
- if (string.IsNullOrEmpty(pluginName))
- {
- return scope.Resolve<RsaOptionsFactory>();
- }
- var factory = _plugins.CsrPluginFactory(scope, pluginName);
- if (factory == null)
- {
- _log.Error("Unable to find csr plugin {PluginName}", pluginName);
- return new NullCsrFactory();
- }
- var (disabled, disabledReason) = factory.Disabled;
- if (disabled)
- {
- _log.Error($"CSR plugin {{PluginName}} is not available. {disabledReason}", pluginName);
- return new NullCsrFactory();
- }
- return factory;
+ return await GetPlugin<ICsrPluginOptionsFactory>(
+ scope,
+ defaultParam1: _arguments.MainArguments.Csr,
+ defaultType: typeof(RsaOptionsFactory),
+ nullResult: new NullCsrFactory(),
+ className: "csr");
}
/// <summary>
@@ -155,45 +181,30 @@ namespace PKISharp.WACS.Plugins.Resolvers
/// <returns></returns>
public virtual async Task<IStorePluginOptionsFactory?> GetStorePlugin(ILifetimeScope scope, IEnumerable<IStorePluginOptionsFactory> chosen)
{
- var args = _arguments.MainArguments.Store;
- if (string.IsNullOrEmpty(args))
+ var cmd = _arguments.MainArguments.Store ?? _settings.Store.DefaultStore;
+ if (string.IsNullOrEmpty(cmd))
{
- if (chosen.Count() == 0)
- {
- args = CertificateStoreOptions.PluginName;
- }
- else
- {
- return new NullStoreOptionsFactory();
- }
+ cmd = CertificateStoreOptions.PluginName;
}
-
- var parts = args.ParseCsv();
+ var parts = cmd.ParseCsv();
if (parts == null)
{
return null;
}
-
var index = chosen.Count();
if (index == parts.Count)
{
return new NullStoreOptionsFactory();
}
-
- var name = parts[index];
- var factory = _plugins.StorePluginFactory(scope, name);
- if (factory == null)
- {
- _log.Error("Unable to find store plugin {PluginName}", name);
- return null;
- }
- var (disabled, disabledReason) = factory.Disabled;
- if (disabled)
- {
- _log.Error($"Store plugin {{PluginName}} is not available. {disabledReason}", name);
- return null;
- }
- return factory;
+ return await GetPlugin<IStorePluginOptionsFactory>(
+ scope,
+ filter: x => x,
+ defaultParam1: parts[index],
+ defaultType: typeof(NullStoreOptionsFactory),
+#pragma warning disable CS8625 // Cannot convert null literal to non-nullable reference type.
+ nullResult: default,
+#pragma warning restore CS8625
+ className: "store");
}
/// <summary>
@@ -203,39 +214,27 @@ namespace PKISharp.WACS.Plugins.Resolvers
/// <returns></returns>
public virtual async Task<IInstallationPluginOptionsFactory?> GetInstallationPlugin(ILifetimeScope scope, IEnumerable<Type> storeTypes, IEnumerable<IInstallationPluginOptionsFactory> chosen)
{
- if (string.IsNullOrEmpty(_arguments.MainArguments.Installation))
+ var cmd = _arguments.MainArguments.Installation ?? _settings.Installation.DefaultInstallation;
+ var parts = cmd.ParseCsv();
+ if (parts == null)
{
return new NullInstallationOptionsFactory();
}
- else
+ var index = chosen.Count();
+ if (index == parts.Count)
{
- var parts = _arguments.MainArguments.Installation.ParseCsv();
- var index = chosen.Count();
- if (parts == null || index == parts.Count)
- {
- return new NullInstallationOptionsFactory();
- }
-
- var name = parts[index];
- var factory = _plugins.InstallationPluginFactory(scope, name);
- if (factory == null)
- {
- _log.Error("Unable to find installation plugin {PluginName}", name);
- return null;
- }
- var (disabled, disabledReason) = factory.Disabled;
- if (disabled)
- {
- _log.Error($"Installation plugin {{PluginName}} is not available. {disabledReason}", name);
- return null;
- }
- if (!factory.CanInstall(storeTypes))
- {
- _log.Error("Installation plugin {PluginName} cannot install from selected store(s)", name);
- return null;
- }
- return factory;
+ return new NullInstallationOptionsFactory();
}
+ return await GetPlugin<IInstallationPluginOptionsFactory>(
+ scope,
+ filter: x => x,
+ unusable: x => (!x.CanInstall(storeTypes), "This step cannot be used in combination with the specified store(s)"),
+ defaultParam1: parts[index],
+ defaultType: typeof(NullInstallationOptionsFactory),
+#pragma warning disable CS8625 // Cannot convert null literal to non-nullable reference type.
+ nullResult: default,
+#pragma warning restore CS8625
+ className: "store");
}
}
}
diff --git a/src/main.lib/Services/ArgumentsParser.cs b/src/main.lib/Services/ArgumentsParser.cs
index 0c974f1..20529f0 100644
--- a/src/main.lib/Services/ArgumentsParser.cs
+++ b/src/main.lib/Services/ArgumentsParser.cs
@@ -9,7 +9,7 @@ namespace PKISharp.WACS.Configuration
{
private readonly ILogService _log;
private readonly string[] _args;
- private readonly List<IArgumentsProvider> _providers;
+ private readonly IEnumerable<IArgumentsProvider> _providers;
public T GetArguments<T>() where T : class, new()
{
@@ -27,7 +27,7 @@ namespace PKISharp.WACS.Configuration
{
_log = log;
_args = args;
- _providers = plugins.OptionProviders();
+ _providers = plugins.ArgumentsProviders();
}
internal bool Validate()
diff --git a/src/main.lib/Services/AutofacBuilder.cs b/src/main.lib/Services/AutofacBuilder.cs
index 6f658a9..5a5e4f9 100644
--- a/src/main.lib/Services/AutofacBuilder.cs
+++ b/src/main.lib/Services/AutofacBuilder.cs
@@ -164,7 +164,7 @@ namespace PKISharp.WACS.Services
builder.Register(x =>
{
var plugin = x.Resolve<IPluginService>();
- var match = plugin.ValidationPluginFactories(target).FirstOrDefault(vp => vp.OptionsType.PluginId() == renewal.ValidationPluginOptions.Plugin);
+ var match = plugin.GetFactories<IValidationPluginOptionsFactory>(target).FirstOrDefault(vp => vp.OptionsType.PluginId() == renewal.ValidationPluginOptions.Plugin);
return match;
}).As<IValidationPluginOptionsFactory>().SingleInstance();
diff --git a/src/main.lib/Services/Interfaces/IPluginService.cs b/src/main.lib/Services/Interfaces/IPluginService.cs
index 02a4793..4ef77b4 100644
--- a/src/main.lib/Services/Interfaces/IPluginService.cs
+++ b/src/main.lib/Services/Interfaces/IPluginService.cs
@@ -8,21 +8,9 @@ namespace PKISharp.WACS.Services
{
public interface IPluginService
{
- List<ITargetPluginOptionsFactory> TargetPluginFactories(ILifetimeScope scope);
- List<IValidationPluginOptionsFactory> ValidationPluginFactories(ILifetimeScope scope);
- List<IOrderPluginOptionsFactory> OrderPluginFactories(ILifetimeScope scope);
- List<ICsrPluginOptionsFactory> CsrPluginOptionsFactories(ILifetimeScope scope);
- List<IStorePluginOptionsFactory> StorePluginFactories(ILifetimeScope scope);
- List<IInstallationPluginOptionsFactory> InstallationPluginFactories(ILifetimeScope scope);
-
- ITargetPluginOptionsFactory TargetPluginFactory(ILifetimeScope scope, string name);
- IValidationPluginOptionsFactory ValidationPluginFactory(ILifetimeScope scope, string type, string name);
- IOrderPluginOptionsFactory OrderPluginFactory(ILifetimeScope scope, string name);
- ICsrPluginOptionsFactory CsrPluginFactory(ILifetimeScope scope, string name);
- IStorePluginOptionsFactory StorePluginFactory(ILifetimeScope scope, string name);
- IInstallationPluginOptionsFactory InstallationPluginFactory(ILifetimeScope scope, string name);
-
- List<IArgumentsProvider> OptionProviders();
- List<Type> PluginOptionTypes<T>() where T : PluginOptions;
+ IEnumerable<T> GetFactories<T>(ILifetimeScope scope) where T: IPluginOptionsFactory;
+ T GetFactory<T>(ILifetimeScope scope, string name, string? parameter = null) where T : IPluginOptionsFactory;
+ IEnumerable<IArgumentsProvider> ArgumentsProviders();
+ IEnumerable<Type> PluginOptionTypes<T>() where T : PluginOptions;
}
}
diff --git a/src/main.lib/Services/PluginService.cs b/src/main.lib/Services/PluginService.cs
index b2c4a57..404e65d 100644
--- a/src/main.lib/Services/PluginService.cs
+++ b/src/main.lib/Services/PluginService.cs
@@ -14,114 +14,53 @@ namespace PKISharp.WACS.Services
public class PluginService : IPluginService
{
private readonly List<Type> _allTypes;
-
- private readonly List<Type> _optionProviders;
-
- private readonly List<Type> _targetOptionFactories;
- private readonly List<Type> _validationOptionFactories;
- private readonly List<Type> _orderOptionFactories;
- private readonly List<Type> _csrOptionFactories;
- private readonly List<Type> _storeOptionFactories;
- private readonly List<Type> _installationOptionFactories;
-
- private readonly List<Type> _target;
- private readonly List<Type> _validation;
- private readonly List<Type> _order;
- private readonly List<Type> _csr;
- private readonly List<Type> _store;
- private readonly List<Type> _installation;
+ private readonly List<Type> _argumentProviders;
+ private readonly List<Type> _optionFactories;
+ private readonly List<Type> _plugins;
internal readonly ILogService _log;
- public List<IArgumentsProvider> OptionProviders()
+ public IEnumerable<IArgumentsProvider> ArgumentsProviders()
{
- return _optionProviders.Select(x =>
+ return _argumentProviders.Select(x =>
{
var c = x.GetConstructor(new Type[] { });
return (IArgumentsProvider)c.Invoke(new object[] { });
}).ToList();
}
- public List<ITargetPluginOptionsFactory> TargetPluginFactories(ILifetimeScope scope) => GetFactories<ITargetPluginOptionsFactory>(_targetOptionFactories, scope);
-
- public List<IValidationPluginOptionsFactory> ValidationPluginFactories(ILifetimeScope scope) => GetFactories<IValidationPluginOptionsFactory>(_validationOptionFactories, scope);
-
- public List<IOrderPluginOptionsFactory> OrderPluginFactories(ILifetimeScope scope) => GetFactories<IOrderPluginOptionsFactory>(_orderOptionFactories, scope);
-
- public List<ICsrPluginOptionsFactory> CsrPluginOptionsFactories(ILifetimeScope scope) => GetFactories<ICsrPluginOptionsFactory>(_csrOptionFactories, scope);
-
- public List<IStorePluginOptionsFactory> StorePluginFactories(ILifetimeScope scope) => GetFactories<IStorePluginOptionsFactory>(_storeOptionFactories, scope);
-
- public List<IInstallationPluginOptionsFactory> InstallationPluginFactories(ILifetimeScope scope) => GetFactories<IInstallationPluginOptionsFactory>(_installationOptionFactories, scope);
-
- public ITargetPluginOptionsFactory TargetPluginFactory(ILifetimeScope scope, string name) => GetByName<ITargetPluginOptionsFactory>(_targetOptionFactories, name, scope);
-
- public IValidationPluginOptionsFactory ValidationPluginFactory(ILifetimeScope scope, string type, string name)
- {
- return _validationOptionFactories.
- Select(scope.Resolve).
- OfType<IValidationPluginOptionsFactory>().
- FirstOrDefault(x => x.Match(name) && string.Equals(type, x.ChallengeType, StringComparison.InvariantCultureIgnoreCase));
- }
-
- public IOrderPluginOptionsFactory OrderPluginFactory(ILifetimeScope scope, string name) => GetByName<IOrderPluginOptionsFactory>(_orderOptionFactories, name, scope);
-
- public ICsrPluginOptionsFactory CsrPluginFactory(ILifetimeScope scope, string name) => GetByName<ICsrPluginOptionsFactory>(_csrOptionFactories, name, scope);
-
- public IStorePluginOptionsFactory StorePluginFactory(ILifetimeScope scope, string name) => GetByName<IStorePluginOptionsFactory>(_storeOptionFactories, name, scope);
-
- public IInstallationPluginOptionsFactory InstallationPluginFactory(ILifetimeScope scope, string name) => GetByName<IInstallationPluginOptionsFactory>(_installationOptionFactories, name, scope);
-
- public List<Type> PluginOptionTypes<T>() where T : PluginOptions => GetResolvable<T>();
+ public IEnumerable<Type> PluginOptionTypes<T>() where T : PluginOptions => GetResolvable<T>();
internal void Configure(ContainerBuilder builder)
{
- _targetOptionFactories.ForEach(t => builder.RegisterType(t).SingleInstance());
- _validationOptionFactories.ForEach(t => builder.RegisterType(t).SingleInstance());
- _orderOptionFactories.ForEach(t => builder.RegisterType(t).SingleInstance());
- _csrOptionFactories.ForEach(t => builder.RegisterType(t).SingleInstance());
- _storeOptionFactories.ForEach(t => builder.RegisterType(t).SingleInstance());
- _installationOptionFactories.ForEach(t => builder.RegisterType(t).SingleInstance());
-
- _target.ForEach(ip => builder.RegisterType(ip));
- _validation.ForEach(ip => builder.RegisterType(ip));
- _order.ForEach(ip => builder.RegisterType(ip));
- _csr.ForEach(ip => builder.RegisterType(ip));
- _store.ForEach(ip => builder.RegisterType(ip));
- _installation.ForEach(ip => builder.RegisterType(ip));
+ _optionFactories.ForEach(t => builder.RegisterType(t).SingleInstance());
+ _plugins.ForEach(ip => builder.RegisterType(ip));
}
- private List<T> GetFactories<T>(List<Type> source, ILifetimeScope scope) where T : IPluginOptionsFactory => source.Select(scope.Resolve).OfType<T>().OrderBy(x => x.Order).ToList();
+ public IEnumerable<T> GetFactories<T>(ILifetimeScope scope) where T : IPluginOptionsFactory => _optionFactories.Select(scope.Resolve).OfType<T>().OrderBy(x => x.Order).ToList();
- private T GetByName<T>(IEnumerable<Type> list, string name, ILifetimeScope scope) where T : IPluginOptionsFactory => list.Select(scope.Resolve).OfType<T>().FirstOrDefault(x => x.Match(name));
+ private IEnumerable<T> GetByName<T>(string name, ILifetimeScope scope) where T : IPluginOptionsFactory => GetFactories<T>(scope).Where(x => x.Match(name));
public PluginService(ILogService logger)
{
_log = logger;
_allTypes = GetTypes();
- _optionProviders = GetResolvable<IArgumentsProvider>();
-
- _targetOptionFactories = GetResolvable<ITargetPluginOptionsFactory>();
- _validationOptionFactories = GetResolvable<IValidationPluginOptionsFactory>();
- _orderOptionFactories = GetResolvable<IOrderPluginOptionsFactory>();
- _csrOptionFactories = GetResolvable<ICsrPluginOptionsFactory>();
- _storeOptionFactories = GetResolvable<IStorePluginOptionsFactory>(true);
- _installationOptionFactories = GetResolvable<IInstallationPluginOptionsFactory>(true);
-
- _target = GetResolvable<ITargetPlugin>();
- _validation = GetResolvable<IValidationPlugin>();
- _order = GetResolvable<IOrderPlugin>();
- _csr = GetResolvable<ICsrPlugin>();
- _store = GetResolvable<IStorePlugin>();
- _installation = GetResolvable<IInstallationPlugin>();
-
- ListPlugins(_target, "target");
- ListPlugins(_validation, "validation");
- ListPlugins(_order, "order");
- ListPlugins(_csr, "csr");
- ListPlugins(_store, "store");
- ListPlugins(_installation, "installation");
+ _argumentProviders = GetResolvable<IArgumentsProvider>();
+ _optionFactories = GetResolvable<IPluginOptionsFactory>(true);
+ _plugins = new List<Type>();
+ void AddPluginType<T>(string name)
+ {
+ var temp = GetResolvable<T>();
+ ListPlugins(temp, name);
+ _plugins.AddRange(temp);
+ }
+ AddPluginType<ITargetPlugin>("target");
+ AddPluginType<IValidationPlugin>("validation");
+ AddPluginType<IOrderPlugin>("order");
+ AddPluginType<ICsrPlugin>("csr");
+ AddPluginType<IStorePlugin>("store");
+ AddPluginType<IInstallationPlugin>("installation");
}
private void ListPlugins(IEnumerable<Type> list, string type)
@@ -268,5 +207,15 @@ namespace PKISharp.WACS.Services
}
return ret.ToList();
}
+
+ public T GetFactory<T>(ILifetimeScope scope, string name, string? parameter = null) where T : IPluginOptionsFactory
+ {
+ var plugins = GetByName<T>(name, scope);
+ if (typeof(T) is IValidationPluginOptionsFactory)
+ {
+ plugins = plugins.Where(x => string.Equals(parameter, (x as IValidationPluginOptionsFactory)?.ChallengeType, StringComparison.InvariantCultureIgnoreCase));
+ }
+ return plugins.FirstOrDefault();
+ }
}
}
diff --git a/src/main.lib/Services/SettingsService.cs b/src/main.lib/Services/SettingsService.cs
index e89b111..0fb54c5 100644
--- a/src/main.lib/Services/SettingsService.cs
+++ b/src/main.lib/Services/SettingsService.cs
@@ -549,7 +549,7 @@ namespace PKISharp.WACS.Services
/// <summary>
/// Default plugin(s) to select
/// </summary>
- public string? DefaultPlugin { get; set; }
+ public string? DefaultStore { get; set; }
/// <summary>
/// The certificate store to save the certificates in. If left empty,
diff --git a/src/main.test/Mock/Clients/IISClient.cs b/src/main.test/Mock/Clients/IISClient.cs
index 6b8cc38..df0c1a8 100644
--- a/src/main.test/Mock/Clients/IISClient.cs
+++ b/src/main.test/Mock/Clients/IISClient.cs
@@ -121,7 +121,7 @@ namespace PKISharp.WACS.UnitTests.Mock.Clients
public void UpdateBinding(MockSite site, MockBinding binding, BindingOptions bindingOptions)
{
- site.Bindings.Remove(binding);
+ _ = site.Bindings.Remove(binding);
var updateOptions = bindingOptions
.WithHost(binding.Host)
.WithIP(binding.IP)
diff --git a/src/main.test/Tests/BindingTests/Bindings.cs b/src/main.test/Tests/BindingTests/Bindings.cs
index 138c481..8b4a57a 100644
--- a/src/main.test/Tests/BindingTests/Bindings.cs
+++ b/src/main.test/Tests/BindingTests/Bindings.cs
@@ -171,16 +171,16 @@ namespace PKISharp.WACS.UnitTests.Tests.BindingTests
Assert.AreEqual(existingBindings.Count() + expectedNew, httpOnlySite.Bindings.Count);
var newBindings = httpOnlySite.Bindings.Except(existingBindings);
- newBindings.All(newBinding =>
- {
- Assert.AreEqual(existingHost, newBinding.Host);
- Assert.AreEqual("https", newBinding.Protocol);
- Assert.AreEqual(storeName, newBinding.CertificateStoreName);
- Assert.AreEqual(newCert, newBinding.CertificateHash);
- Assert.AreEqual(bindingPort, newBinding.Port);
- Assert.AreEqual(expectedFlags, newBinding.SSLFlags);
- return true;
- });
+ _ = newBindings.All(newBinding =>
+ {
+ Assert.AreEqual(existingHost, newBinding.Host);
+ Assert.AreEqual("https", newBinding.Protocol);
+ Assert.AreEqual(storeName, newBinding.CertificateStoreName);
+ Assert.AreEqual(newCert, newBinding.CertificateHash);
+ Assert.AreEqual(bindingPort, newBinding.Port);
+ Assert.AreEqual(expectedFlags, newBinding.SSLFlags);
+ return true;
+ });
var oldips = existingBindings.Select(x => x.IP).Distinct();
var newips = newBindings.Select(x => x.IP).Distinct();
diff --git a/src/main.test/Tests/InstallationPluginTests/MultipleInstallerTests.cs b/src/main.test/Tests/InstallationPluginTests/MultipleInstallerTests.cs
index 2e22240..8c8aa79 100644
--- a/src/main.test/Tests/InstallationPluginTests/MultipleInstallerTests.cs
+++ b/src/main.test/Tests/InstallationPluginTests/MultipleInstallerTests.cs
@@ -12,6 +12,7 @@ using mock = PKISharp.WACS.UnitTests.Mock.Services;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
+using PKISharp.WACS.Clients.DNS;
namespace PKISharp.WACS.UnitTests.Tests.InstallationPluginTests
{
@@ -42,26 +43,30 @@ namespace PKISharp.WACS.UnitTests.Tests.InstallationPluginTests
var builder = new ContainerBuilder();
- builder.RegisterInstance(plugins).
+ _ = builder.RegisterType<LookupClientProvider>();
+ _ = builder.RegisterType<ProxyService>();
+ _ = builder.RegisterType<DomainParseService>();
+ _ = builder.RegisterType<IISHelper>();
+ _ = builder.RegisterInstance(plugins).
As<IPluginService>().
- SingleInstance();
- builder.RegisterInstance(settings).
+ SingleInstance();
+ _ = builder.RegisterInstance(settings).
As<ISettingsService>().
SingleInstance();
- builder.RegisterInstance(log).
+ _ = builder.RegisterInstance(log).
As<ILogService>().
SingleInstance();
- builder.RegisterType<Mock.Clients.MockIISClient>().
+ _ = builder.RegisterType<Mock.Clients.MockIISClient>().
As<IIISClient>().
SingleInstance();
- builder.RegisterType<ArgumentsParser>().
+ _ = builder.RegisterType<ArgumentsParser>().
SingleInstance().
WithParameter(new TypedParameter(typeof(string[]), commandLine.Split(' ')));
- builder.RegisterType<ArgumentsService>().
+ _ = builder.RegisterType<ArgumentsService>().
As<IArgumentsService>().
SingleInstance();
- builder.RegisterType<mock.UserRoleService>().As<IUserRoleService>().SingleInstance();
- builder.RegisterType<UnattendedResolver>().As<IResolver>();
+ _ = builder.RegisterType<mock.UserRoleService>().As<IUserRoleService>().SingleInstance();
+ _ = builder.RegisterType<UnattendedResolver>().As<IResolver>();
plugins.Configure(builder);
var scope = builder.Build();
diff --git a/src/main/settings.json b/src/main/settings.json
index 332569b..7657b14 100644
--- a/src/main/settings.json
+++ b/src/main/settings.json
@@ -59,7 +59,7 @@
"DefaultTarget": null
},
"Validation": {
- "DefaultValidation": "azure",
+ "DefaultValidation": "script",
"DefaultValidationMode": "dns-01",
"CleanupFolders": true,
"PreValidateDns": true,