candango / automatoes

A Let's Encrypt/ACME client based on Manuale. You can keep being manual but we're automated also.
Apache License 2.0
13 stars 6 forks source link

manuale with sub-domains #100

Closed pythonmobile closed 2 years ago

pythonmobile commented 2 years ago

Is there a way to manuale authorize a root domain (say example.com) and then generate/renew certificates for all sub-domains (a.example.com) without authorizing for each subdomain?

piraz commented 2 years ago

You can generate a *.example.com. It seems not recommended, for security issues.

Are you using the library or using the command?

Basically the command will generate a simple order structure based on an hash from the domains being authorized.

With the library you can do other things, I don't have the documentation of the python api, but the work I'll do for the automatoes command is document this so you don't use only the command but the library.

The plain naked execution is here: https://github.com/candango/automatoes/blob/develop/tests/features/steps/acme_v2_steps.py

The tests are under behave:

Those are the basic life-cycle of an order defined by the letsencrypt protocol.

piraz commented 2 years ago

This is a funny scenario and I'm checking right here:

Candango Automatoes 0.9.7. Manuale replacement.

Authorizing test.com, *.test.com.

  Requesting challenge for test.com.
  Requesting challenge for test.com.

  DNS verification required. Make sure these TXT records are in place:

    _acme-challenge.test.com.  IN TXT  "SyA7Flwwfr4ATxcQvBNG7C6pMsbvukxE1aLoTnfootw"
    _acme-challenge.test.com.  IN TXT  "u-11Rg8aWg3ji29riJoqTLPiu95B_pOKzI2LkkZaOo8"

Press Enter to continue.

Let me see if that works...

Not testing with test.com right? Just obfuscating my test, I'm in production doing that.

piraz commented 2 years ago

Results:

.
.
.
Press Enter to continue.

  test.com: waiting for verification. Checking in 5 seconds.
  test.com: OK! Authorization lasts until 2022-03-24T21:05:24Z.
  test.com: waiting for verification. Checking in 5 seconds.
  test.com: OK! Authorization lasts until 2022-03-24T21:05:46Z.
  1 domain(s) authorized. Let's Encrypt!

#1010>>> manuale issue -o test test.com *.test.com
Candango Automatoes 0.9.7. Manuale replacement.

Generating a 4096 bit RSA key. This might take a second.
  Key generated.
  Order updated with generated key.
Requesting certificate issuance...
  We already know the certificate uri for order obfuscated_blablabla. Downloading certificate.
  Certificate downloaded.
  Expires: 2022-06-15
   SHA256: obfuscated_blablabla

  Wrote key to test/test.com.pem
  Wrote certificate to test/test.com.crt
  Wrote certificate with intermediate to test/test.com.chain.crt
  Wrote intermediate certificate to test/test.com.intermediate.crt

I created two _acme-challenge.test.com txt dns entries each with the values displayed by the challenge(SyA7Flwwfr4ATxcQvBNG7C6pMsbvukxE1aLoTnfootw, u-11Rg8aWg3ji29riJoqTLPiu95B_pOKzI2LkkZaOo8).

We can see the validation and issuance worked fine.

Here is the certifcate:

[#1013]>>> openssl x509 -in test.com.crt -text -noout
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number:
            obfuscated_blablabla
        .
        .
        .
        Subject: CN = test.com  <====== HERE, THIS IS THE ROOT DOMAIN
        Subject Public Key Info:
            .
            .
            .
            X509v3 Subject Alternative Name:  <==== HERE, THIS IS THE ALTERNATIVES
                DNS:*.test.com, DNS:test.com
            .
            .
            .
piraz commented 2 years ago

Is that your scenario @pythonmobile?

pythonmobile commented 2 years ago

@piraz Thanks for the help. In my case, I have to add/delete/renew subdomain_i.test.com at different times. I understand that when I need to get certs for xyz.test.com, I've to do the acme challenge from scratch. I do not need/want *.test.com to even exist - if i understand this right. I need to automate this cert generation/renewal process - from a single machine, since my servers have port 80/443 restricted.

piraz commented 2 years ago

From the rfc in the protocol overview:

Once an account is registered, there are four major steps the client needs to take to get a certificate:

  1. Submit an order for a certificate to be issued

  2. Prove control of any identifiers requested in the certificate

  3. Finalize the order by submitting a CSR

  4. Await issuance and download the issued certificate

We need to create an order with [test.com x1.test.com x2.test.com]. For simplicity in our side, as I don't receive any identifier from acme, a hash based on "test.com x1.test.com x2.test.com" is created and stored in the a directory in the orders directory.

The order directory(the hash one) receives the necessary challenges so you can prove control of the domains. Those challenges have a limited expiration date, around 7 or 20 days , don't quote me on that, but something around that. The time limit is not described in the protocol rfc also.

I have 7 and 20 numbers in my head for the challenge expiration date in days, but I'm not sure about it. I think is 7 for the challenges...

If you have issued the certificate for [test.com x1.test.com x2.test.com] without problems and you want to add x3.test.com to the certificate, lets encrypt will create a new order and automatoes will create a new hash for [test.com x1.test.com x2.test.com x3.test.com] and add that directory to the orders directory.

Right now, I'm talking about what I know about Let's Encrypt implementation(there are others).

If challenges for test.com, x1.test.com and x2.test.com are still not expired, in this new order you just need certify x3.test.com. So if expiration is 7(a week) or 20 days, adding another domain or removing a domain from [test.com x1.test.com x2.test.com] will trigger a new order with fresh challenges and you need to start from scratch.

Using the manuale command from automatoes, a new order will be created and this is by design. I was just trying to mimic the protocol with an identifier, the hash from all domains being added to the repository.

Using the library(https://github.com/candango/automatoes/blob/develop/automatoes/acme.py#L250) you can control or even abstract the order right? The order will be a identifier defined by you.

You can choose to authorize and issue the cert in just one routine.

You can name the certificate as cert_from_domain_test_com. This will be your identifier(not the local order).

You can use from Acme2:

This can be automated without manuale(command) but you are still limited by the order structure from the letsencrypt protocol and server. If you fail a challenge the whole order will be invalidated, you need to create a new one, orders already validated will be kept validated in this new order(if not expired), pending only the challenges not validate and the invalid one.

I'll start to work on the automatoes command to chop manuale commands so you can have better control and new workflows.

Also I want to create a event and hooks structure #94 to the project, it is still something to be defined. Those hooks will help you to interact with your database and go to your dns/web server and add challenges without using the library.

I'll see if I get back to the automatoes command and give more tools to help you with your certificate workflow.

piraz commented 2 years ago

Here are the divergences from the implementation from the protocol definition:

https://github.com/letsencrypt/boulder/blob/main/docs/acme-divergences.md

They are pretty clear about, no retries, lack of order list for accounts and fixed order date limits.

pythonmobile commented 2 years ago

@piraz how do i get in touch with you ? I tried to find your email/phone/etc, but could not.

piraz commented 2 years ago

Every commit has my email, you can also find here:

https://github.com/candango/automatoes/blob/develop/automatoes/__init__.py#L18

piraz commented 2 years ago

In another words, [piraz at candango.org]. We can take from there...

piraz commented 2 years ago

@pythonmobile do you got the email?

[piraz at candango.org]