def handle(self, country, state, city, org, ou, cn, **options): if os.path.exists(settings.CA_KEY): raise CommandError("%s: private key already exists." % settings.CA_KEY) if os.path.exists(settings.CA_CRT): raise CommandError("%s: public key already exists." % settings.CA_CRT) now = datetime.utcnow() expires = now + timedelta(days=options['expires']) key = crypto.PKey() key.generate_key(settings.CA_KEY_TYPE, settings.CA_BITSIZE) cert = crypto.X509() cert.get_subject().C = country cert.get_subject().ST = state cert.get_subject().L = city cert.get_subject().O = org cert.get_subject().OU = ou cert.get_subject().CN = cn cert.set_serial_number(uuid.uuid4().int) cert.set_notBefore(format_date(now - timedelta(minutes=5))) cert.set_notAfter(format_date(expires)) cert.set_issuer(cert.get_subject()) cert.set_pubkey(key) cert.sign(key, settings.DIGEST_ALGORITHM) cert.add_extensions([ crypto.X509Extension(str('basicConstraints'), True, str('CA:TRUE, pathlen:0')), crypto.X509Extension(str('keyUsage'), 0, str('keyCertSign,cRLSign')), crypto.X509Extension(str('subjectKeyIdentifier'), False, str('hash'), subject=cert), crypto.X509Extension(str('subjectAltName'), 0, str('DNS:%s' % cn)) ]) cert.add_extensions([ crypto.X509Extension(str('authorityKeyIdentifier'), False, str('keyid:always'), issuer=cert), ]) if options['password'] is None: args = [] elif options['password'] == '': args = [str('des3'), getpass()] else: args = [str('des3'), options['password']] oldmask = os.umask(247) with open(settings.CA_KEY, 'w') as key_file: # TODO: optionally add 'des3', 'passphrase' as args key_file.write(crypto.dump_privatekey(crypto.FILETYPE_PEM, key, *args)) with open(settings.CA_CRT, 'w') as cert_file: cert_file.write(crypto.dump_certificate(crypto.FILETYPE_PEM, cert)) os.umask(oldmask)
def from_csr(self, csr, subjectAltNames=None, key_usage=None, ext_key_usage=None, days=730, algorithm=None, watchers=None): # get algorithm used to sign certificate if algorithm is None: algorithm = settings.DIGEST_ALGORITHM if key_usage is None: key_usage = settings.CA_KEY_USAGE if ext_key_usage is None: ext_key_usage = settings.CA_EXT_KEY_USAGE # get certificate information req = crypto.load_certificate_request(crypto.FILETYPE_PEM, csr) subject = req.get_subject() cn = dict(subject.get_components()).get('CN') if cn is None: raise Exception('CSR has no CommonName!') # load CA key and cert with open(settings.CA_KEY) as ca_key: issuerKey = crypto.load_privatekey(crypto.FILETYPE_PEM, ca_key.read()) with open(settings.CA_CRT) as ca_crt: issuerPub = crypto.load_certificate(crypto.FILETYPE_PEM, ca_crt.read()) # compute notAfter info expires = datetime.today() + timedelta(days=days + 1) expires = expires.replace(hour=0, minute=0, second=0, microsecond=0) # create signed certificate cert = crypto.X509() cert.set_serial_number(uuid.uuid4().int) cert.set_notBefore(format_date(datetime.utcnow() - timedelta(minutes=5))) cert.set_notAfter(format_date(expires)) cert.set_issuer(issuerPub.get_subject()) cert.set_subject(req.get_subject()) cert.set_pubkey(req.get_pubkey()) # collect any extension extensions = [] # add subjectAltName if given: if subjectAltNames: subjData = str(','.join(['DNS:%s' % n for n in subjectAltNames])) ext = crypto.X509Extension(str('subjectAltName'), 0, subjData) extensions.append(ext) # set CRL distribution points: if settings.CA_CRL_DISTRIBUTION_POINTS: value = ','.join(['URI:%s' % uri for uri in settings.CA_CRL_DISTRIBUTION_POINTS]) extensions.append(crypto.X509Extension(str('crlDistributionPoints'), 0, str(value))) # Add issuerAltName if settings.CA_ISSUER_ALT_NAME: issuerAltName = str('URI:%s' % settings.CA_ISSUER_ALT_NAME) else: issuerAltName = str('issuer:copy') extensions.append(crypto.X509Extension(str('issuerAltName'), 0, issuerAltName, issuer=issuerPub)) # Add authorityInfoAccess auth_info_access = [] if settings.CA_OCSP: auth_info_access.append('OCSP;URI:%s' % settings.CA_OCSP) if settings.CA_ISSUER: auth_info_access.append('caIssuers;URI:%s' % settings.CA_ISSUER) if auth_info_access: auth_info_access = str(','.join(auth_info_access)) extensions.append(crypto.X509Extension(str('authorityInfoAccess'), 0, auth_info_access)) # add basicConstraints, keyUsage and extendedKeyUsage extensions.append(crypto.X509Extension(str('basicConstraints'), 0, str('CA:FALSE'))) extensions.append(crypto.X509Extension(str('keyUsage'), 0, str(','.join(key_usage)))) extensions.append(crypto.X509Extension(str('extendedKeyUsage'), 0, str(','.join(ext_key_usage)))) extensions.append(crypto.X509Extension(str('subjectKeyIdentifier'), 0, str('hash'), subject=cert)) extensions.append(crypto.X509Extension(str('authorityKeyIdentifier'), 0, str('keyid,issuer'), issuer=issuerPub)) cert.add_extensions(extensions) # finally sign the certificate: cert.sign(issuerKey, algorithm) # create database object crt = crypto.dump_certificate(crypto.FILETYPE_PEM, cert) obj = self.create(csr=csr, pub=crt, cn=cn, expires=expires) # add watchers: if watchers: obj.watchers.add(*watchers) return obj