def test_generate_dv_csr_with_existing_key(tmp_path, common_name, sans): name = 'auto_example.com' existing_key_content = tests_util.DATA_PATH.joinpath('auto_example.com.key').read_bytes() key_content, csr_path = ssl.generate_csr( name=name, common_name=common_name, sans=sans, key_content=existing_key_content, output_path=str(tmp_path), ) # check that returned key content is same than input key content assert key_content == existing_key_content # check csr files has been created assert csr_path.is_file() # check csr file has right name assert csr_path.name == '%s.csr' % name # load csr first csr = x509.load_pem_x509_csr(data=csr_path.read_bytes(), backend=default_backend()) # check content of CSR if common_name is not None: assert len(csr.subject.get_attributes_for_oid(NameOID.COMMON_NAME)) == 1 assert csr.subject.get_attributes_for_oid(NameOID.COMMON_NAME)[0].value == common_name else: # common name is optional assert len(csr.subject.get_attributes_for_oid(NameOID.COMMON_NAME)) == 0 assert sans == [dns_name.value for dns_name in csr.extensions.get_extension_for_oid(ExtensionOID.SUBJECT_ALTERNATIVE_NAME).value]
def test_generate_dv_csr_with_key_creation(tmp_path, common_name, sans): name = 'auto_example.com' key_content, csr_path = ssl.generate_csr( name=name, common_name=common_name, sans=sans, key_content=None, output_path=str(tmp_path), ) # check key + csr files have been created assert key_content.startswith(b'-----BEGIN RSA PRIVATE KEY-----\n') assert csr_path.is_file() # check csr file has right name assert csr_path.name == '%s.csr' % name # load csr first csr = x509.load_pem_x509_csr(data=csr_path.read_bytes(), backend=default_backend()) # check content of CSR if common_name is not None: assert len(csr.subject.get_attributes_for_oid(NameOID.COMMON_NAME)) == 1 assert csr.subject.get_attributes_for_oid(NameOID.COMMON_NAME)[0].value == common_name else: # common name is optional assert len(csr.subject.get_attributes_for_oid(NameOID.COMMON_NAME)) == 0 assert sans == [dns_name.value for dns_name in csr.extensions.get_extension_for_oid(ExtensionOID.SUBJECT_ALTERNATIVE_NAME).value]
def create_self_signed_certificate(crt_name, output_path, common_name, sans=None, certificate_validity_days=365): """Generate self signed SSL certificate :param crt_name: name of file generated (without extension) :type crt_name: str :param output_path: ouput directory to generate certificate :type output_path: pathlib.Path or str :param common_name: certificate common name :type common_name: str :param sans: certificate alternate names :type sans: list :param certificate_validity_days: validity duration of certificate in days :type certificate_validity_days: int """ if not isinstance(output_path, util.Path): output_path = util.Path(str(output_path)) key_path = output_path.joinpath(crt_name + '.key') key_content, csr_path = ssl.generate_csr(name=crt_name, common_name=common_name, sans=sans, output_path=output_path) crt_path = output_path.joinpath(crt_name + '.crt') crt_content = create_signed_certificate( csr_path=csr_path, certificate_validity_days=certificate_validity_days, ) crt_path.write_bytes(crt_content) key_path.write_bytes(key_content) return key_path, crt_path
def test_get_signed_certificate(ca_manager, common_name, tmp_path): _, csr_path = ssl.generate_csr(name='autossl_cert', common_name=common_name, output_path=tmp_path) crt = ca_manager.get_signed_certificate(ssl_blueprint=None, csr_path=csr_path, servers_api=None) # check CRT x509_object = x509.load_pem_x509_certificate(data=crt, backend=default_backend()) assert len(x509_object.subject.get_attributes_for_oid(NameOID.COMMON_NAME)) == 1 assert x509_object.subject.get_attributes_for_oid(NameOID.COMMON_NAME)[0].value == common_name
def test_generate_ov_csr(tmp_path): name = 'auto_example.com' common_name = 'example.com' sans = ['example.com', 'www.example.com', 'test.example.com'] company_name = 'Autossl corporation' street_address = 'Newbury street' city = 'Boston' state = 'Massachusetts' postal_code = '02115' country_code = 'US' email_address = '*****@*****.**' key_content, csr_path = ssl.generate_csr( name=name, common_name=common_name, company_name=company_name, street_address=street_address, city=city, state=state, postal_code=postal_code, country_code=country_code, email_address=email_address, sans=sans, key_content=None, output_path=str(tmp_path), ) # check key + csr files have been created assert key_content.startswith(b'-----BEGIN RSA PRIVATE KEY-----\n') assert csr_path.is_file() # check csr file has right name assert csr_path.name == '%s.csr' % name # load csr first csr = x509.load_pem_x509_csr(data=csr_path.read_bytes(), backend=default_backend()) # check content of CSR # common name assert len(csr.subject.get_attributes_for_oid(NameOID.COMMON_NAME)) == 1 assert csr.subject.get_attributes_for_oid(NameOID.COMMON_NAME)[0].value == common_name # sans assert sans == [dns_name.value for dns_name in csr.extensions.get_extension_for_oid(ExtensionOID.SUBJECT_ALTERNATIVE_NAME).value] # organization assert csr.subject.get_attributes_for_oid(NameOID.ORGANIZATION_NAME)[0].value == company_name assert csr.subject.get_attributes_for_oid(NameOID.STREET_ADDRESS)[0].value == street_address assert csr.subject.get_attributes_for_oid(NameOID.LOCALITY_NAME)[0].value == city assert csr.subject.get_attributes_for_oid(NameOID.STATE_OR_PROVINCE_NAME)[0].value == state assert csr.subject.get_attributes_for_oid(NameOID.POSTAL_CODE)[0].value == postal_code assert csr.subject.get_attributes_for_oid(NameOID.COUNTRY_NAME)[0].value == country_code assert csr.subject.get_attributes_for_oid(NameOID.EMAIL_ADDRESS)[0].value == email_address
def test_generate_two_csr_with_same_key(tmp_path): name = 'auto_example.com' common_name = 'example.com' sans = ['example.com', 'www.example.com', 'test.example.com'] key_content, csr_path = ssl.generate_csr( name=name, common_name=common_name, sans=sans, key_content=None, output_path=str(tmp_path), ) # generate 2nd csr with same key key_content, csr2_path = ssl.generate_csr( name='test_' + name, common_name=common_name, sans=sans, key_content=key_content, output_path=str(tmp_path), ) # csr should be exactly the same if same key and content are used assert csr_path.read_bytes() == csr2_path.read_bytes()
def test_get_domains_from_x509(tmp_path, common_name, sans): name = 'auto_example.com' key_path, csr_path = ssl.generate_csr( name=name, common_name=common_name, sans=sans, key_content=None, output_path=str(tmp_path), ) expected_domains = set(sans) if common_name is not None: expected_domains.add(common_name) assert ssl.get_domains_from_x509(csr_path, file_type=ssl.DataType.CertificateSigningRequest) == expected_domains
def keypair(tmp_path, ca_keypair_path): common_name = 'tst.autossl.example.com' crt_name = tests_util.get_random_ascii_string() key_path = tmp_path.joinpath(crt_name + '.key') key_content, csr_path = ssl.generate_csr(name=crt_name, common_name=common_name, output_path=tmp_path) crt_path = tmp_path.joinpath(crt_name + '.crt') crt_content = tests_util.create_signed_certificate( csr_path=csr_path, ca_crt_path=ca_keypair_path.crt, ca_key_path=ca_keypair_path.key, certificate_validity_days=10, ) crt_path.write_bytes(crt_content) key_path.write_bytes(key_content) yield CertificateKeyPair(key_path, crt_path)
def test_subca_ko(tmp_path, subca_manager, subca_keypair_path): # sign a new certificate with the sub-CA _, csr_path = ssl.generate_csr(name='invalidcert', common_name='domain.other.example.com', sans=['domain.other.example.com'], output_path=str(tmp_path)) crt_content = tests_util.create_signed_certificate( csr_path=csr_path, ca_crt_path=subca_keypair_path.crt, ca_key_path=subca_keypair_path.key) crt_path = tmp_path / 'invalidcert.crt' crt_path.write_bytes(crt_content) # check trust chain bundle_path = os.path.join(os.environ['AUTOSSL_STORAGE_PATH'], subca_manager.ssl_blueprint.name + '.bundle') assert os.system('openssl verify -CAfile %s %s' % (bundle_path, crt_path)) != 0
def test_cert_sign(tmp_path, common_name, sans, validity_days): ca_key, ca_crt = tests_util.create_ca_certificate(ca_name='Autossl') _, csr_path = ssl.generate_csr( name='autossl_cert', common_name=common_name, sans=sans, output_path=str(tmp_path), ) signed_crt = ssl.sign(csr=csr_path.read_bytes(), ca_key=ca_key, ca_cert=ca_crt, validity_days=validity_days) # load CRT x509_object = x509.load_pem_x509_certificate(data=signed_crt, backend=default_backend()) # check content of CRT assert len(x509_object.subject.get_attributes_for_oid(NameOID.COMMON_NAME)) == 1 assert x509_object.subject.get_attributes_for_oid(NameOID.COMMON_NAME)[0].value == common_name assert sans == [dns_name.value for dns_name in x509_object.extensions.get_extension_for_oid(ExtensionOID.SUBJECT_ALTERNATIVE_NAME).value]
def test_check_chain_of_trust(tmp_path): crt_path = tmp_path / 'local.crt' ca_crt_path = tmp_path / 'local_ca.crt' ca_key_path = tmp_path / 'local_ca.key' # generate CA certificate key, crt = tests_util.create_ca_certificate(ca_name='Autossl') ca_crt_path.write_bytes(crt) ca_key_path.write_bytes(key) # sign a new certificate with the CA _, csr_path = ssl.generate_csr(name='autossl_cert', common_name='test.autossl.com', output_path=str(tmp_path)) crt_content = tests_util.create_signed_certificate( csr_path=csr_path, ca_crt_path=ca_crt_path, ca_key_path=ca_key_path, ) crt_path.write_bytes(crt_content) # valid trust chain should no raise any error ssl.check_chain_of_trust( chain_of_trust=[ crt.decode('utf-8') ], # Chain of trust comes normally from SSL blueprint so it not in bytes crt_path=crt_path, ) # generate self-signed certificate self_signed_key_path, self_signed_crt_path = tests_util.create_self_signed_certificate( crt_name="self_signed_local.crt", output_path=tmp_path, common_name='self_signed.test.autossl.com', ) # self signed certificate should not be validated by this CA with pytest.raises(exception.InvalidTrustChain): ssl.check_chain_of_trust( chain_of_trust=[ crt.decode('utf-8') ], # Chain of trust comes normally from SSL blueprint so it not in bytes crt_path=self_signed_crt_path, )
def create_autossl_signed_cert(ssl_blueprint, output_folder): """Create certificate signed by Autossl CA for specified blueprint and in specified location :param ssl_blueprint: SSL blueprint for which to generate certificate :type ssl_blueprint: ssl.SslBlueprint :param output_folder: local folder where to generate new key and signed certificate :type output_folder: pathlib.Path :return: 2-tuple(local path to private key, local path to signed certificate) :rtype: tuple(pathlib.Path, pathlib.Path) """ if not isinstance(output_folder, util.Path): output_folder = util.Path(output_folder) ca_crt_path = DATA_PATH / 'ca' / 'autossl_ca.crt' ca_key_path = DATA_PATH / 'ca' / 'autossl_ca.key' crt_path = output_folder.joinpath(ssl_blueprint.name + '.crt') key_path = output_folder.joinpath(ssl_blueprint.name + '.key') # generate new CSR key_content, csr_path = ssl.generate_csr( name=ssl_blueprint.name, common_name=ssl_blueprint.certificate.common_name, sans=ssl_blueprint.certificate.sans, output_path=output_folder, ) key_path.write_bytes(key_content) # sign a new certificate with the CA crt_content = create_signed_certificate( csr_path=csr_path, ca_crt_path=ca_crt_path, ca_key_path=ca_key_path, ) crt_path.write_bytes(crt_content) return key_path, crt_path
def test_subca_ok(tmp_path, subca_manager, subca_keypair_path): # check sub-CA certificate subca_crt_path, _ = subca_manager.get_and_check_artifacts() subca_cert = ssl.SslCertificate().init_from_x509(x509_path=subca_crt_path) assert subca_cert.common_name == 'subca.example.com' # sign a new certificate with the sub-CA _, csr_path = ssl.generate_csr( name='leafcert', common_name='domain.subca.example.com', sans=['domain1.subca.example.com', 'domain2.subca.example.com'], output_path=str(tmp_path)) crt_content = tests_util.create_signed_certificate( csr_path=csr_path, ca_crt_path=subca_keypair_path.crt, ca_key_path=subca_keypair_path.key) crt_path = tmp_path / 'leafcert.crt' crt_path.write_bytes(crt_content) # check trust chain bundle_path = os.path.join(os.environ['AUTOSSL_STORAGE_PATH'], subca_manager.ssl_blueprint.name + '.bundle') assert os.system('openssl verify -CAfile %s %s' % (bundle_path, crt_path)) == 0