diff options
-rw-r--r-- | README.md | 10 | ||||
-rw-r--r-- | acmens.py | 125 |
2 files changed, 63 insertions, 72 deletions
@@ -32,13 +32,11 @@ This is the key that you will get signed for free for your domain (replace and CSR for your domain, you can skip this step. ```sh -#Create a CSR for example.com -openssl genrsa -aes256 4096 > domain.key -openssl req -new -sha256 -key domain.key -subj "/CN=example.com" > domain.csr +# Generate domain key. +openssl genrsa -aes256 -out domain.key 4096 -#Alternatively, if you want both example.com and www.example.com -openssl genrsa -aes256 4096 > domain.key -openssl req -new -sha256 -key domain.key -subj "/" -reqexts SAN -config <(cat /etc/ssl/openssl.cnf <(printf "[SAN]\nsubjectAltName=DNS:example.com,DNS:www.example.com")) > domain.csr +# Generate CSR +openssl req -new -sha256 -key domain.key -out domain.csr ``` Third, you run the script using python and passing in the path to your user @@ -105,20 +105,15 @@ def sign_csr(account_key, csr, email=None): # Step 2: Get the domain names to be certified sys.stderr.write("Reading csr file...\n") out = _cmd(["openssl", "req", "-in", csr, "-noout", "-text"], err_msg="Error loading {}".format(csr)) - domains = set([]) + domain = None common_name = re.search("Subject:.*? CN *= *([^\s,;/]+)", out.decode('utf8')) if common_name is not None: - domains.add(common_name.group(1)) - subject_alt_names = re.search("X509v3 Subject Alternative Name: \n +([^\n]+)\n", out.decode('utf8'), re.MULTILINE|re.DOTALL) - if subject_alt_names is not None: - for san in subject_alt_names.group(1).split(", "): - if san.startswith("DNS:"): - domains.add(san[4:]) - sys.stderr.write("Found domains {0}\n".format(", ".join(domains))) + domain = common_name.group(1) + sys.stderr.write("Found domain {0}\n".format(domain)) # Step 3: Ask user for contact email if not email: - default_email = "webmaster@{0}".format(min(domains, key=len)) + default_email = "webmaster@{0}".format(domain) stdout = sys.stdout sys.stdout = sys.stderr input_email = input("STEP 1: What is your contact email? ({0}) ".format(default_email)) @@ -139,37 +134,36 @@ def sign_csr(account_key, csr, email=None): sys.stderr.write("Already registered!\n") - # Step 5: Request challenges for each domain - for domain in domains: - sys.stderr.write("Making new order for {0}...\n".format(domain)) - id = { - "identifiers": [{ - "type": "dns", - "value": domain, - }], - } - order, order_code, order_headers = _send_signed_request(DIRECTORY['newOrder'], id, "Error creating new order") - - # Request challenges - sys.stderr.write("Requesting challenges...\n") - chl_result, chl_code, chl_headers = _send_signed_request(order['authorizations'][0], None, "Error getting challenges") - - challenge = [c for c in chl_result['challenges'] if c['type'] == "http-01"][0] - token = re.sub(r"[^A-Za-z0-9_\-]", "_", challenge['token']) - keyauthorization = "{0}.{1}".format(challenge['token'], thumbprint) - - # build request for the server to test this challenge. - test_url = challenge['url'] - test_raw = "{}" - - # challenge response for server - response = { - "uri": ".well-known/acme-challenge/{0}".format(challenge['token']), - "data": keyauthorization, - } - - # Step 6: Ask the user to host the token on their server - sys.stderr.write("""\ + # Step 5: Request challenges for domain + sys.stderr.write("Making new order for {0}...\n".format(domain)) + id = { + "identifiers": [{ + "type": "dns", + "value": domain, + }], + } + order, order_code, order_headers = _send_signed_request(DIRECTORY['newOrder'], id, "Error creating new order") + + # Request challenges + sys.stderr.write("Requesting challenges...\n") + chl_result, chl_code, chl_headers = _send_signed_request(order['authorizations'][0], None, "Error getting challenges") + + challenge = [c for c in chl_result['challenges'] if c['type'] == "http-01"][0] + token = re.sub(r"[^A-Za-z0-9_\-]", "_", challenge['token']) + keyauthorization = "{0}.{1}".format(challenge['token'], thumbprint) + + # build request for the server to test this challenge. + test_url = challenge['url'] + test_raw = "{}" + + # challenge response for server + response = { + "uri": ".well-known/acme-challenge/{0}".format(challenge['token']), + "data": keyauthorization, + } + + # Step 6: Ask the user to host the token on their server + sys.stderr.write("""\ Please update your server to serve the following file at this URL: -------------- @@ -183,32 +177,31 @@ Notes: """.format(domain, response['uri'], response['data'])) - stdout = sys.stdout - sys.stdout = sys.stderr - input("Press Enter when you've got the file hosted on your server...") - sys.stdout = stdout - - # Step 7: Let the CA know you're ready for the challenge - sys.stderr.write("Requesting verification for {0}...\n".format(domain)) - _send_signed_request(challenge['url'], {}, "Error requesting challenge verfication: {0}".format(domain)) - chl_verification = _poll_until_not(challenge['url'], ["pending"], "Error checking challenge verification") - if chl_verification['status'] != "valid": - raise ValueError("Challenge did not pass for {0}: {1}".format(domain, chl_verification)) - sys.stderr.write("{} verified!\n".format(domain)) - - # Step 8: Finalize - csr_der = _cmd(["openssl", "req", "-in", csr, "-outform", "DER"], err_msg="DER Export Error") - fnlz_resp, fnlz_code, fnlz_headers = _send_signed_request(order['finalize'], {"csr": _b64(csr_der)}, "Error finalizing order") - - # Step 9: Wait for CA to mark test as valid - sys.stderr.write("Waiting for {0} challenge to pass...\n".format(domain)) - order = _poll_until_not(order_headers['Location'], ["pending", "processing"], "Error checking order status") - - if order['status'] == "valid": - sys.stderr.write("Passed {0} challenge!\n".format(domain)) - else: - raise ValueError("'{0}' challenge did not pass: {1}".format(domain, order)) - + stdout = sys.stdout + sys.stdout = sys.stderr + input("Press Enter when you've got the file hosted on your server...") + sys.stdout = stdout + + # Step 7: Let the CA know you're ready for the challenge + sys.stderr.write("Requesting verification for {0}...\n".format(domain)) + _send_signed_request(challenge['url'], {}, "Error requesting challenge verfication: {0}".format(domain)) + chl_verification = _poll_until_not(challenge['url'], ["pending"], "Error checking challenge verification") + if chl_verification['status'] != "valid": + raise ValueError("Challenge did not pass for {0}: {1}".format(domain, chl_verification)) + sys.stderr.write("{} verified!\n".format(domain)) + + # Step 8: Finalize + csr_der = _cmd(["openssl", "req", "-in", csr, "-outform", "DER"], err_msg="DER Export Error") + fnlz_resp, fnlz_code, fnlz_headers = _send_signed_request(order['finalize'], {"csr": _b64(csr_der)}, "Error finalizing order") + + # Step 9: Wait for CA to mark test as valid + sys.stderr.write("Waiting for {0} challenge to pass...\n".format(domain)) + order = _poll_until_not(order_headers['Location'], ["pending", "processing"], "Error checking order status") + + if order['status'] == "valid": + sys.stderr.write("Passed {0} challenge!\n".format(domain)) + else: + raise ValueError("'{0}' challenge did not pass: {1}".format(domain, order)) # Step 10: Get the certificate. sys.stderr.write("Getting certificate...\n") |