Commit aebde7ae authored by Daniel Roesler's avatar Daniel Roesler

added propper logging, but needs code reduction to bring back below 200 lines

parent ee20af39
#!/usr/bin/env python
import argparse, subprocess, json, os, sys, base64, binascii, time, hashlib, re, copy, textwrap
import argparse, subprocess, json, os, sys, base64, binascii, time, hashlib, re, copy, textwrap, logging
try:
from urllib.request import urlopen # Python 3
except ImportError:
......@@ -8,14 +8,18 @@ except ImportError:
#CA = "https://acme-staging.api.letsencrypt.org"
CA = "https://acme-v01.api.letsencrypt.org"
def get_crt(account_key, csr, acme_dir):
LOGGER = logging.getLogger(__name__)
LOGGER.addHandler(logging.StreamHandler())
LOGGER.setLevel(logging.INFO)
def get_crt(account_key, csr, acme_dir, log=LOGGER):
# helper function base64 encode for jose spec
def _b64(b):
return base64.urlsafe_b64encode(b).decode('utf8').replace("=", "")
# parse account key to get public key
sys.stderr.write("Parsing account key...")
log.info("Parsing account key...")
proc = subprocess.Popen(["openssl", "rsa", "-in", account_key, "-noout", "-text"],
stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
out, err = proc.communicate()
......@@ -39,7 +43,6 @@ def get_crt(account_key, csr, acme_dir):
}
accountkey_json = json.dumps(header['jwk'], sort_keys=True, separators=(',', ':'))
thumbprint = _b64(hashlib.sha256(accountkey_json.encode('utf8')).digest())
sys.stderr.write("parsed!\n")
# helper function make signed requests
def _send_signed_request(url, payload):
......@@ -66,7 +69,7 @@ def get_crt(account_key, csr, acme_dir):
return e.code, e.read()
# find domains
sys.stderr.write("Parsing CSR...")
log.info("Parsing CSR...")
proc = subprocess.Popen(["openssl", "req", "-in", csr, "-noout", "-text"],
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
out, err = proc.communicate()
......@@ -81,24 +84,23 @@ def get_crt(account_key, csr, acme_dir):
for san in subject_alt_names.group(1).split(", "):
if san.startswith("DNS:"):
domains.add(san[4:])
sys.stderr.write("parsed!\n")
# get the certificate domains and expiration
sys.stderr.write("Registering account...")
log.info("Registering account...")
code, result = _send_signed_request(CA + "/acme/new-reg", {
"resource": "new-reg",
"agreement": "https://letsencrypt.org/documents/LE-SA-v1.0.1-July-27-2015.pdf",
})
if code == 201:
sys.stderr.write("registered!\n")
log.info("Registered!")
elif code == 409:
sys.stderr.write("already registered!\n")
log.info("Already registered!")
else:
raise ValueError("Error registering: {0} {1}".format(code, result))
# verify each domain
for domain in domains:
sys.stderr.write("Verifying {0}...".format(domain))
log.info("Verifying {0}...".format(domain))
# get new challenge
code, result = _send_signed_request(CA + "/acme/new-authz", {
......@@ -147,7 +149,7 @@ def get_crt(account_key, csr, acme_dir):
if challenge_status['status'] == "pending":
time.sleep(2)
elif challenge_status['status'] == "valid":
sys.stderr.write("verified!\n")
log.info("{0} verified!".format(domain))
os.remove(wellknown_path)
break
else:
......@@ -155,7 +157,7 @@ def get_crt(account_key, csr, acme_dir):
domain, challenge_status))
# get the new certificate
sys.stderr.write("Signing certificate...")
log.info("Signing certificate...")
proc = subprocess.Popen(["openssl", "req", "-in", csr, "-outform", "DER"],
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
csr_der, err = proc.communicate()
......@@ -167,7 +169,7 @@ def get_crt(account_key, csr, acme_dir):
raise ValueError("Error signing certificate: {0} {1}".format(code, result))
# return signed certificate!
sys.stderr.write("signed!\n")
log.info("Certificate signed!")
return """-----BEGIN CERTIFICATE-----\n{0}\n-----END CERTIFICATE-----\n""".format(
"\n".join(textwrap.wrap(base64.b64encode(result).decode('utf8'), 64)))
......@@ -192,7 +194,9 @@ if __name__ == "__main__":
parser.add_argument("--account-key", required=True, help="path to your Let's Encrypt account private key")
parser.add_argument("--csr", required=True, help="path to your certificate signing request")
parser.add_argument("--acme-dir", required=True, help="path to the .well-known/acme-challenge/ directory")
parser.add_argument("--quiet", action="store_const", const=logging.ERROR, help="suppress output except for errors")
args = parser.parse_args()
signed_crt = get_crt(args.account_key, args.csr, args.acme_dir)
LOGGER.setLevel(args.quiet or LOGGER.level)
signed_crt = get_crt(args.account_key, args.csr, args.acme_dir, LOGGER)
sys.stdout.write(signed_crt)
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment