diff --git a/changelogs/fragments/919-acme_account-ear.yml b/changelogs/fragments/919-acme_account-ear.yml new file mode 100644 index 00000000..3c0f1cbf --- /dev/null +++ b/changelogs/fragments/919-acme_account-ear.yml @@ -0,0 +1,2 @@ +bugfixes: + - "acme_account - make work with CAs that do not accept any account request without External Account Binding data (https://github.com/ansible-collections/community.crypto/issues/918, https://github.com/ansible-collections/community.crypto/pull/919)." diff --git a/plugins/module_utils/_acme/account.py b/plugins/module_utils/_acme/account.py index d5085c9c..c2878fde 100644 --- a/plugins/module_utils/_acme/account.py +++ b/plugins/module_utils/_acme/account.py @@ -66,13 +66,28 @@ class ACMEAccount: # and provide external_account_binding credentials. Thus we first send a request with allow_creation=False # to see whether the account already exists. - # Note that we pass contact here: ZeroSSL does not accept registration calls without contacts, even - # if onlyReturnExisting is set to true. - created, data = self._new_reg(contact=contact, allow_creation=False) - if data: - # An account already exists! Return data - return created, data - # An account does not yet exist. Try to create one next. + # Unfortunately, for other ACME servers it's the other way around: (at least some) HARICA endpoints + # do not allow *any* access without external account data. That's why we catch errors and check + # for 'externalAccountRequired'. + try: + # Note that we pass contact here: ZeroSSL does not accept registration calls without contacts, even + # if onlyReturnExisting is set to true. + created, data = self._new_reg(contact=contact, allow_creation=False) + if data: + # An account already exists! Return data + return created, data + # An account does not yet exist. Try to create one next. + except ACMEProtocolException as exc: + if ( + exc.error_type + != "urn:ietf:params:acme:error:externalAccountRequired" + or external_account_binding is None + ): + # Either another error happened, or we got 'externalAccountRequired' and external account data was not supplied + # => re-raise exception! + raise + # In this case, the server really wants external account data. + # The below code tries to create the account with external account data present. new_reg: dict[str, t.Any] = {"contact": contact} if not allow_creation: