From 3570baacda94bfbca3c6f26151052c963eb9bee9 Mon Sep 17 00:00:00 2001 From: Kishi85 Date: Tue, 12 Feb 2019 10:27:53 +0100 Subject: [PATCH] standalone: Fix server start+stop with multiple handlers --- authority/v1.py | 58 +++++++++++++++++++++++++-------------------- modes/abstract.py | 8 +++++++ modes/standalone.py | 7 ++---- 3 files changed, 42 insertions(+), 31 deletions(-) diff --git a/authority/v1.py b/authority/v1.py index e180754..063a04d 100644 --- a/authority/v1.py +++ b/authority/v1.py @@ -131,34 +131,40 @@ class ACMEAuthority(AbstractACMEAuthority): time.sleep(1) for domain in domains: - print("Starting key authorization") - # notify challenge are met - keyauthorization = "{0}.{1}".format(tokens[domain], account_thumbprint) - code, result = self._send_signed(challenges[domain]['uri'], header, { - "resource": "challenge", - "keyAuthorization": keyauthorization, - }) - if code != 202: - raise ValueError("Error triggering challenge: {0} {1}".format(code, result)) + challenge_handlers[domain].start_challenge() + try: + print("Starting key authorization") + # notify challenge are met + keyauthorization = "{0}.{1}".format(tokens[domain], account_thumbprint) + code, result = self._send_signed(challenges[domain]['uri'], header, { + "resource": "challenge", + "keyAuthorization": keyauthorization, + }) + if code != 202: + raise ValueError("Error triggering challenge: {0} {1}".format(code, result)) - # wait for challenge to be verified - while True: - try: - resp = urlopen(challenges[domain]['uri']) - challenge_status = json.loads(resp.read().decode('utf8')) - except IOError as e: - raise ValueError("Error checking challenge: {0} {1}".format( - e.code, json.loads(e.read().decode('utf8')))) - if challenge_status['status'] == "pending": - time.sleep(2) - elif challenge_status['status'] == "valid": - print("{0} verified!".format(domain)) - break - else: - raise ValueError("{0} challenge did not pass: {1}".format( - domain, challenge_status)) + # wait for challenge to be verified + while True: + try: + resp = urlopen(challenges[domain]['uri']) + challenge_status = json.loads(resp.read().decode('utf8')) + except IOError as e: + raise ValueError("Error checking challenge: {0} {1}".format( + e.code, json.loads(e.read().decode('utf8')))) + if challenge_status['status'] == "pending": + time.sleep(2) + elif challenge_status['status'] == "valid": + print("{0} verified!".format(domain)) + break + else: + raise ValueError("{0} challenge did not pass: {1}".format( + domain, challenge_status)) + finally: + challenge_handlers[domain].stop_challenge() finally: - for domain in domains: + # Destroy challenge handlers in reverse order to replay + # any saved state information in the handlers correctly + for domain in reversed(domains): try: challenge_handlers[domain].destroy_challenge(domain, account_thumbprint, tokens[domain]) except: diff --git a/modes/abstract.py b/modes/abstract.py index 55f0f82..9714b15 100644 --- a/modes/abstract.py +++ b/modes/abstract.py @@ -20,3 +20,11 @@ class AbstractChallengeHandler: def destroy_challenge(self, domain, thumbprint, token): raise NotImplemented + + # Optional: Indicate when a challenge request is imminent + def start_challenge(self): + pass + + # Optional: Indicate when a challenge response has been received + def stop_challenge(self): + pass diff --git a/modes/standalone.py b/modes/standalone.py index 35b1397..687dd37 100644 --- a/modes/standalone.py +++ b/modes/standalone.py @@ -70,15 +70,12 @@ class ChallengeHandler(WebChallengeHandler): self.server_thread = None self.server = HTTPServer(("", port), ACMERequestHandler) - def create_challenge(self, domain, thumbprint, token): - WebChallengeHandler.create_challenge(self, domain, thumbprint, token) + def start_challenge(self): self.server_thread = threading.Thread(target=start_standalone, args=(self.server,)) os.chdir(self.challenge_directory) self.server_thread.start() - return datetime.datetime.now() - def destroy_challenge(self, domain, thumbprint, token): + def stop_challenge(self): self.server.shutdown() self.server_thread.join() os.chdir(self.current_directory) - WebChallengeHandler.destroy_challenge(self, domain, thumbprint, token)