def get_certificate_primitives(certificate): """ Retrieve key primitive from a certificate such that the certificate could be recreated with new expiration or be used to build upon. :param certificate: :return: dict of certificate primitives, should be enough to effectively re-issue certificate via `create`. """ start, end = calculate_reissue_range(certificate.not_before, certificate.not_after) data = CertificateInputSchema().load( CertificateOutputSchema().dump(certificate).data).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 data.pop('name', None) # TODO this can be removed once we migrate away from cn data['cn'] = data['common_name'] # needed until we move off not_* data['not_before'] = start data['not_after'] = end data['validity_start'] = start data['validity_end'] = end return data
def test_certificate_input_schema(client, authority): from lemur.certificates.schemas import CertificateInputSchema input_data = { 'commonName': 'test.example.com', 'owner': '*****@*****.**', 'authority': { 'id': authority.id }, 'description': 'testtestest', 'validityStart': arrow.get(2018, 11, 9).isoformat(), 'validityEnd': arrow.get(2019, 11, 9).isoformat(), 'dnsProvider': None, } data, errors = CertificateInputSchema().load(input_data) assert not errors assert data['authority'].id == authority.id # make sure the defaults got set assert data['common_name'] == 'test.example.com' assert data['country'] == 'US' assert data['location'] == 'Los Gatos' assert len(data.keys()) == 19
def test_certificate_out_of_range_date(client, authority): from lemur.certificates.schemas import CertificateInputSchema input_data = { 'commonName': 'test.example.com', 'owner': '*****@*****.**', 'authority': { 'id': authority.id }, 'description': 'testtestest', 'validityYears': 100, 'dnsProvider': None, } data, errors = CertificateInputSchema().load(input_data) assert errors input_data['validityStart'] = '2017-04-30T00:12:34.513631' data, errors = CertificateInputSchema().load(input_data) assert errors input_data['validityEnd'] = '2018-04-30T00:12:34.513631' data, errors = CertificateInputSchema().load(input_data) assert errors
def test_certificate_input_schema(client, authority): from lemur.certificates.schemas import CertificateInputSchema input_data = { "commonName": "test.example.com", "owner": "*****@*****.**", "authority": { "id": authority.id }, "description": "testtestest", "validityStart": arrow.get(2018, 11, 9).isoformat(), "validityEnd": arrow.get(2019, 11, 9).isoformat(), "dnsProvider": None, } data, errors = CertificateInputSchema().load(input_data) assert not errors assert data["authority"].id == authority.id # make sure the defaults got set assert data["common_name"] == "test.example.com" assert data["country"] == "US" assert data["location"] == "Los Gatos" assert len(data.keys()) == 19
def test_certificate_out_of_range_date(client, authority): from lemur.certificates.schemas import CertificateInputSchema input_data = { "commonName": "test.example.com", "owner": "*****@*****.**", "authority": { "id": authority.id }, "description": "testtestest", "validityYears": 100, "dnsProvider": None, } data, errors = CertificateInputSchema().load(input_data) assert errors input_data["validityStart"] = "2017-04-30T00:12:34.513631" data, errors = CertificateInputSchema().load(input_data) assert errors input_data["validityEnd"] = "2018-04-30T00:12:34.513631" data, errors = CertificateInputSchema().load(input_data) assert errors
def test_certificate_allowed_names(client, authority, session, logged_in_user): """Test for allowed CN and SAN values.""" from lemur.certificates.schemas import CertificateInputSchema input_data = { "commonName": "Names with spaces are not checked", "owner": "*****@*****.**", "authority": { "id": authority.id }, "description": "testtestest", "validityStart": "2020-01-01T00:00:00", "validityEnd": "2020-01-01T00:00:01", "extensions": { "subAltNames": { "names": [ { "nameType": "DNSName", "value": "allowed.example.com" }, { "nameType": "IPAddress", "value": "127.0.0.1" }, ] } }, "dnsProvider": None, } data, errors = CertificateInputSchema().load(input_data) assert not errors
def test_certificate_input_schema_parse_csr(authority): from lemur.certificates.schemas import CertificateInputSchema test_san_dns = 'foobar.com' extensions = { 'sub_alt_names': { 'names': x509.SubjectAlternativeName([x509.DNSName(test_san_dns)]) } } csr, private_key = create_csr(owner='*****@*****.**', common_name='ACommonName', organization='test', organizational_unit='Meters', country='NL', state='Noord-Holland', location='Amsterdam', key_type='RSA2048', extensions=extensions) input_data = { 'commonName': 'test.example.com', 'owner': '*****@*****.**', 'authority': { 'id': authority.id }, 'description': 'testtestest', 'csr': csr, 'dnsProvider': None, } data, errors = CertificateInputSchema().load(input_data) for san in data['extensions']['sub_alt_names']['names']: assert san.value == test_san_dns assert not errors
def test_certificate_input_with_extensions(client, authority): from lemur.certificates.schemas import CertificateInputSchema input_data = { "commonName": "test.example.com", "owner": "*****@*****.**", "authority": { "id": authority.id }, "description": "testtestest", "extensions": { "keyUsage": { "digital_signature": True }, "extendedKeyUsage": { "useClientAuthentication": True, "useServerAuthentication": True, }, "subjectKeyIdentifier": { "includeSKI": True }, "subAltNames": { "names": [{ "nameType": "DNSName", "value": "test.example.com" }] }, }, "dnsProvider": None, } data, errors = CertificateInputSchema().load(input_data) assert not errors
def test_certificate_allowed_names(client, authority, session, logged_in_user): """Test for allowed CN and SAN values.""" from lemur.certificates.schemas import CertificateInputSchema input_data = { 'commonName': 'Names with spaces are not checked', 'owner': '*****@*****.**', 'authority': { 'id': authority.id }, 'description': 'testtestest', 'validityStart': '2020-01-01T00:00:00', 'validityEnd': '2020-01-01T00:00:01', 'extensions': { 'subAltNames': { 'names': [ { 'nameType': 'DNSName', 'value': 'allowed.example.com' }, { 'nameType': 'IPAddress', 'value': '127.0.0.1' }, ] } }, 'dnsProvider': None, } data, errors = CertificateInputSchema().load(input_data) assert not errors
def test_certificate_disallowed_names(client, authority, session, logged_in_user): """The CN and SAN are disallowed by LEMUR_ALLOWED_DOMAINS.""" from lemur.certificates.schemas import CertificateInputSchema input_data = { "commonName": "*.example.com", "owner": "*****@*****.**", "authority": {"id": authority.id}, "description": "testtestest", "validityStart": "2020-01-01T00:00:00", "validityEnd": "2020-01-01T00:00:01", "extensions": { "subAltNames": { "names": [ {"nameType": "DNSName", "value": "allowed.example.com"}, {"nameType": "DNSName", "value": "evilhacker.org"}, ] } }, "dnsProvider": None, } data, errors = CertificateInputSchema().load(input_data) assert errors["common_name"][0].startswith( "Domain *.example.com does not match allowed domain patterns" ) assert errors["extensions"]["sub_alt_names"]["names"][0].startswith( "Domain evilhacker.org does not match allowed domain patterns" )
def test_certificate_disallowed_names(client, authority, session, logged_in_user): """The CN and SAN are disallowed by LEMUR_WHITELISTED_DOMAINS.""" from lemur.certificates.schemas import CertificateInputSchema input_data = { 'commonName': '*.example.com', 'owner': '*****@*****.**', 'authority': { 'id': authority.id }, 'description': 'testtestest', 'validityStart': '2020-01-01T00:00:00', 'validityEnd': '2020-01-01T00:00:01', 'extensions': { 'subAltNames': { 'names': [ { 'nameType': 'DNSName', 'value': 'allowed.example.com' }, { 'nameType': 'DNSName', 'value': 'evilhacker.org' }, ] } }, 'dnsProvider': None, } data, errors = CertificateInputSchema().load(input_data) assert errors['common_name'][0].startswith( "Domain *.example.com does not match whitelisted domain patterns") assert (errors['extensions']['sub_alt_names']['names'][0].startswith( "Domain evilhacker.org does not match whitelisted domain patterns"))
def test_certificate_input_with_extensions(client, authority): from lemur.certificates.schemas import CertificateInputSchema input_data = { 'commonName': 'test.example.com', 'owner': '*****@*****.**', 'authority': {'id': authority.id}, 'description': 'testtestest', 'extensions': { 'keyUsage': { 'digital_signature': True }, 'extendedKeyUsage': { 'useClientAuthentication': True, 'useServerAuthentication': True }, 'subjectKeyIdentifier': { 'includeSKI': True }, 'subAltNames': { 'names': [ {'nameType': 'DNSName', 'value': 'test.example.com'} ] } } } data, errors = CertificateInputSchema().load(input_data) assert not errors
def test_certificate_input_schema_parse_csr(authority): from lemur.certificates.schemas import CertificateInputSchema test_san_dns = "foobar.com" extensions = { "sub_alt_names": { "names": x509.SubjectAlternativeName([x509.DNSName(test_san_dns)]) } } csr, private_key = create_csr( owner="*****@*****.**", common_name="ACommonName", organization="test", organizational_unit="Meters", country="NL", state="Noord-Holland", location="Amsterdam", key_type="RSA2048", extensions=extensions, ) input_data = { "commonName": "test.example.com", "owner": "*****@*****.**", "authority": {"id": authority.id}, "description": "testtestest", "csr": csr, "dnsProvider": None, } data, errors = CertificateInputSchema().load(input_data) for san in data["extensions"]["sub_alt_names"]["names"]: assert san.value == test_san_dns assert not errors
def test_certificate_input_schema(client, authority): from lemur.certificates.schemas import CertificateInputSchema input_data = { 'commonName': 'test.example.com', 'owner': '*****@*****.**', 'authority': {'id': authority.id}, 'description': 'testtestest', } data, errors = CertificateInputSchema().load(input_data) assert not errors assert data['authority'].id == authority.id # make sure the defaults got set assert data['common_name'] == 'test.example.com' assert data['country'] == 'US' assert data['location'] == 'Los Gatos' assert len(data.keys()) == 12
def test_certificate_valid_years(client, authority): from lemur.certificates.schemas import CertificateInputSchema input_data = { 'commonName': 'test.example.com', 'owner': '*****@*****.**', 'authority': {'id': authority.id}, 'description': 'testtestest', 'validityYears': 1 } data, errors = CertificateInputSchema().load(input_data) assert not errors
def test_certificate_valid_years(client, authority): from lemur.certificates.schemas import CertificateInputSchema input_data = { "commonName": "test.example.com", "owner": "*****@*****.**", "authority": {"id": authority.id}, "description": "testtestest", "validityYears": 1, "dnsProvider": None, } data, errors = CertificateInputSchema().load(input_data) assert not errors
def test_certificate_valid_dates(client, authority): from lemur.certificates.schemas import CertificateInputSchema input_data = { 'commonName': 'test.example.com', 'owner': '*****@*****.**', 'authority': {'id': authority.id}, 'description': 'testtestest', 'validityStart': '2020-01-01T00:00:00', 'validityEnd': '2020-01-01T00:00:01', 'dnsProvider': None, } data, errors = CertificateInputSchema().load(input_data) assert not errors
def test_certificate_cn_admin(client, authority, logged_in_admin): """Admin is exempt from CN/SAN domain restrictions.""" from lemur.certificates.schemas import CertificateInputSchema input_data = { 'commonName': '*.admin-overrides-whitelist.com', 'owner': '*****@*****.**', 'authority': {'id': authority.id}, 'description': 'testtestest', 'validityStart': '2020-01-01T00:00:00', 'validityEnd': '2020-01-01T00:00:01', } data, errors = CertificateInputSchema().load(input_data) assert not errors
def test_certificate_sensitive_name(client, authority, session, logged_in_user): """The CN is disallowed by 'sensitive' flag on Domain model.""" from lemur.certificates.schemas import CertificateInputSchema input_data = { 'commonName': 'sensitive.example.com', 'owner': '*****@*****.**', 'authority': {'id': authority.id}, 'description': 'testtestest', 'validityStart': '2020-01-01T00:00:00', 'validityEnd': '2020-01-01T00:00:01', } session.add(Domain(name='sensitive.example.com', sensitive=True)) data, errors = CertificateInputSchema().load(input_data) assert errors['common_name'][0].startswith("Domain sensitive.example.com has been marked as sensitive")
def get_certificate_primitives(certificate): """ Retrieve key primitive from a certificate such that the certificate could be recreated with new expiration or be used to build upon. :param certificate: :return: dict of certificate primitives, should be enough to effectively re-issue certificate via `create`. """ start, end = calculate_reissue_range(certificate.not_before, certificate.not_after) data = CertificateInputSchema().load(CertificateOutputSchema().dump(certificate).data).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 data.pop('name', None) # TODO this can be removed once we migrate away from cn data['cn'] = data['common_name'] # needed until we move off not_* data['not_before'] = start data['not_after'] = end data['validity_start'] = start data['validity_end'] = end return data
def get_certificate_primitives(certificate): """ Retrieve key primitive from a certificate such that the certificate could be recreated with new expiration or be used to build upon. :param certificate: :return: dict of certificate primitives, should be enough to effectively re-issue certificate via `create`. """ start, end = calculate_reissue_range(certificate.not_before, certificate.not_after) data = CertificateInputSchema().load( CertificateOutputSchema().dump(certificate).data).data data['validity_start'] = start data['validity_end'] = end return data
def test_certificate_cn_admin(client, authority, logged_in_admin): """Admin is exempt from CN/SAN domain restrictions.""" from lemur.certificates.schemas import CertificateInputSchema input_data = { "commonName": "*.admin-overrides-allowlist.com", "owner": "*****@*****.**", "authority": {"id": authority.id}, "description": "testtestest", "validityStart": "2020-01-01T00:00:00", "validityEnd": "2020-01-01T00:00:01", "dnsProvider": None, } data, errors = CertificateInputSchema().load(input_data) assert not errors
def test_certificate_incative_authority(client, authority, session, logged_in_user): """Cannot issue certificates with an inactive authority.""" from lemur.certificates.schemas import CertificateInputSchema authority.active = False session.add(authority) input_data = { 'commonName': 'foo.example.com', 'owner': '*****@*****.**', 'authority': {'id': authority.id}, 'description': 'testtestest', 'validityStart': '2020-01-01T00:00:00', 'validityEnd': '2020-01-01T00:00:01', } data, errors = CertificateInputSchema().load(input_data) assert errors['authority'][0] == "The authority is inactive."
def test_certificate_incative_authority(client, authority, session, logged_in_user): """Cannot issue certificates with an inactive authority.""" from lemur.certificates.schemas import CertificateInputSchema authority.active = False session.add(authority) input_data = { "commonName": "foo.example.com", "owner": "*****@*****.**", "authority": {"id": authority.id}, "description": "testtestest", "validityStart": "2020-01-01T00:00:00", "validityEnd": "2020-01-01T00:00:01", "dnsProvider": None, } data, errors = CertificateInputSchema().load(input_data) assert errors["authority"][0] == "The authority is inactive."
def test_certificate_sensitive_name(client, authority, session, logged_in_user): """The CN is disallowed by 'sensitive' flag on Domain model.""" from lemur.certificates.schemas import CertificateInputSchema input_data = { "commonName": "sensitive.example.com", "owner": "*****@*****.**", "authority": {"id": authority.id}, "description": "testtestest", "validityStart": "2020-01-01T00:00:00", "validityEnd": "2020-01-01T00:00:01", "dnsProvider": None, } session.add(Domain(name="sensitive.example.com", sensitive=True)) data, errors = CertificateInputSchema().load(input_data) assert errors["common_name"][0].startswith( "Domain sensitive.example.com has been marked as sensitive" )