diff --git a/lib/ansible/module_utils/acme.py b/lib/ansible/module_utils/acme.py index 1effe9ce7e..19ea0cddc9 100644 --- a/lib/ansible/module_utils/acme.py +++ b/lib/ansible/module_utils/acme.py @@ -686,8 +686,9 @@ class ACMEAccount(object): elif info['status'] == (409 if self.version == 1 else 200): # Account did exist if result.get('status') == 'deactivated': - # A probable bug in Pebble (https://github.com/letsencrypt/pebble/issues/179) - # and Boulder: this should not return a valid account object according to + # A bug in Pebble (https://github.com/letsencrypt/pebble/issues/179) and + # Boulder (https://github.com/letsencrypt/boulder/issues/3971): this should + # not return a valid account object according to # https://tools.ietf.org/html/draft-ietf-acme-acme-18#section-7.3.6: # "Once an account is deactivated, the server MUST NOT accept further # requests authorized by that account's key." @@ -701,6 +702,14 @@ class ACMEAccount(object): elif info['status'] == 400 and result['type'] == 'urn:ietf:params:acme:error:accountDoesNotExist' and not allow_creation: # Account does not exist (and we didn't try to create it) return False, None + elif info['status'] == 403 and result['type'] == 'urn:ietf:params:acme:error:unauthorized' and 'deactivated' in (result.get('detail') or ''): + # Account has been deactivated; currently works for Pebble; hasn't been + # implemented for Boulder (https://github.com/letsencrypt/boulder/issues/3971), + # might need adjustment in error detection. + if not allow_creation: + return False, None + else: + raise ModuleFailException("Account is deactivated") else: raise ModuleFailException("Error registering: {0} {1}".format(info['status'], result)) diff --git a/test/integration/targets/acme_account/tests/validate.yml b/test/integration/targets/acme_account/tests/validate.yml index 1fcfda65f7..3bc1d7aa73 100644 --- a/test/integration/targets/acme_account/tests/validate.yml +++ b/test/integration/targets/acme_account/tests/validate.yml @@ -111,6 +111,9 @@ assert: that: - account_deactivate_idempotent is not changed + # The next condition should be true for all conforming ACME servers. + # In case it is not true, it could be both an error in acme_account + # and in the ACME server. - account_deactivate_idempotent.account_uri is none - name: Validate that the account is gone (new account key) diff --git a/test/runner/lib/cloud/acme.py b/test/runner/lib/cloud/acme.py index 75bc597c33..e74edf8ee3 100644 --- a/test/runner/lib/cloud/acme.py +++ b/test/runner/lib/cloud/acme.py @@ -44,7 +44,7 @@ class ACMEProvider(CloudProvider): if os.environ.get('ANSIBLE_ACME_CONTAINER'): self.image = os.environ.get('ANSIBLE_ACME_CONTAINER') else: - self.image = 'quay.io/ansible/acme-test-container:1.4.1' + self.image = 'quay.io/ansible/acme-test-container:1.4.2' self.container_name = '' def _wait_for_service(self, protocol, acme_host, port, local_part, name):