summaryrefslogtreecommitdiffstats
path: root/src/main.lib/Plugins/ValidationPlugins/Dns/Script
diff options
context:
space:
mode:
Diffstat (limited to 'src/main.lib/Plugins/ValidationPlugins/Dns/Script')
-rw-r--r--src/main.lib/Plugins/ValidationPlugins/Dns/Script/Script.cs78
-rw-r--r--src/main.lib/Plugins/ValidationPlugins/Dns/Script/ScriptArguments.cs11
-rw-r--r--src/main.lib/Plugins/ValidationPlugins/Dns/Script/ScriptArgumentsProvider.cs41
-rw-r--r--src/main.lib/Plugins/ValidationPlugins/Dns/Script/ScriptOptions.cs19
-rw-r--r--src/main.lib/Plugins/ValidationPlugins/Dns/Script/ScriptOptionsFactory.cs160
5 files changed, 309 insertions, 0 deletions
diff --git a/src/main.lib/Plugins/ValidationPlugins/Dns/Script/Script.cs b/src/main.lib/Plugins/ValidationPlugins/Dns/Script/Script.cs
new file mode 100644
index 0000000..7bd9e4d
--- /dev/null
+++ b/src/main.lib/Plugins/ValidationPlugins/Dns/Script/Script.cs
@@ -0,0 +1,78 @@
+using PKISharp.WACS.Clients;
+using PKISharp.WACS.Clients.DNS;
+using PKISharp.WACS.DomainObjects;
+using PKISharp.WACS.Services;
+
+namespace PKISharp.WACS.Plugins.ValidationPlugins.Dns
+{
+ internal class Script : DnsValidation<ScriptOptions, Script>
+ {
+ private readonly ScriptClient _scriptClient;
+
+ internal const string DefaultCreateArguments = "create {Identifier} {RecordName} {Token}";
+ internal const string DefaultDeleteArguments = "delete {Identifier} {RecordName} {Token}";
+
+ public Script(
+ ScriptOptions options,
+ LookupClientProvider dnsClient,
+ ILogService log,
+ string identifier) :
+ base(dnsClient, log, options, identifier)
+ {
+ _scriptClient = new ScriptClient(log);
+ }
+
+ public override void CreateRecord(string recordName, string token)
+ {
+ var script = _options.Script ?? _options.CreateScript;
+ if (!string.IsNullOrWhiteSpace(script))
+ {
+ var args = DefaultCreateArguments;
+ if (!string.IsNullOrWhiteSpace(_options.CreateScriptArguments))
+ {
+ args = _options.CreateScriptArguments;
+ }
+ _scriptClient.RunScript(script, ProcessArguments(recordName, token, args, script.EndsWith(".ps1")));
+ }
+ else
+ {
+ _log.Error("No create script configured");
+ }
+ }
+
+ public override void DeleteRecord(string recordName, string token)
+ {
+ var script = _options.Script ?? _options.DeleteScript;
+ if (!string.IsNullOrWhiteSpace(script))
+ {
+ var args = DefaultDeleteArguments;
+ if (!string.IsNullOrWhiteSpace(_options.DeleteScriptArguments))
+ {
+ args = _options.DeleteScriptArguments;
+ }
+ _scriptClient.RunScript(script, ProcessArguments(recordName, token, args, script.EndsWith(".ps1")));
+ }
+ else
+ {
+ _log.Warning("No delete script configured, validation record remains");
+ }
+ }
+
+ private string ProcessArguments(string recordName, string token, string args, bool escapeToken)
+ {
+ var ret = args;
+ ret = ret.Replace("{Identifier}", _identifier);
+ ret = ret.Replace("{RecordName}", recordName);
+ // Some tokens start with - which confuses Powershell. We did not want to
+ // make a breaking change for .bat or .exe files, so instead escape the
+ // token with double quotes, as Powershell discards the quotes anyway and
+ // thus it's functionally equivalant.
+ if (escapeToken && (ret.Contains(" {Token} ") || ret.EndsWith(" {Token}")))
+ {
+ ret.Replace("{Token}", "\"{Token}\"");
+ }
+ ret = ret.Replace("{Token}", token);
+ return ret;
+ }
+ }
+}
diff --git a/src/main.lib/Plugins/ValidationPlugins/Dns/Script/ScriptArguments.cs b/src/main.lib/Plugins/ValidationPlugins/Dns/Script/ScriptArguments.cs
new file mode 100644
index 0000000..c73a963
--- /dev/null
+++ b/src/main.lib/Plugins/ValidationPlugins/Dns/Script/ScriptArguments.cs
@@ -0,0 +1,11 @@
+namespace PKISharp.WACS.Plugins.ValidationPlugins.Dns
+{
+ class ScriptArguments
+ {
+ public string DnsScript { get; set; }
+ public string DnsCreateScript { get; set; }
+ public string DnsCreateScriptArguments { get; set; }
+ public string DnsDeleteScript { get; set; }
+ public string DnsDeleteScriptArguments { get; set; }
+ }
+}
diff --git a/src/main.lib/Plugins/ValidationPlugins/Dns/Script/ScriptArgumentsProvider.cs b/src/main.lib/Plugins/ValidationPlugins/Dns/Script/ScriptArgumentsProvider.cs
new file mode 100644
index 0000000..2fb7a1a
--- /dev/null
+++ b/src/main.lib/Plugins/ValidationPlugins/Dns/Script/ScriptArgumentsProvider.cs
@@ -0,0 +1,41 @@
+using Fclp;
+using PKISharp.WACS.Configuration;
+using PKISharp.WACS.Services;
+
+namespace PKISharp.WACS.Plugins.ValidationPlugins.Dns
+{
+ class ScriptArgumentsProvider : BaseArgumentsProvider<ScriptArguments>
+ {
+ public override string Name => "Script";
+ public override string Group => "Validation";
+ public override string Condition => "--validationmode dns-01 --validation dnsscript";
+
+ public override void Configure(FluentCommandLineParser<ScriptArguments> parser)
+ {
+ parser.Setup(o => o.DnsScript)
+ .As("dnsscript")
+ .WithDescription("Path to script that creates and deletes validation records, depending on its parameters. If this parameter is provided then --dnscreatescript and --dnsdeletescript are ignored.");
+ parser.Setup(o => o.DnsCreateScript)
+ .As("dnscreatescript")
+ .WithDescription("Path to script that creates the validation TXT record.");
+ parser.Setup(o => o.DnsCreateScriptArguments)
+ .As("dnscreatescriptarguments")
+ .WithDescription($"Default parameters passed to the script are {Script.DefaultCreateArguments}, but that can be customized using this argument.");
+ parser.Setup(o => o.DnsDeleteScript)
+ .As("dnsdeletescript")
+ .WithDescription("Path to script to remove TXT record.");
+ parser.Setup(o => o.DnsDeleteScriptArguments)
+ .As("dnsdeletescriptarguments")
+ .WithDescription($"Default parameters passed to the script are {Script.DefaultDeleteArguments}, but that can be customized using this argument.");
+ }
+
+ public override bool Active(ScriptArguments current)
+ {
+ return !string.IsNullOrEmpty(current.DnsScript) ||
+ !string.IsNullOrEmpty(current.DnsCreateScript) ||
+ !string.IsNullOrEmpty(current.DnsDeleteScript) ||
+ !string.IsNullOrEmpty(current.DnsDeleteScriptArguments) ||
+ !string.IsNullOrEmpty(current.DnsCreateScriptArguments);
+ }
+ }
+}
diff --git a/src/main.lib/Plugins/ValidationPlugins/Dns/Script/ScriptOptions.cs b/src/main.lib/Plugins/ValidationPlugins/Dns/Script/ScriptOptions.cs
new file mode 100644
index 0000000..4ad3f5a
--- /dev/null
+++ b/src/main.lib/Plugins/ValidationPlugins/Dns/Script/ScriptOptions.cs
@@ -0,0 +1,19 @@
+using PKISharp.WACS.Plugins.Base;
+using PKISharp.WACS.Plugins.Base.Options;
+
+namespace PKISharp.WACS.Plugins.ValidationPlugins.Dns
+{
+ [Plugin("8f1da72e-f727-49f0-8546-ef69e5ecec32")]
+ class ScriptOptions : ValidationPluginOptions<Script>
+ {
+ public override string Name => "DnsScript";
+ public override string Description => "Create verification records with your own script";
+ public override string ChallengeType { get => Constants.Dns01ChallengeType; }
+
+ public string Script { get; set; }
+ public string CreateScript { get; set; }
+ public string CreateScriptArguments { get; set; }
+ public string DeleteScript { get; set; }
+ public string DeleteScriptArguments { get; set; }
+ }
+}
diff --git a/src/main.lib/Plugins/ValidationPlugins/Dns/Script/ScriptOptionsFactory.cs b/src/main.lib/Plugins/ValidationPlugins/Dns/Script/ScriptOptionsFactory.cs
new file mode 100644
index 0000000..4ed53f4
--- /dev/null
+++ b/src/main.lib/Plugins/ValidationPlugins/Dns/Script/ScriptOptionsFactory.cs
@@ -0,0 +1,160 @@
+using PKISharp.WACS.DomainObjects;
+using PKISharp.WACS.Extensions;
+using PKISharp.WACS.Plugins.Base.Factories;
+using PKISharp.WACS.Services;
+using System;
+using System.Collections.Generic;
+
+namespace PKISharp.WACS.Plugins.ValidationPlugins.Dns
+{
+ internal class ScriptOptionsFactory : ValidationPluginOptionsFactory<Script, ScriptOptions>
+ {
+ private readonly ILogService _log;
+ private readonly IArgumentsService _arguments;
+
+ public ScriptOptionsFactory(ILogService log, IArgumentsService arguments) : base(Constants.Dns01ChallengeType)
+ {
+ _log = log;
+ _arguments = arguments;
+ }
+
+ public override ScriptOptions Aquire(Target target, IInputService input, RunLevel runLevel)
+ {
+ var args = _arguments.GetArguments<ScriptArguments>();
+ var ret = new ScriptOptions();
+ var createScript = "";
+ do
+ {
+ createScript = _arguments.TryGetArgument(args.DnsCreateScript, input, "Path to script that creates DNS records");
+ }
+ while (!createScript.ValidFile(_log));
+
+ var deleteScript = "";
+ input.ChooseFromList(
+ "How to delete records after validation",
+ new List<Choice<Action>>()
+ {
+ Choice.Create<Action>(() => { deleteScript = createScript; }, "Using the same script"),
+ Choice.Create<Action>(() => {
+ do {
+ deleteScript = _arguments.TryGetArgument(args.DnsDeleteScript, input, "Path to script that deletes DNS records");
+ }
+ while (!deleteScript.ValidFile(_log));
+ }, "Using a different script"),
+ Choice.Create<Action>(() => { }, "Do not delete")
+ }).Invoke();
+
+ ProcessScripts(ret, null, createScript, deleteScript);
+
+ input.Show("{Identifier}", "Domain that's being validated");
+ input.Show("{RecordName}", "Full TXT record name");
+ input.Show("{Token}", "Expected value in the TXT record");
+ var createArgs = _arguments.TryGetArgument(args.DnsCreateScriptArguments, input, $"Input parameters for create script, or enter for default \"{Script.DefaultCreateArguments}\"");
+ var deleteArgs = "";
+ if (!string.IsNullOrWhiteSpace(ret.DeleteScript) ||
+ !string.IsNullOrWhiteSpace(ret.Script))
+ {
+ deleteArgs = _arguments.TryGetArgument(args.DnsDeleteScriptArguments, input, $"Input parameters for delete script, or enter for default \"{Script.DefaultDeleteArguments}\"");
+ }
+ ProcessArgs(ret, createArgs, deleteArgs);
+
+ return ret;
+ }
+
+ public override ScriptOptions Default(Target target)
+ {
+ var args = _arguments.GetArguments<ScriptArguments>();
+ var ret = new ScriptOptions();
+ ProcessScripts(ret, args.DnsScript, args.DnsCreateScript, args.DnsDeleteScript);
+ if (!string.IsNullOrEmpty(ret.Script))
+ {
+ if (!ret.Script.ValidFile(_log))
+ {
+ _log.Error($"Invalid argument --{nameof(args.DnsScript).ToLower()}");
+ return null;
+ }
+ }
+ else
+ {
+ if (!ret.CreateScript.ValidFile(_log))
+ {
+ _log.Error($"Invalid argument --{nameof(args.DnsCreateScript).ToLower()}");
+ return null;
+ }
+ if (!string.IsNullOrEmpty(ret.DeleteScript))
+ {
+ if (!ret.DeleteScript.ValidFile(_log))
+ {
+ _log.Error($"Invalid argument --{nameof(args.DnsDeleteScript).ToLower()}");
+ return null;
+ }
+ }
+ }
+
+ ProcessArgs(ret, args.DnsCreateScriptArguments, args.DnsDeleteScriptArguments);
+ return ret;
+ }
+
+ /// <summary>
+ /// Choose the right script to run
+ /// </summary>
+ /// <param name="options"></param>
+ /// <param name="commonInput"></param>
+ /// <param name="createInput"></param>
+ /// <param name="deleteInput"></param>
+ private void ProcessScripts(ScriptOptions options, string commonInput, string createInput, string deleteInput)
+ {
+ if (!string.IsNullOrWhiteSpace(commonInput))
+ {
+ if(!string.IsNullOrWhiteSpace(createInput))
+ {
+ _log.Warning($"Ignoring --dnscreatescript because --dnsscript was provided");
+ }
+ if (!string.IsNullOrWhiteSpace(deleteInput))
+ {
+ _log.Warning("Ignoring --dnsdeletescript because --dnsscript was provided");
+ }
+ }
+
+
+ if (string.IsNullOrWhiteSpace(commonInput) &&
+ string.Equals(createInput, deleteInput, StringComparison.CurrentCultureIgnoreCase))
+ {
+ commonInput = createInput;
+ }
+ if (!string.IsNullOrWhiteSpace(commonInput))
+ {
+ options.Script = commonInput;
+ }
+ else
+ {
+ options.CreateScript = string.IsNullOrWhiteSpace(createInput) ? null : createInput;
+ options.DeleteScript = string.IsNullOrWhiteSpace(deleteInput) ? null : deleteInput;
+ }
+ }
+
+ private void ProcessArgs(ScriptOptions options, string createInput, string deleteInput)
+ {
+ if (!string.IsNullOrWhiteSpace(createInput) &&
+ createInput != Script.DefaultCreateArguments)
+ {
+ options.CreateScriptArguments = createInput;
+ }
+ if (!string.IsNullOrWhiteSpace(options.DeleteScript) ||
+ !string.IsNullOrWhiteSpace(options.Script))
+ {
+ if (!string.IsNullOrWhiteSpace(deleteInput) &&
+ deleteInput != Script.DefaultDeleteArguments)
+ {
+ options.DeleteScriptArguments = deleteInput;
+ }
+ }
+ }
+
+ public override bool CanValidate(Target target)
+ {
+ return true;
+ }
+ }
+
+}