Commit 61dc78dc by ale

add update-crl command

1 parent c892b159
Pipeline #112 passed
in 1 minute 0 seconds
......@@ -57,6 +57,7 @@ class CA(object):
self._generate_ca_cert()
def renew_ca(self):
"""Renew the CA certificate itself (keeping the private key)."""
if not self.ca_key:
log.error('CA private key not available')
return
......@@ -64,14 +65,35 @@ class CA(object):
self._generate_ca_cert()
def get_ca(self):
"""Return the CA certificate (PEM-encoded)."""
return self.public_ca_pem
def make_certificate(self, subject_attrs, days=7, server=False):
"""Create a new certificate and private key.
Args:
subject_attrs: dict of X509 Subject attributes
days: days of validity of the new certificate
server: if True, create a server certificate, otherwise a
client one.
Returns:
A (private_key, certificate) pair.
"""
pkey = certutil.create_rsa_key_pair()
csr = certutil.create_cert_request(pkey, **subject_attrs)
return pkey, self.sign_certificate(csr, days, server)
def sign_certificate(self, req, days=365, server=False):
def sign_certificate(self, req, days=7, server=False):
"""Sign a certificate request.
Args:
req: CSR object
days: days of validity of the new certificate
server: if True, create a server certificate, otherwise a
client one.
Returns:
A X509 certificate, PEM-encoded.
"""
cn = req.get_subject().CN
log.info('sign request for cn=%s', cn)
cert = self.get_certificate(cn)
......@@ -97,7 +119,12 @@ class CA(object):
cn, crypto.dump_certificate(crypto.FILETYPE_PEM, cert))
return cert
def _update_crl(self):
def update_crl(self):
"""Update the CRL.
This function will generate a newly signed CRL every time it
is called.
"""
crl = crypto.CRL()
for serial, stamp in self.storage.get_revoked():
revoked = crypto.Revoked()
......@@ -125,6 +152,7 @@ class CA(object):
self.crl_data_der = pipe.communicate(self.crl_data_pem)[0]
def get_crl(self, format='der'):
"""Return the CRL (PEM- or DER-encoded)."""
if format == 'der':
return self.crl_data_der
else:
......@@ -139,20 +167,27 @@ class CA(object):
self.storage.delete_certificate(cn)
self.storage.add_revoked(serial_num)
self._update_crl()
self.update_crl()
def revoke_certificate(self, cn):
"""Revoke a certificate."""
serial_num = self.get_serial(cn)
if serial_num:
self._revoke_certificate(cn, serial_num)
def get_certificate(self, cn, raw=False):
"""Return a certificate given its subject.
If raw is True, the returned data will be in DER format,
otherwise it will be PEM-encoded.
"""
data = self.storage.get_certificate(cn)
if data and not raw:
data = crypto.load_certificate(crypto.FILETYPE_PEM, data)
return data
def get_serial(self, cn):
"""Return the serial number of the certificate given its subject."""
crt = self.get_certificate(cn, raw=False)
if crt:
return crt.get_serial_number()
......@@ -35,6 +35,9 @@ get-crl
to request a specific output format by passing the desired
format as second argument ("pem" or "der").
update-crl
Update the CRL on a local CA (requires --ca-path).
sign
Create a new certificate request and sign it. If the --server
option is not specified, a client certificate will be
......@@ -126,6 +129,10 @@ separated by slashes ('/'), for example:
parser.error('The "init" command is only valid with a local CA')
# Nothing to do, actually.
print 'Done.'
elif cmd == 'update-crl':
if not opts.ca_path:
parser.error('The "update-crl" command is only valid with a local CA')
client.update_crl()
else:
parser.error('Unknown command')
......
autoca (0.3.1) unstable; urgency=low
* Added command to update the CRL.
-- Autistici/Inventati <debian@autistici.org> Sat, 19 Nov 2016 09:53:16 +0000
autoca (0.3) unstable; urgency=low
* Initial Release.
......
......@@ -4,7 +4,7 @@ from setuptools import setup, find_packages
setup(
name="autoca",
version="0.3",
version="0.3.1",
description="Automated CA management.",
author="Ale",
author_email="ale@incal.net",
......
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!