Пример #1
0
    def validate_cert_private_key_chain(self, data):
        cert = None
        key = None
        if data.get('body'):
            try:
                cert = utils.parse_certificate(data['body'])
            except ValueError:
                raise ValidationError("Public certificate presented is not valid.", field_names=['body'])

        if data.get('private_key'):
            try:
                key = utils.parse_private_key(data['private_key'])
            except ValueError:
                raise ValidationError("Private key presented is not valid.", field_names=['private_key'])

        if cert and key:
            # Throws ValidationError
            validators.verify_private_key_match(key, cert)

        if data.get('chain'):
            try:
                chain = utils.parse_cert_chain(data['chain'])
            except ValueError:
                raise ValidationError("Invalid certificate in certificate chain.", field_names=['chain'])

            # Throws ValidationError
            validators.verify_cert_chain([cert] + chain)
Пример #2
0
    def validate_cert_private_key_chain(self, data):
        cert = None
        key = None
        if data.get("body"):
            try:
                cert = utils.parse_certificate(data["body"])
            except ValueError:
                raise ValidationError(
                    "Public certificate presented is not valid.",
                    field_names=["body"])

        if data.get("private_key"):
            try:
                key = utils.parse_private_key(data["private_key"])
            except ValueError:
                raise ValidationError("Private key presented is not valid.",
                                      field_names=["private_key"])

        if cert and key:
            # Throws ValidationError
            validators.verify_private_key_match(key, cert)

        if data.get("chain"):
            try:
                chain = utils.parse_cert_chain(data["chain"])
            except ValueError:
                raise ValidationError(
                    "Invalid certificate in certificate chain.",
                    field_names=["chain"])

            # Throws ValidationError
            validators.verify_cert_chain([cert] + chain)
Пример #3
0
def test_validate_private_key(session):
    key = parse_private_key(SAN_CERT_KEY)

    verify_private_key_match(key, SAN_CERT)

    with pytest.raises(ValidationError):
        # Wrong key for certificate
        verify_private_key_match(key, INTERMEDIATE_CERT)
Пример #4
0
def test_validate_private_key(session):
    key = parse_private_key(SAN_CERT_KEY)

    verify_private_key_match(key, SAN_CERT)

    with pytest.raises(ValidationError):
        # Wrong key for certificate
        verify_private_key_match(key, INTERMEDIATE_CERT)
Пример #5
0
 def check_integrity(self):
     """
     Integrity checks: Does the cert have a matching private key?
     """
     if self.private_key:
         validators.verify_private_key_match(utils.parse_private_key(
             self.private_key),
                                             self.parsed_cert,
                                             error_class=AssertionError)
Пример #6
0
def create_keystore(cert, chain, key, alias, passphrase):
    certs_bytes = cert_chain_as_der(cert, chain)
    key_bytes = parse_private_key(key).private_bytes(
        encoding=serialization.Encoding.DER,
        format=serialization.PrivateFormat.PKCS8,
        encryption_algorithm=serialization.NoEncryption())
    entry = PrivateKeyEntry.new(alias, certs_bytes, key_bytes)

    return KeyStore.new('jks', [entry]).saves(passphrase)
Пример #7
0
def create_keystore(cert, chain, key, alias, passphrase):
    certs_bytes = cert_chain_as_der(cert, chain)
    key_bytes = parse_private_key(key).private_bytes(
        encoding=serialization.Encoding.DER,
        format=serialization.PrivateFormat.PKCS8,
        encryption_algorithm=serialization.NoEncryption()
    )
    entry = PrivateKeyEntry.new(alias, certs_bytes, key_bytes)

    return KeyStore.new('jks', [entry]).saves(passphrase)
Пример #8
0
    def check_integrity(self):
        """
        Integrity checks: Does the cert have a valid chain and matching private key?
        """
        if self.private_key:
            validators.verify_private_key_match(utils.parse_private_key(self.private_key), self.parsed_cert,
                                                error_class=AssertionError)

        if self.chain:
            chain = [self.parsed_cert] + utils.parse_cert_chain(self.chain)
            validators.verify_cert_chain(chain, error_class=AssertionError)
Пример #9
0
    def upload(self, name, body, private_key, cert_chain, options, **kwargs):
        """
        Upload certificate and private key

        :param private_key:
        :param cert_chain:
        :return:
        """

        # we use the common name to identify the certificate
        # Azure does not allow "." in the certificate name we replace them with "-"
        cert = parse_certificate(body)
        certificate_name = common_name(cert).replace(".", "-")

        vault_URI = self.get_option("vaultUrl", options)
        tenant = self.get_option("azureTenant", options)
        app_id = self.get_option("appID", options)
        password = self.get_option("azurePassword", options)

        access_token = get_access_token(tenant, app_id, password, self)

        cert_url = f"{vault_URI}/certificates/{certificate_name}/import?api-version=7.1"
        post_header = {"Authorization": f"Bearer {access_token}"}
        key_pkcs8 = parse_private_key(private_key).private_bytes(
            encoding=serialization.Encoding.PEM,
            format=serialization.PrivateFormat.PKCS8,
            encryption_algorithm=serialization.NoEncryption(),
        )
        key_pkcs8 = key_pkcs8.decode("utf-8").replace('\\n', '\n')
        cert_package = f"{body}\n{key_pkcs8}"

        post_body = {
            "value": cert_package,
            "policy": {
                "key_props": {
                    "exportable": True,
                    "kty": "RSA",
                    "key_size": bitstrength(cert),
                    "reuse_key": True
                },
                "secret_props": {
                    "contentType": "application/x-pem-file"
                }
            }
        }

        try:
            response = self.session.post(cert_url,
                                         headers=post_header,
                                         json=post_body)
        except requests.exceptions.RequestException as e:
            current_app.logger.exception(f"AZURE: Error for POST {e}")
        return_value = handle_response(response)
Пример #10
0
    def check_integrity(self):
        """
        Integrity checks: Does the cert have a valid chain and matching private key?
        """
        if self.private_key:
            validators.verify_private_key_match(utils.parse_private_key(
                self.private_key),
                                                self.parsed_cert,
                                                error_class=AssertionError)

        if self.chain:
            chain = [self.parsed_cert] + utils.parse_cert_chain(self.chain)
            validators.verify_cert_chain(chain, error_class=AssertionError)
Пример #11
0
    def validate_cert_private_key(self, data):
        cert = None
        key = None
        if data.get('body'):
            try:
                cert = utils.parse_certificate(data['body'])
            except ValueError:
                raise ValidationError(
                    "Public certificate presented is not valid.",
                    field_names=['body'])

        if data.get('private_key'):
            try:
                key = utils.parse_private_key(data['private_key'])
            except ValueError:
                raise ValidationError("Private key presented is not valid.",
                                      field_names=['private_key'])

        if cert and key:
            # Throws ValidationError
            validators.verify_private_key_match(key, cert)
Пример #12
0
def issuer_private_key():
    return parse_private_key(INTERMEDIATE_KEY)
Пример #13
0
def private_key():
    return parse_private_key(SAN_CERT_KEY)
Пример #14
0
def issue_certificate(csr, options, private_key=None):
    csr = x509.load_pem_x509_csr(csr.encode("utf-8"), default_backend())

    if options.get("parent"):
        # creating intermediate authorities will have options['parent'] to specify the issuer
        # creating certificates will have options['authority'] to specify the issuer
        # This works around that by making sure options['authority'] can be referenced for either
        options["authority"] = options["parent"]

    if options.get("authority"):
        # Issue certificate signed by an existing lemur_certificates authority
        issuer_subject = options["authority"].authority_certificate.subject
        if not "parent" in options:
            assert (
                private_key is None
            ), "Private would be ignored, authority key used instead"
        private_key = options["authority"].authority_certificate.private_key
        chain_cert_pem = options["authority"].authority_certificate.body
        authority_key_identifier_public = options[
            "authority"
        ].authority_certificate.public_key
        authority_key_identifier_subject = x509.SubjectKeyIdentifier.from_public_key(
            authority_key_identifier_public
        )
        authority_key_identifier_issuer = issuer_subject
        authority_key_identifier_serial = int(
            options["authority"].authority_certificate.serial
        )
        # TODO figure out a better way to increment serial
        # New authorities have a value at options['serial_number'] that is being ignored here.
        serial = int(uuid.uuid4())
    else:
        # Issue certificate that is self-signed (new lemur_certificates root authority)
        issuer_subject = csr.subject
        chain_cert_pem = ""
        authority_key_identifier_public = csr.public_key()
        authority_key_identifier_subject = None
        authority_key_identifier_issuer = csr.subject
        authority_key_identifier_serial = options["serial_number"]
        # TODO figure out a better way to increment serial
        serial = int(uuid.uuid4())

    extensions = normalize_extensions(csr)

    builder = x509.CertificateBuilder(
        issuer_name=issuer_subject,
        subject_name=csr.subject,
        public_key=csr.public_key(),
        not_valid_before=options["validity_start"],
        not_valid_after=options["validity_end"],
        serial_number=serial,
        extensions=extensions,
    )

    for k, v in options.get("extensions", {}).items():
        if k == "authority_key_identifier":
            # One or both of these options may be present inside the aki extension
            (authority_key_identifier, authority_identifier) = (False, False)
            for k2, v2 in v.items():
                if k2 == "use_key_identifier" and v2:
                    authority_key_identifier = True
                if k2 == "use_authority_cert" and v2:
                    authority_identifier = True
            if authority_key_identifier:
                if authority_key_identifier_subject:
                    # FIXME in python-cryptography.
                    # from_issuer_subject_key_identifier(cls, ski) is looking for ski.value.digest
                    # but the digest of the ski is at just ski.digest. Until that library is fixed,
                    # this function won't work. The second line has the same result.
                    # aki = x509.AuthorityKeyIdentifier.from_issuer_subject_key_identifier(authority_key_identifier_subject)
                    aki = x509.AuthorityKeyIdentifier(
                        authority_key_identifier_subject.digest, None, None
                    )
                else:
                    aki = x509.AuthorityKeyIdentifier.from_issuer_public_key(
                        authority_key_identifier_public
                    )
            elif authority_identifier:
                aki = x509.AuthorityKeyIdentifier(
                    None,
                    [x509.DirectoryName(authority_key_identifier_issuer)],
                    authority_key_identifier_serial,
                )
            builder = builder.add_extension(aki, critical=False)
        if k == "certificate_info_access":
            # FIXME: Implement the AuthorityInformationAccess extension
            # descriptions = [
            #     x509.AccessDescription(x509.oid.AuthorityInformationAccessOID.OCSP, x509.UniformResourceIdentifier(u"http://FIXME")),
            #     x509.AccessDescription(x509.oid.AuthorityInformationAccessOID.CA_ISSUERS, x509.UniformResourceIdentifier(u"http://FIXME"))
            # ]
            # for k2, v2 in v.items():
            #     if k2 == 'include_aia' and v2 == True:
            #         builder = builder.add_extension(
            #             x509.AuthorityInformationAccess(descriptions),
            #             critical=False
            #         )
            pass
        if k == "crl_distribution_points":
            # FIXME: Implement the CRLDistributionPoints extension
            # FIXME: Not implemented in lemur/schemas.py yet https://github.com/Netflix/lemur/issues/662
            pass

    private_key = parse_private_key(private_key)

    cert = builder.sign(private_key, hashes.SHA256(), default_backend())
    cert_pem = cert.public_bytes(encoding=serialization.Encoding.PEM).decode("utf-8")

    return cert_pem, chain_cert_pem
Пример #15
0
def test_private_key(session):
    parse_private_key(SAN_CERT_KEY)

    with pytest.raises(ValueError):
        parse_private_key('invalid_private_key')
Пример #16
0
def test_private_key(session):
    parse_private_key(SAN_CERT_KEY)

    with pytest.raises(ValueError):
        parse_private_key("invalid_private_key")
Пример #17
0
def issue_certificate(csr, options, private_key=None):
    csr = x509.load_pem_x509_csr(csr.encode('utf-8'), default_backend())

    if options.get("parent"):
        # creating intermediate authorities will have options['parent'] to specify the issuer
        # creating certificates will have options['authority'] to specify the issuer
        # This works around that by making sure options['authority'] can be referenced for either
        options['authority'] = options['parent']

    if options.get("authority"):
        # Issue certificate signed by an existing lemur_certificates authority
        issuer_subject = options['authority'].authority_certificate.subject
        assert private_key is None, "Private would be ignored, authority key used instead"
        private_key = options['authority'].authority_certificate.private_key
        chain_cert_pem = options['authority'].authority_certificate.body
        authority_key_identifier_public = options['authority'].authority_certificate.public_key
        authority_key_identifier_subject = x509.SubjectKeyIdentifier.from_public_key(authority_key_identifier_public)
        authority_key_identifier_issuer = issuer_subject
        authority_key_identifier_serial = int(options['authority'].authority_certificate.serial)
        # TODO figure out a better way to increment serial
        # New authorities have a value at options['serial_number'] that is being ignored here.
        serial = int(uuid.uuid4())
    else:
        # Issue certificate that is self-signed (new lemur_certificates root authority)
        issuer_subject = csr.subject
        chain_cert_pem = ""
        authority_key_identifier_public = csr.public_key()
        authority_key_identifier_subject = None
        authority_key_identifier_issuer = csr.subject
        authority_key_identifier_serial = options['serial_number']
        # TODO figure out a better way to increment serial
        serial = int(uuid.uuid4())

    extensions = normalize_extensions(csr)

    builder = x509.CertificateBuilder(
        issuer_name=issuer_subject,
        subject_name=csr.subject,
        public_key=csr.public_key(),
        not_valid_before=options['validity_start'],
        not_valid_after=options['validity_end'],
        serial_number=serial,
        extensions=extensions)

    for k, v in options.get('extensions', {}).items():
        if k == 'authority_key_identifier':
            # One or both of these options may be present inside the aki extension
            (authority_key_identifier, authority_identifier) = (False, False)
            for k2, v2 in v.items():
                if k2 == 'use_key_identifier' and v2:
                    authority_key_identifier = True
                if k2 == 'use_authority_cert' and v2:
                    authority_identifier = True
            if authority_key_identifier:
                if authority_key_identifier_subject:
                    # FIXME in python-cryptography.
                    # from_issuer_subject_key_identifier(cls, ski) is looking for ski.value.digest
                    # but the digest of the ski is at just ski.digest. Until that library is fixed,
                    # this function won't work. The second line has the same result.
                    # aki = x509.AuthorityKeyIdentifier.from_issuer_subject_key_identifier(authority_key_identifier_subject)
                    aki = x509.AuthorityKeyIdentifier(authority_key_identifier_subject.digest, None, None)
                else:
                    aki = x509.AuthorityKeyIdentifier.from_issuer_public_key(authority_key_identifier_public)
            elif authority_identifier:
                aki = x509.AuthorityKeyIdentifier(None, [x509.DirectoryName(authority_key_identifier_issuer)], authority_key_identifier_serial)
            builder = builder.add_extension(aki, critical=False)
        if k == 'certificate_info_access':
            # FIXME: Implement the AuthorityInformationAccess extension
            # descriptions = [
            #     x509.AccessDescription(x509.oid.AuthorityInformationAccessOID.OCSP, x509.UniformResourceIdentifier(u"http://FIXME")),
            #     x509.AccessDescription(x509.oid.AuthorityInformationAccessOID.CA_ISSUERS, x509.UniformResourceIdentifier(u"http://FIXME"))
            # ]
            # for k2, v2 in v.items():
            #     if k2 == 'include_aia' and v2 == True:
            #         builder = builder.add_extension(
            #             x509.AuthorityInformationAccess(descriptions),
            #             critical=False
            #         )
            pass
        if k == 'crl_distribution_points':
            # FIXME: Implement the CRLDistributionPoints extension
            # FIXME: Not implemented in lemur/schemas.py yet https://github.com/Netflix/lemur/issues/662
            pass

    private_key = parse_private_key(private_key)

    cert = builder.sign(private_key, hashes.SHA256(), default_backend())
    cert_pem = cert.public_bytes(
        encoding=serialization.Encoding.PEM
    ).decode('utf-8')

    return cert_pem, chain_cert_pem