#!/usr/bin/env python2 from OpenSSL import * PRIVATE_KEY = "/etc/pki/tls/private/scripts-2048.key" # PEM format with no passphrase SUBJECT_ATTRIBUTES = [ ("countryName", "US"), ("stateOrProvinceName", "Massachusetts"), ("localityName", "Cambridge"), ("organizationName", "Massachusetts Institute of Technology"), ("organizationalUnitName", "scripts.mit.edu web hosting service"), ("CN", None), # to be filled in below ("emailAddress", "scripts@mit.edu"), ] EXTENSIONS = [ # apparently OpenSSL marks CSR extensions as non-critical; it's not our # fault if the CA messes up and forgets CA:FALSE, right? ("basicConstraints", False, "CA:FALSE"), ("keyUsage", False, "nonRepudiation, digitalSignature, keyEncipherment"), ] def generate_csr(cn, alt_names=None): """ Generate a CSR for the given Common Name (a hostname) with the provided subjectAltName's (a list of hostnames) using the above settings. Returns a PEM string. """ req = crypto.X509Req() # set the subject fields (in the same order as OpenSSL XD) subject = req.get_subject() for attr, val in SUBJECT_ATTRIBUTES: if attr == "CN": # fills in the CN in the right place val = cn setattr(subject, attr, val) # subject.attr = val # initialize the extensions extensions = [] for type_name, critical, value in EXTENSIONS: ext = crypto.X509Extension(type_name, critical, value) extensions.append(ext) # ...including subjectAltName san_string = ", ".join("DNS:"+name for name in alt_names) ext = crypto.X509Extension("subjectAltName", False, san_string) extensions.append(ext) # and add them to the CSR req.add_extensions(extensions) # load the private key with open(PRIVATE_KEY) as f: pk_pem = f.read() private_key = crypto.load_privatekey(crypto.FILETYPE_PEM, pk_pem) # do the bit with the key! req.set_pubkey(private_key) # yeah...I know req.sign(private_key, "sha256") # dump the CSR to PEM return crypto.dump_certificate_request(crypto.FILETYPE_PEM, req) if __name__=="__main__": import sys if len(sys.argv) != 2: print "usage: %s HOSTNAME" % sys.argv[0] exit(1) hostname = sys.argv[1].lower() if not hostname.endswith(".mit.edu"): hostname += ".mit.edu" print generate_csr(hostname, [hostname]), # with subjectAltName print >> sys.stderr, "Generated a CSR for %s using %s" % ( hostname, PRIVATE_KEY) exit(0)