From 2da9754ffa271fa4f9ac9e74c59bac8184b2bcbc Mon Sep 17 00:00:00 2001 From: Jasmine Schladen Date: Wed, 17 Mar 2021 10:51:21 -0700 Subject: [PATCH] Security fixes --- lemur/authorities/service.py | 6 ++++++ lemur/dns_providers/schemas.py | 2 +- lemur/tests/conftest.py | 8 ++++++++ lemur/tests/factories.py | 17 ++++++++++++++++- lemur/tests/test_dns_providers.py | 16 ++++++++++++++++ 5 files changed, 47 insertions(+), 2 deletions(-) diff --git a/lemur/authorities/service.py b/lemur/authorities/service.py index 0913e629..5719d052 100644 --- a/lemur/authorities/service.py +++ b/lemur/authorities/service.py @@ -117,6 +117,12 @@ def create(**kwargs): """ Creates a new authority. """ + ca_name = kwargs.get("name") + if get_by_name(ca_name): + raise Exception(f"Authority with name {ca_name} already exists") + if role_service.get_by_name(f"{ca_name}_admin") or role_service.get_by_name(f"{ca_name}_operator"): + raise Exception(f"Admin and/or operator roles for authority {ca_name} already exist") + body, private_key, chain, roles = mint(**kwargs) kwargs["creator"].roles = list(set(list(kwargs["creator"].roles) + roles)) diff --git a/lemur/dns_providers/schemas.py b/lemur/dns_providers/schemas.py index af9377b3..27f7c182 100644 --- a/lemur/dns_providers/schemas.py +++ b/lemur/dns_providers/schemas.py @@ -10,9 +10,9 @@ class DnsProvidersNestedOutputSchema(LemurOutputSchema): name = fields.String() provider_type = fields.String() description = fields.String() - credentials = fields.String() api_endpoint = fields.String() date_created = ArrowDateTime() + # credentials are intentionally omitted (they are input-only) class DnsProvidersNestedInputSchema(LemurInputSchema): diff --git a/lemur/tests/conftest.py b/lemur/tests/conftest.py index f388acc6..482424bf 100644 --- a/lemur/tests/conftest.py +++ b/lemur/tests/conftest.py @@ -36,6 +36,7 @@ from .factories import ( InvalidCertificateFactory, CryptoAuthorityFactory, CACertificateFactory, + DnsProviderFactory, ) @@ -183,6 +184,13 @@ def user(session): return {"user": u, "token": token} +@pytest.fixture +def dns_provider(session): + d = DnsProviderFactory() + session.commit() + return d + + @pytest.fixture def pending_certificate(session): u = UserFactory() diff --git a/lemur/tests/factories.py b/lemur/tests/factories.py index fea4c59a..ed2ec525 100644 --- a/lemur/tests/factories.py +++ b/lemur/tests/factories.py @@ -1,14 +1,15 @@ +import json from datetime import date from factory import Sequence, post_generation, SubFactory from factory.alchemy import SQLAlchemyModelFactory from factory.fuzzy import FuzzyChoice, FuzzyText, FuzzyDate, FuzzyInteger - from lemur.database import db from lemur.authorities.models import Authority from lemur.certificates.models import Certificate from lemur.destinations.models import Destination +from lemur.dns_providers.models import DnsProvider from lemur.sources.models import Source from lemur.notifications.models import Notification from lemur.pending_certificates.models import PendingCertificate @@ -435,3 +436,17 @@ class PendingCertificateFactory(BaseFactory): if extracted: for domain in extracted: self.roles.append(domain) + + +class DnsProviderFactory(BaseFactory): + """DnsProvider Factory.""" + + name = Sequence(lambda n: f"dnsProvider{n}") + description = FuzzyText(length=128) + provider_type = FuzzyText(length=128) + credentials = json.dumps({"account_id": f"{FuzzyInteger(100000, 999999).fuzz()}"}) + + class Meta: + """Factory Configuration.""" + + model = DnsProvider diff --git a/lemur/tests/test_dns_providers.py b/lemur/tests/test_dns_providers.py index 9b8fdb5a..7bd73037 100644 --- a/lemur/tests/test_dns_providers.py +++ b/lemur/tests/test_dns_providers.py @@ -1,5 +1,7 @@ +import json import unittest from lemur.dns_providers import util as dnsutil +from lemur.dns_providers.schemas import dns_provider_output_schema class TestDNSProvider(unittest.TestCase): @@ -21,3 +23,17 @@ class TestDNSProvider(unittest.TestCase): self.assertFalse(dnsutil.is_valid_domain('example..io')) self.assertFalse(dnsutil.is_valid_domain('exa mple.io')) self.assertFalse(dnsutil.is_valid_domain('-')) + + +def test_output_schema(dns_provider): + # no credentials using the output schema dump + assert dns_provider.credentials + assert json.loads(dns_provider.credentials)["account_id"] + dump = dns_provider_output_schema.dump(dns_provider).data + assert 'name' in dump + assert 'credentials' not in dump + + +def test_json(dns_provider): + # we can still get credentials using json.load + assert 'account_id' in json.loads(dns_provider.credentials)