Skip to content
Snippets Groups Projects
Commit 61dc78dc authored by ale's avatar ale
Browse files

add update-crl command

parent c892b159
No related branches found
No related tags found
No related merge requests found
...@@ -57,6 +57,7 @@ class CA(object): ...@@ -57,6 +57,7 @@ class CA(object):
self._generate_ca_cert() self._generate_ca_cert()
def renew_ca(self): def renew_ca(self):
"""Renew the CA certificate itself (keeping the private key)."""
if not self.ca_key: if not self.ca_key:
log.error('CA private key not available') log.error('CA private key not available')
return return
...@@ -64,14 +65,35 @@ class CA(object): ...@@ -64,14 +65,35 @@ class CA(object):
self._generate_ca_cert() self._generate_ca_cert()
def get_ca(self): def get_ca(self):
"""Return the CA certificate (PEM-encoded)."""
return self.public_ca_pem return self.public_ca_pem
def make_certificate(self, subject_attrs, days=7, server=False): 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() pkey = certutil.create_rsa_key_pair()
csr = certutil.create_cert_request(pkey, **subject_attrs) csr = certutil.create_cert_request(pkey, **subject_attrs)
return pkey, self.sign_certificate(csr, days, server) 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 cn = req.get_subject().CN
log.info('sign request for cn=%s', cn) log.info('sign request for cn=%s', cn)
cert = self.get_certificate(cn) cert = self.get_certificate(cn)
...@@ -97,7 +119,12 @@ class CA(object): ...@@ -97,7 +119,12 @@ class CA(object):
cn, crypto.dump_certificate(crypto.FILETYPE_PEM, cert)) cn, crypto.dump_certificate(crypto.FILETYPE_PEM, cert))
return 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() crl = crypto.CRL()
for serial, stamp in self.storage.get_revoked(): for serial, stamp in self.storage.get_revoked():
revoked = crypto.Revoked() revoked = crypto.Revoked()
...@@ -125,6 +152,7 @@ class CA(object): ...@@ -125,6 +152,7 @@ class CA(object):
self.crl_data_der = pipe.communicate(self.crl_data_pem)[0] self.crl_data_der = pipe.communicate(self.crl_data_pem)[0]
def get_crl(self, format='der'): def get_crl(self, format='der'):
"""Return the CRL (PEM- or DER-encoded)."""
if format == 'der': if format == 'der':
return self.crl_data_der return self.crl_data_der
else: else:
...@@ -139,20 +167,27 @@ class CA(object): ...@@ -139,20 +167,27 @@ class CA(object):
self.storage.delete_certificate(cn) self.storage.delete_certificate(cn)
self.storage.add_revoked(serial_num) self.storage.add_revoked(serial_num)
self._update_crl() self.update_crl()
def revoke_certificate(self, cn): def revoke_certificate(self, cn):
"""Revoke a certificate."""
serial_num = self.get_serial(cn) serial_num = self.get_serial(cn)
if serial_num: if serial_num:
self._revoke_certificate(cn, serial_num) self._revoke_certificate(cn, serial_num)
def get_certificate(self, cn, raw=False): 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) data = self.storage.get_certificate(cn)
if data and not raw: if data and not raw:
data = crypto.load_certificate(crypto.FILETYPE_PEM, data) data = crypto.load_certificate(crypto.FILETYPE_PEM, data)
return data return data
def get_serial(self, cn): def get_serial(self, cn):
"""Return the serial number of the certificate given its subject."""
crt = self.get_certificate(cn, raw=False) crt = self.get_certificate(cn, raw=False)
if crt: if crt:
return crt.get_serial_number() return crt.get_serial_number()
...@@ -35,6 +35,9 @@ get-crl ...@@ -35,6 +35,9 @@ get-crl
to request a specific output format by passing the desired to request a specific output format by passing the desired
format as second argument ("pem" or "der"). format as second argument ("pem" or "der").
update-crl
Update the CRL on a local CA (requires --ca-path).
sign sign
Create a new certificate request and sign it. If the --server Create a new certificate request and sign it. If the --server
option is not specified, a client certificate will be option is not specified, a client certificate will be
...@@ -126,6 +129,10 @@ separated by slashes ('/'), for example: ...@@ -126,6 +129,10 @@ separated by slashes ('/'), for example:
parser.error('The "init" command is only valid with a local CA') parser.error('The "init" command is only valid with a local CA')
# Nothing to do, actually. # Nothing to do, actually.
print 'Done.' 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: else:
parser.error('Unknown command') 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 autoca (0.3) unstable; urgency=low
* Initial Release. * Initial Release.
......
...@@ -4,7 +4,7 @@ from setuptools import setup, find_packages ...@@ -4,7 +4,7 @@ from setuptools import setup, find_packages
setup( setup(
name="autoca", name="autoca",
version="0.3", version="0.3.1",
description="Automated CA management.", description="Automated CA management.",
author="Ale", author="Ale",
author_email="ale@incal.net", author_email="ale@incal.net",
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment