unixcharles / acme-client

A Ruby client for the letsencrypt's ACME protocol.
MIT License
495 stars 116 forks source link

Multiple Certificates for same domain #237

Closed braindeaf closed 8 months ago

braindeaf commented 8 months ago

Hi there,

I wonder if you can point me in the right direction. I'm in a position where I might need to generate different certificates for the same hostname. Something like...

cert1
- robl.me
- *.robl.me
- *.x.robl.me

cert2
- robl.me
- *.robl.me
- *.y.robl.me

We're basically doing a mutli-tenant setup where it's entirely possible we end up with multiple certificates that contain the same hostnames and I don't want to end up invalidating an rendering an existing certificate useles / revoking an older certificate that is with robl.me in it. Or I am thinking we might have each cert having up to 100 hosts in one certificate and keeping one consistent primary host *robl.me and robl.me in every cert. Something like that.

Anyway. I understand you can do this with certbot by providing a certificate name. I am unclear if this is even possible with acme-client and where is would go

certbot certonly --cert-name robl-ssl-01

I initially thought it was in the common_name but that needs to be a hostname with a valid TLD. Honestly I've never set up a multi-domain certificate so I'm not entirely sure of the process even without Certbot.

  csr = Acme::Client::CertificateRequest.new(
    common_name: common_name.to_s,
    names: identifiers
  )
  order.finalize(csr: csr)

Can you help?

RobL

unixcharles commented 8 months ago

We're basically doing a mutli-tenant setup where it's entirely possible we end up with multiple certificates that contain the same hostnames and I don't want to end up invalidating an rendering an existing certificate useles / revoking an older certificate that is with robl.me in it.

That's not a problem. Ordering new certificate for a domain that already has certificates in circulation will not invalidate them. At least it's not part of the specification for ACME and LetsEncrypt doesn't do that. There are a lot of valid reasons to have multiple certificate for a domain, so I don't think it would make sense.

Or I am thinking we might have each cert having up to 100 hosts in one certificate and keeping one consistent primary host *robl.me and robl.me in every cert. Something like that.

That sound complicated but it should work. IMO, it's easier to just have 100s of certificates, and serve the right one at request time using SNI. That's how we handled millions of certificate at Shopify.

I initially thought it was in the common_name but that needs to be a hostname with a valid TLD. Honestly I've never set up a multi-domain certificate so I'm not entirely sure of the process even without Certbot.

You can have only one common name, it has to be one of the domain name, doesn't really matter which one and multiple subject alt names. That's how you do a multi-domains certificate.

Using Acme::Client::CertificateRequest you can do it like this:

Acme::Client::CertificateRequest.new(common_name: 'robl.me', names: ['robl.me', '*.robl.me', '*.x.robl.me'])

I'm assume there are historical reason why it's so complicated. Probably that subjectAltName came later as some sort of extension to tls/ssl.

Acme::Client::CertificateRequest is actually just a wrapper I've put together for OpenSSL::X509::Request because I find it hard to reason about. It's from openssl in the standard library.

You can generate the CSR anyway you want. Client#finalize only expect an object that respond to to_der, it doesn't have to be an Acme::Client::CertificateRequest. If you completed the challenges for all the domain contained in the CSR you pass to #finalize, it will work.

I'll close the issue since none of this stuff is client specific. I hope that was helpful.

braindeaf commented 8 months ago

This was indeed very helpful and your response it is very much appreciated. We're sadly locked to a single SSL key per load balancer because of our current setup/provider's offering. So we're faced with having a load balancer per-tenant per-application. So while the SSL key management would be less than ideal, the alternative is worse. So migrating to a single SSL key for every available wildcard hostname for which to be fair at the moment will only be 4 variations (but potentially moving to 70 or so in the next year) is the better medium term solution.

Many thanks again.