mathiasertl / django-ca

Django app providing a Certificate Authority
GNU General Public License v3.0
145 stars 43 forks source link

The client sent an unacceptable anti-replay nonce :: Bad or invalid nonce #141

Closed gridfocus closed 6 months ago

gridfocus commented 6 months ago

testing the ACME functionality with certbot I keep on getting the bad nonce error:

sudo certbot certonly -v --standalone --config-dir=.certbot/config/ --work-dir=.certbot/work/ --logs-dir=.certbot/logs --server https://privateca.localnet/ca/acme/directory --cert-name test01.localnet -d test01.localnet --agree-tos -m info@localnet -v

{"type": "urn:ietf:params:acme:error:badNonce", "status": 400, "detail": "Bad or invalid nonce."}

In the admin panel the order and authorization have been created with the status "pending" .

Is this normal behaviour? how can I find out why is this returning a bad nonce and what are the processes expecting? (I haven't found a django-ca user's mailing list, not sure if this is the right place to post this)

Best Regards,

mathiasertl commented 6 months ago

Hi @gridfocus,

This is the right place to post this! Please note I'm on vacation right now, so I will not be able to analyze this in more detail until Monday or Tuesday.

One reason this might be happening is the cache setup. What kind of cache have you configured, if any? ACME requires a distributed cache such as Redis or Memcached.

It would also help if you can tell me more about your setup. How did you install django-ca? What system is it running on? What's the configuration?

The certbot version and OS you're using might also help. It's possible (but unlikely in this case) that this also plays a part.

Kr, Mat

gridfocus commented 6 months ago

Hi @mathiasertl ,
Thanks for your reply, sure there is no rush, let me know when you have time to have a look at the issue.

The info you requested:

certbot 1.21.0 on ubuntu 22.04

django-ca installed via pip (Django version 5.0.4 also on ubuntu 22.04).

Error in nginx log:

{"type": "urn:ietf:params:acme:error:badNonce", "status": 400, "detail": "Bad or invalid nonce."} Exiting abnormally: Traceback (most recent call last): File "/usr/lib/python3/dist-packages/acme/client.py", line 1269, in post return self._post_once(*args, **kwargs) File "/usr/lib/python3/dist-packages/acme/client.py", line 1283, in _post_once response = self._check_response(response, content_type=content_type) File "/usr/lib/python3/dist-packages/acme/client.py", line 1128, in _check_response raise messages.Error.from_json(jobj) acme.messages.Error: urn:ietf:params:acme:error:badNonce :: The client sent an unacceptable anti-replay nonce :: Bad or invalid nonce.

During handling of the above exception, another exception occurred:

Traceback (most recent call last): File "/usr/bin/certbot", line 33, in sys.exit(load_entry_point('certbot==1.21.0', 'console_scripts', 'certbot')()) File "/usr/lib/python3/dist-packages/certbot/main.py", line 15, in main return internal_main.main(cli_args) File "/usr/lib/python3/dist-packages/certbot/_internal/main.py", line 1574, in main return config.func(config, plugins) File "/usr/lib/python3/dist-packages/certbot/_internal/main.py", line 1434, in certonly lineage = _get_and_save_cert(le_client, config, domains, certname, lineage) File "/usr/lib/python3/dist-packages/certbot/_internal/main.py", line 133, in _get_and_save_cert lineage = le_client.obtain_and_enroll_certificate(domains, certname) File "/usr/lib/python3/dist-packages/certbot/_internal/client.py", line 459, in obtain_and_enrollcertificate cert, chain, key, = self.obtain_certificate(domains) File "/usr/lib/python3/dist-packages/certbot/_internal/client.py", line 389, in obtain_certificate orderr = self._get_order_and_authorizations(csr.data, self.config.allow_subset_of_names) File "/usr/lib/python3/dist-packages/certbot/_internal/client.py", line 421, in _get_order_and_authorizations orderr = self.acme.new_order(csr_pem) File "/usr/lib/python3/dist-packages/acme/client.py", line 936, in new_order return cast(ClientV2, self.client).new_order(csr_pem) File "/usr/lib/python3/dist-packages/acme/client.py", line 702, in new_order response = self._post(self.directory['newOrder'], order) File "/usr/lib/python3/dist-packages/acme/client.py", line 101, in _post return self.net.post(*args, *kwargs) File "/usr/lib/python3/dist-packages/acme/client.py", line 1273, in post return self._post_once(args, **kwargs) File "/usr/lib/python3/dist-packages/acme/client.py", line 1283, in _post_once response = self._check_response(response, content_type=content_type) File "/usr/lib/python3/dist-packages/acme/client.py", line 1128, in _check_response raise messages.Error.from_json(jobj) acme.messages.Error: urn:ietf:params:acme:error:badNonce :: The client sent an unacceptable anti-replay nonce :: Bad or invalid nonce. An unexpected error occurred: The client sent an unacceptable anti-replay nonce :: Bad or invalid nonce. Ask for help or search for solutions at https://community.letsencrypt.org. See the logfile /home/user/new/.certbot/logs/letsencrypt.log or re-run Certbot with -v for more details.

mathiasertl commented 6 months ago

Hi @gridfocus ,

What about your cache configuration?

Do the logs of your application server (uWSGI?) say anything?

Kr, Mat

gridfocus commented 6 months ago

Hello,

The log shows this error: Bad Request: /ca/acme/32331AEF3CAC5E0F86C409AD57756726BBCB4362/new-order/

It's a pretty standard config (nginx / gunicorn / django + redis task manager + postgres db), not using cache in nginx or django.

cheers,

mathiasertl commented 6 months ago

The Nonce is stored in the cache. Without a cache that shares data between workers, different workers will not see the nonces created by the other client. Please try configuring Redis also as a Cache (support is now even included in Django: https://docs.djangoproject.com/en/5.0/topics/cache/#redis).

By the way, there even is a system check for this:

python manage.py check --deploy

I notice that the app documentation does not really mention the need for the cache, I will certainly update that.

Please let me know if that solves the issue for you!

gridfocus commented 6 months ago

Hello Mathias,

You were correct, after configuring the shared cache settings, everything is working correctly :)

Thank you,

mathiasertl commented 6 months ago

@gridfocus that's good to hear! I have updated documentation to make this more clear.

I hope you find django-ca useful!