From 61dc78dc2a2755e230d6334a30fdd4bfbef76229 Mon Sep 17 00:00:00 2001
From: ale <ale@incal.net>
Date: Sat, 19 Nov 2016 09:54:33 +0000
Subject: [PATCH] add update-crl command

---
 autoca/ca.py      | 41 ++++++++++++++++++++++++++++++++++++++---
 autoca/ca_tool.py |  7 +++++++
 debian/changelog  |  6 ++++++
 setup.py          |  2 +-
 4 files changed, 52 insertions(+), 4 deletions(-)

diff --git a/autoca/ca.py b/autoca/ca.py
index 33ffefb..2e5818b 100644
--- a/autoca/ca.py
+++ b/autoca/ca.py
@@ -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()
diff --git a/autoca/ca_tool.py b/autoca/ca_tool.py
index 6b43af4..7dc158a 100644
--- a/autoca/ca_tool.py
+++ b/autoca/ca_tool.py
@@ -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')
 
diff --git a/debian/changelog b/debian/changelog
index 8de6ff6..87b4263 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,9 @@
+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.
diff --git a/setup.py b/setup.py
index face0d1..b6ee62a 100755
--- a/setup.py
+++ b/setup.py
@@ -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",
-- 
GitLab