diff --git a/changelogs/fragments/173-acme_certificate-wrong-challenge.yml b/changelogs/fragments/173-acme_certificate-wrong-challenge.yml new file mode 100644 index 00000000..9826d0c3 --- /dev/null +++ b/changelogs/fragments/173-acme_certificate-wrong-challenge.yml @@ -0,0 +1,2 @@ +bugfixes: +- "acme_certificate - error when requested challenge type is not found for non-valid challenges, instead of hanging on step 2 (https://github.com/ansible-collections/community.crypto/issues/171, https://github.com/ansible-collections/community.crypto/pull/173)." diff --git a/plugins/modules/acme_certificate.py b/plugins/modules/acme_certificate.py index cf16051a..1f204933 100644 --- a/plugins/modules/acme_certificate.py +++ b/plugins/modules/acme_certificate.py @@ -738,11 +738,13 @@ class ACMEClient(object): Validate the authorization provided in the auth dict. Returns True when the validation was successful and False when it was not. ''' + found_challenge = False for challenge in auth['challenges']: if self.challenge != challenge['type']: continue uri = challenge['uri'] if self.version == 1 else challenge['url'] + found_challenge = True challenge_response = {} if self.version == 1: @@ -755,6 +757,10 @@ class ACMEClient(object): if info['status'] not in [200, 202]: raise ModuleFailException("Error validating challenge: CODE: {0} RESULT: {1}".format(info['status'], result)) + if not found_challenge: + raise ModuleFailException("Found no challenge of type '{0}' for identifier {1}:{2}!".format( + self.challenge, identifier_type, identifier)) + status = '' while status not in ['valid', 'invalid', 'revoked']: @@ -945,7 +951,7 @@ class ACMEClient(object): self._new_order_v2() self.changed = True - def get_challenges_data(self): + def get_challenges_data(self, first_step): ''' Get challenge details for the chosen challenge type. Return a tuple of generic challenge details, and specialized DNS challenge details. @@ -961,6 +967,9 @@ class ACMEClient(object): continue # We drop the type from the key to preserve backwards compatibility data[identifier] = self._get_challenge_data(auth, identifier_type, identifier) + if first_step and self.challenge not in data[identifier]: + raise ModuleFailException("Found no challenge of type '{0}' for identifier {1}!".format( + self.challenge, type_identifier)) # Get DNS challenge data data_dns = {} if self.challenge == 'dns-01': @@ -1247,7 +1256,8 @@ def main(): client = ACMEClient(module) client.cert_days = cert_days other = dict() - if client.is_first_step(): + is_first_step = client.is_first_step() + if is_first_step: # First run: start challenges / start new order client.start_challenges() else: @@ -1260,7 +1270,7 @@ def main(): finally: if module.params['deactivate_authzs']: client.deactivate_authzs() - data, data_dns = client.get_challenges_data() + data, data_dns = client.get_challenges_data(first_step=is_first_step) auths = dict() for k, v in client.authorizations.items(): # Remove "type:" from key