raforg/danectl

Handle multiple certificate types, HTTP/DNS verification and script hook.

Closed this issue · 3 comments

With current version 0.7.3 of danectl it is not possible to have a certificate with RSA and ECDSA for the same domain name.
For example:
I use certbot for RSA with $OPTIONS www.domain.tld
and for ECDSA with $OPTIONS --key-type ecdsa --cert-name www.domain.tld-ecdsa www..domain.tld
cert-name specifies the folder name under the live folder to differentiate between the two certificate types.

With danectl the certbot options are "static" configured with danectl certbot certonly $OPTIONS
It can not differentiate between the certificate types.

Secondly. I have one system doing all the renewals and deployment for all my systems. For wildcard certificates the authentication must be done through DNS. But for a simple host certificate it can being handled by HTTP authentication (in my case by HAproxy as webserver serving the verification token). For these two type of verification a different certbot line is required. Different $OPTIONS in my case.

So when using other danectl commands it can now not differentiate the correct $OPTIONS and results into issues.

It would be great if it could be more flexibel to be used with different certificate types and different authentications.

And instead of restart service(s), just run a script hook passing the 'current' certificate, so the script can handle the deployment and restart the service(s) (on remote systems).

Hi, Thanks for this. Addressing this will be a big improvement.

I think the first two points are really the same problem (at least partly). Danectl only handles a homogenous environment where all certificates are obtained the same way as each other. The saved certbot authorization/installation options apply to everything. That gives flexibility in some ways, but not the way you need. As it is, you'd probably need multiple certbot installations or multiple local user accounts driving danectl. Yuk.

I don't want danectl to need to completely wrap the interface of certbot. That would never work well. But perhaps there can be two ways to use danectl. The original way, where it knows how to tell certbot how to create similar certificate lineages, and a new way where certbot does all the creation, and danectl just adopts the results. It can already adopt an original certificate lineage, but the "dup" sub-command takes a list of domains, not the cert-name being duplicated. So the "dup" subcommand might need to be able to take a cert-name rather than a list of domains, and then copy all of the authentication/installation details from the original certificate lineage's renewal config file. That might be unwise, as it's a deliberately undocumented file format, but maybe not if it can just have renewalparams copied. Or maybe you should need to create the duplicate directly with certbot, and then adopt the duplicate into danectl. Or perhaps I can just save different certbot options for each cert-name. At the moment, I'm favouring the last option.

I'll need to think about it, and make sure it doesn't get messy, and that everything is backwards-compatible.

As for the hooks, that'll be easy to add. But if all they are doing is restarting something remotely, local "restart" scripts that initiate a remote restart might be better, as you could run them independently of danectl if you wanted to. But I'll add it anyway.

I'm busy at the moment on another fun project, but I should be able to start looking into this properly in a few weeks time. I hope you'll be able to test things for me.

Also, would you be able to send me some /etc/letsencrypt/renewal/*.conf files (or just the (non-sensitive) [renewalparams] parts) so I can get a picture of your environment/requirements? Or the equivalent certbot commands that you would use to create your certificate lineages. Email is fine if you don't want it appearing here.

Hi. Sorry for the delay. I've finally gotten back to this, and I think I've addressed everything.

I've added a --group groupname command line option that enables support for heterogeneous environments by creating multiple named groups of internally homogeneous certificate lineages.

Within each group, all certificate lineages must have the same type of key, and the same authentication and installation methods. But it's no longer the case that all certificate lineages must have these properties be the same.

It might be slightly annoying that each group needs to share all of these properties. For example, it might have been nicer to be able to decouple the choice of key type from the choice of authentication and installation methods, but this implementation is very simple and low-risk (so I like it). It's done by having a separate configuration file for each group. The only downside is that you might need to specify the same authentication and installation details multiple times, once for each key type. But this only needs to be done once per group, not all the time, so it shouldn't be too onerous.

Regarding the request for a script hook to handle remote services, I have added support for the reload subcommand (and add-reload, del-reload, and show-reload) so you can supply an absolute path to an executable file (no spaces), rather than a service name recognized by the local operating system.

Whether the service is an absolute path or a regular service name, the $CERTNAME environment variable will be set to the certificate name. This allows a single script to handle different certificate lineages differently, rather than requiring different scripts for differently-handled certificate lineages.

When an explicit executable file is invoked by the reload subcommand, its first command line argument ($1) will be reload, and its second argument ($2) will be the certificate name being reloaded.

So, given:

danectl add-reload example.org /usr/local/sbin/danectl-reload

The command:

danectl reload example.org

Will effectively invoke:

CERTNAME=example.org /usr/local/sbin/danectl-reload reload example.com

Does this look OK?

I've just released danectl-0.8 which has this new behaviour.