ebekker / ACMESharp

An ACME client library and PowerShell client for the .NET platform (Let's Encrypt)
https://pkisharp.github.io/ACMESharp-docs/
1.21k stars 184 forks source link

Proposal: Allow direct execution of command actions outside of PowerShell #225

Open webprofusion-chrisc opened 7 years ago

webprofusion-chrisc commented 7 years ago

I'm trying to find a way to avoid using Powershell in Certify, but at the same time make minimal changes to ACMESharp. It looks to me like I could directly invoke commands against the vault if all commands provided a way to invoke ProcessRecord, such as:

public void ExecuteCommand() { this.ProcessRecord(); }

How does this sound? It would require changing the existing POSH commands to inherit from a Cmdlet base class that did this. I've been considering just moving chunks of code out of the commands and into a common class for the operations themselves but that's probably unnecessary if the actions the commands perform can be invoked directly. The reason for this change is that my users are not managing to coordinate the correct required versions of Powershell across their various environments, resulting in a variety of issues.

ebekker commented 7 years ago

The PowerShell module is actually just a wrapper around the core client library. You can use the core library directly, and just avoid all the PowerShell stuff. Other projects are already doing this where they have no need or involvement with PowerShell, for example one project uses ACMESharp inside a Web application. Another example is the letsencrypt-win-simple client which is a CLI application for configuring LE certs on IIS. It goes directly against the core client library.

In your case you also want to use the Vault library to manage storage of all the assets related to LE interaction, so you should use both the core client library and the Vault library.

So in your project, you should do a nuget reference to these:

webprofusion-chrisc commented 7 years ago

Hi Eugene, I do agree that we could recreate vault operations in Certify but I'm trying to minimise the amount of code duplication. The long term solution might be to refactor the powershell commands so that they are only wrappers to the actual operations, rather than implementing the actions within the command classes, but I can see that's a big job.

My proposal was to implement the following base class (or similar) and have at least the commands Certify uses inherit from it. This allows the commands 'ProcessRecord' method to be invoked externally outwith of the Powershell environment (via ExecuteCommand) and retains the command result for reference, but still lets them work when invoked from powershell. I do understand if you see this as a bit of hack, but in the short term it would help Certify get around the problems we're seeing with users Powershell environments.


using System;
using System.Management.Automation;

namespace ACMESharp.POSH
{
    public class BaseCmdlet : Cmdlet
    {
        public object CommandResult { get; set; }

        public object ExecuteCommand()
        {
            this.ProcessRecord();
            return this.CommandResult;
        }

        public new void WriteObject(object sendToPipeline)
        {
            this.CommandResult = sendToPipeline;
            try
            {
                base.WriteObject(sendToPipeline);
            }
            catch (NotImplementedException)
            {
            }
        }

        public new void WriteVerbose(string msg)
        {
            //log
            System.Diagnostics.Debug.WriteLine(msg);

            try
            {
                base.WriteVerbose(msg);
            }
            catch (NotImplementedException) { }
        }
    }
}```