From 82158aece60aa7ec68d81838e589a6dabe45685c Mon Sep 17 00:00:00 2001 From: Marti Raudsepp Date: Fri, 3 Aug 2018 13:21:45 +0300 Subject: [PATCH] Fill in missing cert rotation_policy; don't ignore validation errors when re-issuing certs CertificateInputSchema requires the rotation_policy field, but certificates created before the field existed have set to NULL. Thus saving such certificates failed and probably caused other errors. Made cert re-issuing (get_certificate_primitives) more strict so such errors are harder to miss in the future. --- lemur/certificates/service.py | 4 ++- lemur/migrations/versions/1db4f82bc780_.py | 33 ++++++++++++++++++++++ lemur/tests/conf.py | 3 +- lemur/tests/factories.py | 21 +++++++------- lemur/tests/test_certificates.py | 2 +- 5 files changed, 50 insertions(+), 13 deletions(-) create mode 100644 lemur/migrations/versions/1db4f82bc780_.py diff --git a/lemur/certificates/service.py b/lemur/certificates/service.py index 9b250fc3..a02c412c 100644 --- a/lemur/certificates/service.py +++ b/lemur/certificates/service.py @@ -514,7 +514,9 @@ def get_certificate_primitives(certificate): certificate via `create`. """ start, end = calculate_reissue_range(certificate.not_before, certificate.not_after) - data = CertificateInputSchema().load(CertificateOutputSchema().dump(certificate).data).data + ser = CertificateInputSchema().load(CertificateOutputSchema().dump(certificate).data) + assert not ser.errors, "Error re-serializing certificate: %s" % ser.errors + data = ser.data # we can't quite tell if we are using a custom name, as this is an automated process (typically) # we will rely on the Lemur generated name diff --git a/lemur/migrations/versions/1db4f82bc780_.py b/lemur/migrations/versions/1db4f82bc780_.py new file mode 100644 index 00000000..2d917e2e --- /dev/null +++ b/lemur/migrations/versions/1db4f82bc780_.py @@ -0,0 +1,33 @@ +"""Add default rotation_policy to certs where it's missing + +Revision ID: 1db4f82bc780 +Revises: 3adfdd6598df +Create Date: 2018-08-03 12:56:44.565230 + +""" + +# revision identifiers, used by Alembic. +revision = '1db4f82bc780' +down_revision = '3adfdd6598df' + +import logging + +from alembic import op + +log = logging.getLogger(__name__) + + +def upgrade(): + connection = op.get_bind() + + result = connection.execute("""\ + UPDATE certificates + SET rotation_policy_id=(SELECT id FROM rotation_policies WHERE name='default') + WHERE rotation_policy_id IS NULL + RETURNING id + """) + log.info("Filled rotation_policy for %d certificates" % result.rowcount) + + +def downgrade(): + pass diff --git a/lemur/tests/conf.py b/lemur/tests/conf.py index a815230b..71eb7cdc 100644 --- a/lemur/tests/conf.py +++ b/lemur/tests/conf.py @@ -23,7 +23,8 @@ LEMUR_ENCRYPTION_KEYS = 'o61sBLNBSGtAckngtNrfVNd8xy8Hp9LBGDstTbMbqCY=' # List of domain regular expressions that non-admin users can issue LEMUR_WHITELISTED_DOMAINS = [ - '^[a-zA-Z0-9-]+\.example\.com$' + '^[a-zA-Z0-9-]+\.example\.com$', + '^example\d+\.long\.com$', ] # Mail Server diff --git a/lemur/tests/factories.py b/lemur/tests/factories.py index 815c958d..af714425 100644 --- a/lemur/tests/factories.py +++ b/lemur/tests/factories.py @@ -31,6 +31,16 @@ class BaseFactory(SQLAlchemyModelFactory): sqlalchemy_session = db.session +class RotationPolicyFactory(BaseFactory): + """Rotation Factory.""" + name = Sequence(lambda n: 'policy{0}'.format(n)) + days = 30 + + class Meta: + """Factory configuration.""" + model = RotationPolicy + + class CertificateFactory(BaseFactory): """Certificate factory.""" name = Sequence(lambda n: 'certificate{0}'.format(n)) @@ -43,6 +53,7 @@ class CertificateFactory(BaseFactory): description = FuzzyText(length=128) active = True date_created = FuzzyDate(date(2016, 1, 1), date(2020, 1, 1)) + rotation_policy = SubFactory(RotationPolicyFactory) class Meta: """Factory Configuration.""" @@ -150,16 +161,6 @@ class AsyncAuthorityFactory(AuthorityFactory): authority_certificate = SubFactory(CertificateFactory) -class RotationPolicyFactory(BaseFactory): - """Rotation Factory.""" - name = Sequence(lambda n: 'policy{0}'.format(n)) - days = 30 - - class Meta: - """Factory configuration.""" - model = RotationPolicy - - class DestinationFactory(BaseFactory): """Destination factory.""" plugin_name = 'test-destination' diff --git a/lemur/tests/test_certificates.py b/lemur/tests/test_certificates.py index fff6e253..3215d56e 100644 --- a/lemur/tests/test_certificates.py +++ b/lemur/tests/test_certificates.py @@ -46,7 +46,7 @@ def test_get_certificate_primitives(certificate): with freeze_time(datetime.date(year=2016, month=10, day=30)): primitives = get_certificate_primitives(certificate) - assert len(primitives) == 24 + assert len(primitives) == 25 def test_certificate_output_schema(session, certificate, issuer_plugin):