Keep getting `Must agree to subscriber agreement before any further actions` #326

Closed
opened 2025-12-29 01:22:44 +01:00 by adam · 7 comments
Owner

Originally created by @gheja on GitHub (Apr 10, 2018).

I keep getting Must agree to subscriber agreement before any further actions when trying to get a wildcard certificate. I have started with a clean install, only thing I changed is the staging server in the config. Maybe just I am doing something wrong.

The hook.sh is my own hook script as neither the name server nor the web server is located on this machine.

(Replaced my domain with example.com. And I think in hindsight that using this private key is not recommended.)

$ openssl genrsa -des3 -out example.com.key 4096
[...]

$ openssl req -new -key example.com.key -out test4.csr
[...]
Common Name (e.g. server FQDN or YOUR name) []:example.com
[...]

$ ./dehydrated --register --privkey example.com.key --accept-terms
# INFO: Using main config file /home/user/dehydrated/config
Using private key example.com.key instead of account key
Enter pass phrase for example.com.key:
Enter pass phrase for example.com.key:
Enter pass phrase for example.com.key:
+ Account already registered!

$ ./dehydrated --signcsr test4.csr --privkey example.com.key --out test4.crt --challenge dns-01 --hook ./hook.sh --domain '*.example.com'
# INFO: Using main config file /home/user/dehydrated/config
Using private key example.com.key instead of account key
Enter pass phrase for example.com.key:
Enter pass phrase for example.com.key:
Enter pass phrase for example.com.key:
Fetching missing account information from CA...
Enter pass phrase for example.com.key:
Enter pass phrase for example.com.key:
 + Requesting authorization for example.com...
Enter pass phrase for example.com.key:
  + ERROR: An error occurred while sending post-request to https://acme-staging.api.letsencrypt.org/acme/new-authz (Status 403)

Details:
HTTP/1.1 100 Continue
Expires: xxx
Cache-Control: max-age=0, no-cache, no-store
Pragma: no-cache

HTTP/1.1 403 Forbidden
Server: nginx
Content-Type: application/problem+json
Content-Length: 137
Boulder-Requester: xxx
Replay-Nonce: xxx
Expires: xxx
Cache-Control: max-age=0, no-cache, no-store
Pragma: no-cache
Date: xxx
Connection: close

{
  "type": "urn:acme:error:unauthorized",
  "detail": "Must agree to subscriber agreement before any further actions",
  "status": 403
}

rm: cannot remove '/home/user/dehydrated/domains.txt': No such file or directory

Originally created by @gheja on GitHub (Apr 10, 2018). I keep getting ``Must agree to subscriber agreement before any further actions`` when trying to get a wildcard certificate. I have started with a clean install, only thing I changed is the staging server in the config. Maybe just I am doing something wrong. The hook.sh is [my own hook script](https://github.com/gheja/dns-01-manual) as neither the name server nor the web server is located on this machine. (Replaced my domain with ``example.com``. And I think in hindsight that using this private key is not recommended.) ``` $ openssl genrsa -des3 -out example.com.key 4096 [...] $ openssl req -new -key example.com.key -out test4.csr [...] Common Name (e.g. server FQDN or YOUR name) []:example.com [...] $ ./dehydrated --register --privkey example.com.key --accept-terms # INFO: Using main config file /home/user/dehydrated/config Using private key example.com.key instead of account key Enter pass phrase for example.com.key: Enter pass phrase for example.com.key: Enter pass phrase for example.com.key: + Account already registered! $ ./dehydrated --signcsr test4.csr --privkey example.com.key --out test4.crt --challenge dns-01 --hook ./hook.sh --domain '*.example.com' # INFO: Using main config file /home/user/dehydrated/config Using private key example.com.key instead of account key Enter pass phrase for example.com.key: Enter pass phrase for example.com.key: Enter pass phrase for example.com.key: Fetching missing account information from CA... Enter pass phrase for example.com.key: Enter pass phrase for example.com.key: + Requesting authorization for example.com... Enter pass phrase for example.com.key: + ERROR: An error occurred while sending post-request to https://acme-staging.api.letsencrypt.org/acme/new-authz (Status 403) Details: HTTP/1.1 100 Continue Expires: xxx Cache-Control: max-age=0, no-cache, no-store Pragma: no-cache HTTP/1.1 403 Forbidden Server: nginx Content-Type: application/problem+json Content-Length: 137 Boulder-Requester: xxx Replay-Nonce: xxx Expires: xxx Cache-Control: max-age=0, no-cache, no-store Pragma: no-cache Date: xxx Connection: close { "type": "urn:acme:error:unauthorized", "detail": "Must agree to subscriber agreement before any further actions", "status": 403 } rm: cannot remove '/home/user/dehydrated/domains.txt': No such file or directory ```
adam closed this issue 2025-12-29 01:22:45 +01:00
Author
Owner

@gheja commented on GitHub (Apr 10, 2018):

Hmm, when I am not using --privkey the script just works fine.

$ ./dehydrated --register --accept-terms
# INFO: Using main config file /home/user/dehydrated/config
+ Generating account key...
+ Registering account key with ACME server...
+ Done!

$ ./dehydrated --signcsr test4.csr --out test4.crt --challenge dns-01 --hook ./hook.sh --domain '*.example.com'
# INFO: Using main config file /home/user/dehydrated/config
 + Requesting authorization for example.com...
 + 1 pending challenge(s)
 + Deploying challenge tokens...

Add the following to the zone definition of example.com:
_acme-challenge.example.com. IN TXT "xxx"

Press enter to continue...

 + Responding to challenge for example.com authorization...
 + Challenge is valid!
 + Cleaning challenge tokens...

Now you can remove the following from the zone definition of example.com:
_acme-challenge.example.com. IN TXT "xxx"

Press enter to continue...

 + Requesting certificate...
 + Checking certificate...
 + Done!
# CERT #
-----BEGIN CERTIFICATE-----
xxx
-----END CERTIFICATE-----

So it looks like when using a private key from file instead of account key the ToS acceptance is not working for some reason.

@gheja commented on GitHub (Apr 10, 2018): Hmm, when I am not using ``--privkey`` the script just works fine. ``` $ ./dehydrated --register --accept-terms # INFO: Using main config file /home/user/dehydrated/config + Generating account key... + Registering account key with ACME server... + Done! $ ./dehydrated --signcsr test4.csr --out test4.crt --challenge dns-01 --hook ./hook.sh --domain '*.example.com' # INFO: Using main config file /home/user/dehydrated/config + Requesting authorization for example.com... + 1 pending challenge(s) + Deploying challenge tokens... Add the following to the zone definition of example.com: _acme-challenge.example.com. IN TXT "xxx" Press enter to continue... + Responding to challenge for example.com authorization... + Challenge is valid! + Cleaning challenge tokens... Now you can remove the following from the zone definition of example.com: _acme-challenge.example.com. IN TXT "xxx" Press enter to continue... + Requesting certificate... + Checking certificate... + Done! # CERT # -----BEGIN CERTIFICATE----- xxx -----END CERTIFICATE----- ``` So it looks like when using a private key from file instead of account key the ToS acceptance is not working for some reason.
Author
Owner

@lukas2511 commented on GitHub (Apr 13, 2018):

The privkey option was designed to allow use of an existing pre-registered key, there is no registration logic if a custom key is defined.
Dehydrated fails when it tries to receive additional information for the registered account for that key (well, because there is no account registered with that key).

Not really a dehydrated bug, but the error message may be a bit confusing. This actually seems more like a boulder bug. I'll investigate the error message a bit more and may open an issue with boulder.

@lukas2511 commented on GitHub (Apr 13, 2018): The privkey option was designed to allow use of an existing pre-registered key, there is no registration logic if a custom key is defined. Dehydrated fails when it tries to receive additional information for the registered account for that key (well, because there is no account registered with that key). Not really a dehydrated bug, but the error message may be a bit confusing. This actually seems more like a boulder bug. I'll investigate the error message a bit more and may open an issue with boulder.
Author
Owner

@lukas2511 commented on GitHub (Apr 13, 2018):

Well, okay, two things:

  1. I now allowed the register command to also work with keys specified that way, so now registering custom keys should work, but what you are doing using --privkey example.com.key is wrong, that shouldn't be your domain key, that should be an account key and usually wouldn't be needed to specify as dehydrated handles account-management itself.

  2. Any error messages about ToS not being accepted actually seem to be a boulder issue because boulder doesn't implement the only-return-existing flag for account registration/information. I won't change anything about this in dehydrated as it actually follows the protocol specification and the CA should return a different error in this case.

@lukas2511 commented on GitHub (Apr 13, 2018): Well, okay, two things: 1) I now allowed the register command to also work with keys specified that way, so now registering custom keys should work, but what you are doing using `--privkey example.com.key` is wrong, that shouldn't be your domain key, that should be an account key and usually wouldn't be needed to specify as dehydrated handles account-management itself. 2) Any error messages about ToS not being accepted actually seem to be a boulder issue because boulder doesn't implement the `only-return-existing` flag for account registration/information. I won't change anything about this in dehydrated as it actually follows the protocol specification and the CA should return a different error in this case.
Author
Owner

@cpu commented on GitHub (Apr 13, 2018):

Any error messages about ToS not being accepted actually seem to be a boulder issue because boulder doesn't implement the only-return-existing flag for account registration/information. I won't change anything about this in dehydrated as it actually follows the protocol specification and the CA should return a different error in this case.

Boulder does implement onlyReturnExisting for ACME v2 (It's not something that was initially specified in ACME "v1").

This is the correct error message for an ACMEv1 request that is using an account that has been created, but that has not posted the agreement field.

@cpu commented on GitHub (Apr 13, 2018): > Any error messages about ToS not being accepted actually seem to be a boulder issue because boulder doesn't implement the only-return-existing flag for account registration/information. I won't change anything about this in dehydrated as it actually follows the protocol specification and the CA should return a different error in this case. Boulder [does implement `onlyReturnExisting`](https://github.com/letsencrypt/boulder/blob/1271a15be79b9717ee5b98e707b76e7ac86a9a0e/wfe2/wfe.go#L475-L482) for ACME v2 (It's not something that was initially specified in ACME "v1"). This is the correct error message for an ACMEv1 request that is using an account that has been created, but that has not posted the `agreement` field.
Author
Owner

@lukas2511 commented on GitHub (Apr 13, 2018):

@cpu aff1d64605/docs/acme-divergences.md (section-731) wasn't "onlyReturnExisting" acme-v1 and "only-return-existing" acme-v2? Or did I swap the two protocol versions around in my code? Or was it changed between drafts? I'm not entirely sure, I'm always confused which document is for which API version 🙈 Is there a link where I can always get the most recent version of v1 / v2 specs?

@lukas2511 commented on GitHub (Apr 13, 2018): @cpu https://github.com/letsencrypt/boulder/blob/aff1d64605bc0f766e1a98ff34f93981e250f145/docs/acme-divergences.md#section-731 wasn't "onlyReturnExisting" acme-v1 and "only-return-existing" acme-v2? Or did I swap the two protocol versions around in my code? Or was it changed between drafts? I'm not entirely sure, I'm always confused which document is for which API version :see_no_evil: Is there a link where I can always get the most recent version of v1 / v2 specs?
Author
Owner

@cpu commented on GitHub (Apr 13, 2018):

@lukas2511 That divergences doc needs to be clarified - it only applies to the V1 endpoint and was written at the time when we didn't have an ACME v2 implementation. The case was changed from only-return-existing to onlyReturnExisting in a later draft and that page needs to be caught up with its references. ACME v2 does implement this feature. ACME v2 has no divergences page (there's only the two mentioned at the end of the announcement).

It's all a bit of a mess with regards to legacy ACME. There's no specific "v1" draft because the implementation and the point at which drafts were cut were not in lockstep. The latest V2 specs are always here: https://datatracker.ietf.org/doc/draft-ietf-acme-acme/

@cpu commented on GitHub (Apr 13, 2018): @lukas2511 That divergences doc needs to be clarified - it only applies to the V1 endpoint and was written at the time when we didn't have an ACME v2 implementation. The case was changed from `only-return-existing` to `onlyReturnExisting` in a later draft and that page needs to be caught up with its references. ACME v2 does implement this feature. ACME v2 has no divergences page (there's only the two [mentioned at the end of the announcement](https://community.letsencrypt.org/t/acme-v2-production-environment-wildcards/55578/2)). It's all a bit of a mess with regards to legacy ACME. There's no specific "v1" draft because the implementation and the point at which drafts were cut were not in lockstep. The latest V2 specs are always here: https://datatracker.ietf.org/doc/draft-ietf-acme-acme/
Author
Owner

@lukas2511 commented on GitHub (Apr 13, 2018):

@cpu ok thanks, I uhm "fixed" that in ba5928776f now, seems to be working fine.

@lukas2511 commented on GitHub (Apr 13, 2018): @cpu ok thanks, I uhm "fixed" that in ba5928776f9d2e42b73da816daacce180ca6f26c now, seems to be working fine.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: starred/dehydrated#326