Browse Source

consolidated external commandline execution error handling to bring back under 200 lines of code

Daniel Roesler 7 years ago
parent
commit
d1ccbecdfa
1 changed files with 9 additions and 14 deletions
  1. 9 14
      acme_tiny.py

+ 9 - 14
acme_tiny.py

@@ -20,11 +20,12 @@ def get_crt(account_key, csr, acme_dir, log=LOGGER, CA=DEFAULT_CA, disable_check
         return base64.urlsafe_b64encode(b).decode('utf8').replace("=", "")
         return base64.urlsafe_b64encode(b).decode('utf8').replace("=", "")
 
 
     # helper function - run external commands
     # helper function - run external commands
-    def _cmd(cmd_list, cmd_input=None):
-        stdin = subprocess.PIPE if cmd_input is not None else None
+    def _cmd(cmd_list, stdin=None, cmd_input=None, err_msg="Command Line Error"):
         proc = subprocess.Popen(cmd_list, stdin=stdin, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
         proc = subprocess.Popen(cmd_list, stdin=stdin, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
         out, err = proc.communicate(cmd_input)
         out, err = proc.communicate(cmd_input)
-        return proc, out, err
+        if proc.returncode != 0:
+            raise IOError("{0}\n{1}".format(err_msg, err))
+        return out
 
 
     # helper function - make request and automatically parse json response
     # helper function - make request and automatically parse json response
     def _do_request(url, data=None, err_msg="Error", depth=0):
     def _do_request(url, data=None, err_msg="Error", depth=0):
@@ -51,9 +52,7 @@ def get_crt(account_key, csr, acme_dir, log=LOGGER, CA=DEFAULT_CA, disable_check
         protected.update({"jwk": jwk} if acct_headers is None else {"kid": acct_headers['Location']})
         protected.update({"jwk": jwk} if acct_headers is None else {"kid": acct_headers['Location']})
         protected64 = _b64(json.dumps(protected).encode('utf8'))
         protected64 = _b64(json.dumps(protected).encode('utf8'))
         protected_input = "{0}.{1}".format(protected64, payload64).encode('utf8')
         protected_input = "{0}.{1}".format(protected64, payload64).encode('utf8')
-        proc, out, err = _cmd(["openssl", "dgst", "-sha256", "-sign", account_key], cmd_input=protected_input)
-        if proc.returncode != 0:
-            raise IOError("OpenSSL Error: {0}".format(err))
+        out = _cmd(["openssl", "dgst", "-sha256", "-sign", account_key], stdin=subprocess.PIPE, cmd_input=protected_input, err_msg="OpenSSL Error")
         data = json.dumps({"protected": protected64, "payload": payload64, "signature": _b64(out)})
         data = json.dumps({"protected": protected64, "payload": payload64, "signature": _b64(out)})
         try:
         try:
             return _do_request(url, data=data.encode('utf8'), err_msg=err_msg, depth=depth)
             return _do_request(url, data=data.encode('utf8'), err_msg=err_msg, depth=depth)
@@ -71,9 +70,7 @@ def get_crt(account_key, csr, acme_dir, log=LOGGER, CA=DEFAULT_CA, disable_check
 
 
     # parse account key to get public key
     # parse account key to get public key
     log.info("Parsing account key...")
     log.info("Parsing account key...")
-    proc, out, err = _cmd(["openssl", "rsa", "-in", account_key, "-noout", "-text"])
-    if proc.returncode != 0:
-        raise IOError("OpenSSL Error: {0}".format(err))
+    out = _cmd(["openssl", "rsa", "-in", account_key, "-noout", "-text"], err_msg="OpenSSL Error")
     pub_pattern = r"modulus:\n\s+00:([a-f0-9\:\s]+?)\npublicExponent: ([0-9]+)"
     pub_pattern = r"modulus:\n\s+00:([a-f0-9\:\s]+?)\npublicExponent: ([0-9]+)"
     pub_hex, pub_exp = re.search(pub_pattern, out.decode('utf8'), re.MULTILINE|re.DOTALL).groups()
     pub_hex, pub_exp = re.search(pub_pattern, out.decode('utf8'), re.MULTILINE|re.DOTALL).groups()
     pub_exp = "{0:x}".format(int(pub_exp))
     pub_exp = "{0:x}".format(int(pub_exp))
@@ -89,9 +86,7 @@ def get_crt(account_key, csr, acme_dir, log=LOGGER, CA=DEFAULT_CA, disable_check
 
 
     # find domains
     # find domains
     log.info("Parsing CSR...")
     log.info("Parsing CSR...")
-    proc, out, err = _cmd(["openssl", "req", "-in", csr, "-noout", "-text"])
-    if proc.returncode != 0:
-        raise IOError("Error loading {0}: {1}".format(csr, err))
+    out = _cmd(["openssl", "req", "-in", csr, "-noout", "-text"], err_msg="Error loading {0}".format(csr))
     domains = set([])
     domains = set([])
     common_name = re.search(r"Subject:.*? CN\s?=\s?([^\s,;/]+)", out.decode('utf8'))
     common_name = re.search(r"Subject:.*? CN\s?=\s?([^\s,;/]+)", out.decode('utf8'))
     if common_name is not None:
     if common_name is not None:
@@ -101,7 +96,7 @@ def get_crt(account_key, csr, acme_dir, log=LOGGER, CA=DEFAULT_CA, disable_check
         for san in subject_alt_names.group(1).split(", "):
         for san in subject_alt_names.group(1).split(", "):
             if san.startswith("DNS:"):
             if san.startswith("DNS:"):
                 domains.add(san[4:])
                 domains.add(san[4:])
-    log.info("Found domains: {}".format(", ".join(domains)))
+    log.info("Found domains: {0}".format(", ".join(domains)))
 
 
     # get the ACME directory of urls
     # get the ACME directory of urls
     log.info("Getting directory...")
     log.info("Getting directory...")
@@ -153,7 +148,7 @@ def get_crt(account_key, csr, acme_dir, log=LOGGER, CA=DEFAULT_CA, disable_check
 
 
     # finalize the order with the csr
     # finalize the order with the csr
     log.info("Signing certificate...")
     log.info("Signing certificate...")
-    proc, csr_der, err = _cmd(["openssl", "req", "-in", csr, "-outform", "DER"])
+    csr_der = _cmd(["openssl", "req", "-in", csr, "-outform", "DER"], err_msg="DER Export Error")
     _send_signed_request(order['finalize'], {"csr": _b64(csr_der)}, "Error finalizing order")
     _send_signed_request(order['finalize'], {"csr": _b64(csr_der)}, "Error finalizing order")
 
 
     # poll the order to monitor when it's done
     # poll the order to monitor when it's done