Commit de9a8def authored by Vincent Pelletier's avatar Vincent Pelletier

caucase.{ca,storage}: Stop storing the CRL PEM.

If a CRL is stored and contains bogus data (like a missing extension), it
is hard to trigger its renewal in a timely fashion. And because CRLs are
checked as often as possible, a bogus CRL can cause many operations types
to fail.
As caucased is not expected to be restarted very often, the extra CRL
generation on every start should not make a difference.
This uncovers an original breakage in caucase's CRL handling, with one test
failing. The fix will come in another commit.
parent d14f0222
......@@ -79,6 +79,8 @@ class CertificateAuthority(object):
- what x509.3 extensions and attributes are enforced on signed certificates
- CA and CRL automated renewal
"""
_current_crl = (None, None)
def __init__(
self,
storage,
......@@ -732,11 +734,11 @@ class CertificateAuthority(object):
"""
Return PEM-encoded certificate revocation list.
"""
crl_pem = self._storage.getCertificateRevocationList()
if crl_pem is None:
now = datetime.datetime.utcnow()
crl_pem, crl_expiration_date = self._current_crl
if crl_pem is None or crl_expiration_date > now:
ca_key_pair = self._getCurrentCAKeypair()
ca_crt = ca_key_pair['crt']
now = datetime.datetime.utcnow()
crl = x509.CertificateRevocationListBuilder(
issuer_name=ca_crt.issuer,
last_update=now,
......@@ -772,9 +774,9 @@ class CertificateAuthority(object):
backend=_cryptography_backend,
)
crl_pem = crl.public_bytes(serialization.Encoding.PEM)
self._storage.storeCertificateRevocationList(
self._current_crl = (
crl_pem,
expiration_date=utils.datetime2timestamp(now + self._crl_renew_time),
now + self._crl_renew_time,
)
return crl_pem
......
......@@ -131,10 +131,7 @@ class SQLite3Storage(local):
revocation_date INTEGER,
expiration_date INTEGER
);
CREATE TABLE IF NOT EXISTS %(prefix)scrl (
expiration_date INTEGER,
crl TEXT
);
DROP TABLE IF EXISTS %(prefix)scrl;
CREATE TABLE IF NOT EXISTS %(prefix)scounter (
name TEXT PRIMARY KEY,
value INTEGER
......@@ -476,9 +473,6 @@ class SQLite3Storage(local):
"""
with self._db as db:
c = db.cursor()
c.execute('DELETE FROM %scrl' % (
self._table_prefix,
))
try:
c.execute(
'INSERT INTO %srevoked '
......@@ -495,49 +489,12 @@ class SQLite3Storage(local):
except sqlite3.IntegrityError:
raise Found
def getCertificateRevocationList(self):
"""
Get PEM-encoded current Certificate Revocation List.
Returns None if there is no CRL.
"""
with self._db:
row = self._executeSingleRow(
'SELECT crl FROM %scrl '
'WHERE expiration_date > ? ORDER BY expiration_date DESC LIMIT 1' % (
self._table_prefix,
),
(time(), )
)
if row is not None:
return toBytes(row['crl'])
return None
def getNextCertificateRevocationListNumber(self):
"""
Get next CRL sequence number.
"""
return self._incrementCounter('crl_number')
def storeCertificateRevocationList(self, crl, expiration_date):
"""
Store Certificate Revocation List.
"""
with self._db as db:
c = db.cursor()
c.execute('DELETE FROM %scrl' % (
self._table_prefix,
))
c.execute(
'INSERT INTO %scrl (expiration_date, crl) VALUES (?, ?)' % (
self._table_prefix,
),
(
int(expiration_date),
crl,
),
)
def getRevocationList(self):
"""
Get the list of all revoked certificates.
......
......@@ -1137,12 +1137,6 @@ class CaucaseTest(unittest.TestCase):
now = now.replace(microsecond=0)
# Sanity check: pre-existing CRL creation should be strictly in the past
self.assertLess(reference_crl.last_update, now)
# Store a dummy, already expired CRL, just to force a new one to be
# generated on next server start.
SQLite3Storage(
self._server_db,
table_prefix='cas',
).storeCertificateRevocationList('', 0)
self._startServer()
self._runClient()
new_crl = self._getClientCRL()
......@@ -2367,7 +2361,7 @@ class CaucaseTest(unittest.TestCase):
table_prefix='cau',
).dumpIterator())
CRL_INSERT = b'INSERT INTO "caucrl" '
CRLCOUNTER_INSERT = b'INSERT INTO "caucounter" VALUES(\'crl_number\','
CRT_INSERT = b'INSERT INTO "caucrt" '
REV_INSERT = b'INSERT INTO "caurevoked" '
def filterBackup(backup, expect_rev):
......@@ -2377,10 +2371,12 @@ class CaucaseTest(unittest.TestCase):
database) can be tested to be equal.
"""
rev_found = not expect_rev
crl_counter_found = False
new_backup = []
crt_list = []
for row in backup:
if row.startswith(CRL_INSERT):
if row.startswith(CRLCOUNTER_INSERT):
crl_counter_found = True
continue
if row.startswith(CRT_INSERT):
crt_list.append(row)
......@@ -2389,6 +2385,7 @@ class CaucaseTest(unittest.TestCase):
assert not rev_found, 'Unexpected revocation found'
continue
new_backup.append(row)
assert crl_counter_found
return new_backup, crt_list
before_backup, before_crt_list = filterBackup(
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment