Example #1
0
def test_generate_private_key():
    from lemur.common.utils import generate_private_key

    assert generate_private_key('RSA2048')
    assert generate_private_key('RSA4096')

    with pytest.raises(Exception):
        generate_private_key('ECC')
Example #2
0
def test_generate_private_key():
    from lemur.common.utils import generate_private_key

    assert generate_private_key('RSA2048')
    assert generate_private_key('RSA4096')

    with pytest.raises(Exception):
        generate_private_key('ECC')
Example #3
0
    def setup_acme_client(self, authority):
        if not authority.options:
            raise InvalidAuthority("Invalid authority. Options not set")
        options = {}

        for option in json.loads(authority.options):
            options[option["name"]] = option.get("value")
        email = options.get('email', current_app.config.get('ACME_EMAIL'))
        tel = options.get('telephone', current_app.config.get('ACME_TEL'))
        directory_url = options.get('acme_url', current_app.config.get('ACME_DIRECTORY_URL'))

        existing_key = options.get('acme_private_key', current_app.config.get('ACME_PRIVATE_KEY'))
        existing_regr = options.get('acme_regr', current_app.config.get('ACME_REGR'))

        if existing_key and existing_regr:
            # Reuse the same account for each certificate issuance
            key = jose.JWK.json_loads(existing_key)
            regr = messages.RegistrationResource.json_loads(existing_regr)
            current_app.logger.debug("Connecting with directory at {0}".format(directory_url))
            net = ClientNetwork(key, account=regr)
            client = BackwardsCompatibleClientV2(net, key, directory_url)
            return client, {}
        else:
            # Create an account for each certificate issuance
            key = jose.JWKRSA(key=generate_private_key('RSA2048'))

            current_app.logger.debug("Connecting with directory at {0}".format(directory_url))

            net = ClientNetwork(key, account=None, timeout=3600)
            client = BackwardsCompatibleClientV2(net, key, directory_url)
            registration = client.new_account_and_tos(messages.NewRegistration.from_data(email=email))
            current_app.logger.debug("Connected: {0}".format(registration.uri))

        return client, registration
Example #4
0
    def setup_acme_client(self, authority):
        if not authority.options:
            raise InvalidAuthority("Invalid authority. Options not set")
        options = {}

        for option in json.loads(authority.options):
            options[option["name"]] = option.get("value")
        email = options.get('email', current_app.config.get('ACME_EMAIL'))
        tel = options.get('telephone', current_app.config.get('ACME_TEL'))
        directory_url = options.get('acme_url', current_app.config.get('ACME_DIRECTORY_URL'))

        existing_key = options.get('acme_private_key', current_app.config.get('ACME_PRIVATE_KEY'))
        existing_regr = options.get('acme_regr', current_app.config.get('ACME_REGR'))

        if existing_key and existing_regr:
            # Reuse the same account for each certificate issuance
            key = jose.JWK.json_loads(existing_key)
            regr = messages.RegistrationResource.json_loads(existing_regr)
            current_app.logger.debug("Connecting with directory at {0}".format(directory_url))
            net = ClientNetwork(key, account=regr)
            client = BackwardsCompatibleClientV2(net, key, directory_url)
            return client, {}
        else:
            # Create an account for each certificate issuance
            key = jose.JWKRSA(key=generate_private_key('RSA2048'))

            current_app.logger.debug("Connecting with directory at {0}".format(directory_url))

            net = ClientNetwork(key, account=None)
            client = BackwardsCompatibleClientV2(net, key, directory_url)
            registration = client.new_account_and_tos(messages.NewRegistration.from_data(email=email))
            current_app.logger.debug("Connected: {0}".format(registration.uri))

        return client, registration
Example #5
0
def register(email):
    private_key = generate_private_key('RSA2048')
    acme_client = acme_client_for_private_key(
        current_app.config('ACME_DIRECTORY_URL'), private_key)

    registration = acme_client.register(
        messages.NewRegistration.from_data(email=email))
    acme_client.agree_to_tos(registration)
    return private_key
Example #6
0
def setup_acme_client():
    email = current_app.config.get('ACME_EMAIL')
    tel = current_app.config.get('ACME_TEL')
    directory_url = current_app.config.get('ACME_DIRECTORY_URL')
    contact = ('mailto:{}'.format(email), 'tel:{}'.format(tel))

    key = jose.JWKRSA(key=generate_private_key('RSA2048'))

    client = Client(directory_url, key)

    registration = client.register(
        messages.NewRegistration.from_data(email=email))

    client.agree_to_tos(registration)
    return client, registration
Example #7
0
def setup_acme_client():
    email = current_app.config.get('ACME_EMAIL')
    tel = current_app.config.get('ACME_TEL')
    directory_url = current_app.config.get('ACME_DIRECTORY_URL')
    contact = ('mailto:{}'.format(email), 'tel:{}'.format(tel))

    key = jose.JWKRSA(key=generate_private_key('RSA2048'))

    client = Client(directory_url, key)

    registration = client.register(
        messages.NewRegistration.from_data(email=email)
    )

    client.agree_to_tos(registration)
    return client, registration
Example #8
0
    def test_setup_acme_client_success_load_account_from_authority(
            self, mock_acme, mock_key_json_load):
        mock_authority = Mock()
        mock_authority.id = 2
        mock_authority.options = '[{"name": "mock_name", "value": "mock_value"}, ' \
                                 '{"name": "store_account", "value": true},' \
                                 '{"name": "acme_private_key", "value": "{\\"n\\": \\"PwIOkViO\\", \\"kty\\": \\"RSA\\"}"}, ' \
                                 '{"name": "acme_regr", "value": "{\\"body\\": {}, \\"uri\\": \\"http://test.com\\"}"}]'
        mock_client = Mock()
        mock_acme.return_value = mock_client

        mock_key_json_load.return_value = jose.JWKRSA(
            key=generate_private_key("RSA2048"))

        result_client, result_registration = self.acme.setup_acme_client(
            mock_authority)

        mock_acme.new_account_and_tos.assert_not_called()
        assert result_client
        assert not result_registration
Example #9
0
def build_root_certificate(options):
    private_key = generate_private_key(options.get('key_type'))

    subject = issuer = x509.Name([
        x509.NameAttribute(x509.OID_COUNTRY_NAME, options['country']),
        x509.NameAttribute(x509.OID_STATE_OR_PROVINCE_NAME, options['state']),
        x509.NameAttribute(x509.OID_LOCALITY_NAME, options['location']),
        x509.NameAttribute(x509.OID_ORGANIZATION_NAME,
                           options['organization']),
        x509.NameAttribute(x509.OID_ORGANIZATIONAL_UNIT_NAME,
                           options['organizational_unit']),
        x509.NameAttribute(x509.OID_COMMON_NAME, options['common_name'])
    ])

    builder = x509.CertificateBuilder(
        subject_name=subject,
        issuer_name=issuer,
        public_key=private_key.public_key(),
        not_valid_after=options['validity_end'],
        not_valid_before=options['validity_start'],
        serial_number=options['first_serial'])

    builder.add_extension(x509.SubjectAlternativeName(
        [x509.DNSName(options['common_name'])]),
                          critical=False)

    cert = builder.sign(private_key, hashes.SHA256(), default_backend())

    cert_pem = cert.public_bytes(
        encoding=serialization.Encoding.PEM).decode('utf-8')

    private_key_pem = private_key.private_bytes(
        encoding=serialization.Encoding.PEM,
        format=serialization.PrivateFormat.
        TraditionalOpenSSL,  # would like to use PKCS8 but AWS ELBs don't like it
        encryption_algorithm=serialization.NoEncryption())

    return cert_pem, private_key_pem
Example #10
0
def setup_acme_client(authority):
    if not authority.options:
        raise InvalidAuthority("Invalid authority. Options not set")
    options = {}

    for option in json.loads(authority.options):
        options[option["name"]] = option.get("value")
    email = options.get('email', current_app.config.get('ACME_EMAIL'))
    tel = options.get('telephone', current_app.config.get('ACME_TEL'))
    directory_url = options.get('acme_url',
                                current_app.config.get('ACME_DIRECTORY_URL'))

    key = jose.JWKRSA(key=generate_private_key('RSA2048'))

    current_app.logger.debug(
        "Connecting with directory at {0}".format(directory_url))

    net = ClientNetwork(key, account=None)
    client = BackwardsCompatibleClientV2(net, key, directory_url)
    registration = client.new_account_and_tos(
        messages.NewRegistration.from_data(email=email))
    current_app.logger.debug("Connected: {0}".format(registration.uri))

    return client, registration
Example #11
0
def test_generate_private_key():
    from lemur.common.utils import generate_private_key

    assert generate_private_key("RSA2048")
    assert generate_private_key("RSA4096")
    assert generate_private_key("ECCPRIME192V1")
    assert generate_private_key("ECCPRIME256V1")
    assert generate_private_key("ECCSECP192R1")
    assert generate_private_key("ECCSECP224R1")
    assert generate_private_key("ECCSECP256R1")
    assert generate_private_key("ECCSECP384R1")
    assert generate_private_key("ECCSECP521R1")
    assert generate_private_key("ECCSECP256K1")
    assert generate_private_key("ECCSECT163K1")
    assert generate_private_key("ECCSECT233K1")
    assert generate_private_key("ECCSECT283K1")
    assert generate_private_key("ECCSECT409K1")
    assert generate_private_key("ECCSECT571K1")
    assert generate_private_key("ECCSECT163R2")
    assert generate_private_key("ECCSECT233R1")
    assert generate_private_key("ECCSECT283R1")
    assert generate_private_key("ECCSECT409R1")
    assert generate_private_key("ECCSECT571R2")

    with pytest.raises(Exception):
        generate_private_key("LEMUR")
Example #12
0
def create_csr(**csr_config):
    """
    Given a list of domains create the appropriate csr
    for those domains

    :param csr_config:
    """
    private_key = generate_private_key(csr_config.get("key_type"))

    builder = x509.CertificateSigningRequestBuilder()
    name_list = []
    if current_app.config.get("LEMUR_OWNER_EMAIL_IN_SUBJECT", True):
        name_list.append(
            x509.NameAttribute(x509.OID_EMAIL_ADDRESS, csr_config["owner"])
        )
    if "common_name" in csr_config and csr_config["common_name"].strip():
        name_list.append(
            x509.NameAttribute(x509.OID_COMMON_NAME, csr_config["common_name"])
        )
    if "organization" in csr_config and csr_config["organization"].strip():
        name_list.append(
            x509.NameAttribute(x509.OID_ORGANIZATION_NAME, csr_config["organization"])
        )
    if (
        "organizational_unit" in csr_config
        and csr_config["organizational_unit"].strip()
    ):
        name_list.append(
            x509.NameAttribute(
                x509.OID_ORGANIZATIONAL_UNIT_NAME, csr_config["organizational_unit"]
            )
        )
    if "country" in csr_config and csr_config["country"].strip():
        name_list.append(
            x509.NameAttribute(x509.OID_COUNTRY_NAME, csr_config["country"])
        )
    if "state" in csr_config and csr_config["state"].strip():
        name_list.append(
            x509.NameAttribute(x509.OID_STATE_OR_PROVINCE_NAME, csr_config["state"])
        )
    if "location" in csr_config and csr_config["location"].strip():
        name_list.append(
            x509.NameAttribute(x509.OID_LOCALITY_NAME, csr_config["location"])
        )
    builder = builder.subject_name(x509.Name(name_list))

    extensions = csr_config.get("extensions", {})
    critical_extensions = ["basic_constraints", "sub_alt_names", "key_usage"]
    noncritical_extensions = ["extended_key_usage"]
    for k, v in extensions.items():
        if v:
            if k in critical_extensions:
                current_app.logger.debug(
                    "Adding Critical Extension: {0} {1}".format(k, v)
                )
                if k == "sub_alt_names":
                    if v["names"]:
                        builder = builder.add_extension(v["names"], critical=True)
                else:
                    builder = builder.add_extension(v, critical=True)

            if k in noncritical_extensions:
                current_app.logger.debug("Adding Extension: {0} {1}".format(k, v))
                builder = builder.add_extension(v, critical=False)

    ski = extensions.get("subject_key_identifier", {})
    if ski.get("include_ski", False):
        builder = builder.add_extension(
            x509.SubjectKeyIdentifier.from_public_key(private_key.public_key()),
            critical=False,
        )

    request = builder.sign(private_key, hashes.SHA256(), default_backend())

    # serialize our private key and CSR
    private_key = private_key.private_bytes(
        encoding=serialization.Encoding.PEM,
        format=serialization.PrivateFormat.TraditionalOpenSSL,  # would like to use PKCS8 but AWS ELBs don't like it
        encryption_algorithm=serialization.NoEncryption(),
    ).decode("utf-8")

    csr = request.public_bytes(encoding=serialization.Encoding.PEM).decode("utf-8")

    return csr, private_key
Example #13
0
def create_csr(**csr_config):
    """
    Given a list of domains create the appropriate csr
    for those domains

    :param csr_config:
    """
    private_key = generate_private_key(csr_config.get('key_type'))

    builder = x509.CertificateSigningRequestBuilder()
    name_list = [
        x509.NameAttribute(x509.OID_COMMON_NAME, csr_config['common_name'])
    ]
    if current_app.config.get('LEMUR_OWNER_EMAIL_IN_SUBJECT', True):
        name_list.append(
            x509.NameAttribute(x509.OID_EMAIL_ADDRESS, csr_config['owner']))
    if 'organization' in csr_config and csr_config['organization'].strip():
        name_list.append(
            x509.NameAttribute(x509.OID_ORGANIZATION_NAME,
                               csr_config['organization']))
    if 'organizational_unit' in csr_config and csr_config[
            'organizational_unit'].strip():
        name_list.append(
            x509.NameAttribute(x509.OID_ORGANIZATIONAL_UNIT_NAME,
                               csr_config['organizational_unit']))
    if 'country' in csr_config and csr_config['country'].strip():
        name_list.append(
            x509.NameAttribute(x509.OID_COUNTRY_NAME, csr_config['country']))
    if 'state' in csr_config and csr_config['state'].strip():
        name_list.append(
            x509.NameAttribute(x509.OID_STATE_OR_PROVINCE_NAME,
                               csr_config['state']))
    if 'location' in csr_config and csr_config['location'].strip():
        name_list.append(
            x509.NameAttribute(x509.OID_LOCALITY_NAME, csr_config['location']))
    builder = builder.subject_name(x509.Name(name_list))

    extensions = csr_config.get('extensions', {})
    critical_extensions = ['basic_constraints', 'sub_alt_names', 'key_usage']
    noncritical_extensions = ['extended_key_usage']
    for k, v in extensions.items():
        if v:
            if k in critical_extensions:
                current_app.logger.debug(
                    'Adding Critical Extension: {0} {1}'.format(k, v))
                if k == 'sub_alt_names':
                    if v['names']:
                        builder = builder.add_extension(v['names'],
                                                        critical=True)
                else:
                    builder = builder.add_extension(v, critical=True)

            if k in noncritical_extensions:
                current_app.logger.debug('Adding Extension: {0} {1}'.format(
                    k, v))
                builder = builder.add_extension(v, critical=False)

    ski = extensions.get('subject_key_identifier', {})
    if ski.get('include_ski', False):
        builder = builder.add_extension(
            x509.SubjectKeyIdentifier.from_public_key(
                private_key.public_key()),
            critical=False)

    request = builder.sign(private_key, hashes.SHA256(), default_backend())

    # serialize our private key and CSR
    private_key = private_key.private_bytes(
        encoding=serialization.Encoding.PEM,
        format=serialization.PrivateFormat.
        TraditionalOpenSSL,  # would like to use PKCS8 but AWS ELBs don't like it
        encryption_algorithm=serialization.NoEncryption())

    if isinstance(private_key, bytes):
        private_key = private_key.decode('utf-8')

    csr = request.public_bytes(
        encoding=serialization.Encoding.PEM).decode('utf-8')

    return csr, private_key
Example #14
0
    def setup_acme_client(self, authority):
        if not authority.options:
            raise InvalidAuthority("Invalid authority. Options not set")
        options = {}

        for option in json.loads(authority.options):
            options[option["name"]] = option.get("value")
        email = options.get("email", current_app.config.get("ACME_EMAIL"))
        tel = options.get("telephone", current_app.config.get("ACME_TEL"))
        directory_url = options.get(
            "acme_url", current_app.config.get("ACME_DIRECTORY_URL"))

        existing_key = options.get("acme_private_key",
                                   current_app.config.get("ACME_PRIVATE_KEY"))
        existing_regr = options.get("acme_regr",
                                    current_app.config.get("ACME_REGR"))

        eab_kid = options.get("eab_kid", None)
        eab_hmac_key = options.get("eab_hmac_key", None)

        if existing_key and existing_regr:
            current_app.logger.debug("Reusing existing ACME account")
            # Reuse the same account for each certificate issuance

            # existing_key might be encrypted
            if not is_json(existing_key):
                # decrypt the private key, if not already in plaintext (json format)
                existing_key = data_decrypt(existing_key)

            key = jose.JWK.json_loads(existing_key)
            regr = messages.RegistrationResource.json_loads(existing_regr)
            current_app.logger.debug(
                "Connecting with directory at {0}".format(directory_url))
            net = ClientNetwork(key, account=regr)
            client = BackwardsCompatibleClientV2(net, key, directory_url)
            return client, {}
        else:
            # Create an account for each certificate issuance
            key = jose.JWKRSA(key=generate_private_key("RSA2048"))

            current_app.logger.debug("Creating a new ACME account")
            current_app.logger.debug(
                "Connecting with directory at {0}".format(directory_url))

            net = ClientNetwork(key, account=None, timeout=3600)
            client = BackwardsCompatibleClientV2(net, key, directory_url)
            if eab_kid and eab_hmac_key:
                # external account binding (eab_kid and eab_hmac_key could be potentially single use to establish
                # long-term credentials)
                eab = messages.ExternalAccountBinding.from_data(
                    account_public_key=key.public_key(),
                    kid=eab_kid,
                    hmac_key=eab_hmac_key,
                    directory=client.directory)
                registration = client.new_account_and_tos(
                    messages.NewRegistration.from_data(
                        email=email, external_account_binding=eab))
            else:
                registration = client.new_account_and_tos(
                    messages.NewRegistration.from_data(email=email))

            # if store_account is checked, add the private_key and registration resources to the options
            if options['store_account']:
                new_options = json.loads(authority.options)
                # the key returned by fields_to_partial_json is missing the key type, so we add it manually
                key_dict = key.fields_to_partial_json()
                key_dict["kty"] = "RSA"
                acme_private_key = {
                    "name": "acme_private_key",
                    "value": data_encrypt(json.dumps(key_dict))
                }
                new_options.append(acme_private_key)

                acme_regr = {
                    "name": "acme_regr",
                    "value": json.dumps({
                        "body": {},
                        "uri": registration.uri
                    })
                }
                new_options.append(acme_regr)

                authorities_service.update_options(
                    authority.id, options=json.dumps(new_options))

            current_app.logger.debug("Connected: {0}".format(registration.uri))

        return client, registration
Example #15
0
    def setup_acme_client(self, authority):
        if not authority.options:
            raise InvalidAuthority("Invalid authority. Options not set")
        options = {}

        for option in json.loads(authority.options):
            options[option["name"]] = option.get("value")
        email = options.get("email", current_app.config.get("ACME_EMAIL"))
        tel = options.get("telephone", current_app.config.get("ACME_TEL"))
        directory_url = options.get(
            "acme_url", current_app.config.get("ACME_DIRECTORY_URL")
        )

        existing_key = options.get(
            "acme_private_key", current_app.config.get("ACME_PRIVATE_KEY")
        )
        existing_regr = options.get("acme_regr", current_app.config.get("ACME_REGR"))

        if existing_key and existing_regr:
            current_app.logger.debug("Reusing existing ACME account")
            # Reuse the same account for each certificate issuance
            key = jose.JWK.json_loads(existing_key)
            regr = messages.RegistrationResource.json_loads(existing_regr)
            current_app.logger.debug(
                "Connecting with directory at {0}".format(directory_url)
            )
            net = ClientNetwork(key, account=regr)
            client = BackwardsCompatibleClientV2(net, key, directory_url)
            return client, {}
        else:
            # Create an account for each certificate issuance
            key = jose.JWKRSA(key=generate_private_key("RSA2048"))

            current_app.logger.debug("Creating a new ACME account")
            current_app.logger.debug(
                "Connecting with directory at {0}".format(directory_url)
            )

            net = ClientNetwork(key, account=None, timeout=3600)
            client = BackwardsCompatibleClientV2(net, key, directory_url)
            registration = client.new_account_and_tos(
                messages.NewRegistration.from_data(email=email)
            )

            # if store_account is checked, add the private_key and registration resources to the options
            if options['store_account']:
                new_options = json.loads(authority.options)
                # the key returned by fields_to_partial_json is missing the key type, so we add it manually
                key_dict = key.fields_to_partial_json()
                key_dict["kty"] = "RSA"
                acme_private_key = {
                    "name": "acme_private_key",
                    "value": json.dumps(key_dict)
                }
                new_options.append(acme_private_key)

                acme_regr = {
                    "name": "acme_regr",
                    "value": json.dumps({"body": {}, "uri": registration.uri})
                }
                new_options.append(acme_regr)

                authorities_service.update_options(authority.id, options=json.dumps(new_options))

            current_app.logger.debug("Connected: {0}".format(registration.uri))

        return client, registration
Example #16
0
def test_generate_private_key():
    from lemur.common.utils import generate_private_key

    assert generate_private_key('RSA2048')
    assert generate_private_key('RSA4096')
    assert generate_private_key('ECCPRIME192V1')
    assert generate_private_key('ECCPRIME256V1')
    assert generate_private_key('ECCSECP192R1')
    assert generate_private_key('ECCSECP224R1')
    assert generate_private_key('ECCSECP256R1')
    assert generate_private_key('ECCSECP384R1')
    assert generate_private_key('ECCSECP521R1')
    assert generate_private_key('ECCSECP256K1')
    assert generate_private_key('ECCSECT163K1')
    assert generate_private_key('ECCSECT233K1')
    assert generate_private_key('ECCSECT283K1')
    assert generate_private_key('ECCSECT409K1')
    assert generate_private_key('ECCSECT571K1')
    assert generate_private_key('ECCSECT163R2')
    assert generate_private_key('ECCSECT233R1')
    assert generate_private_key('ECCSECT283R1')
    assert generate_private_key('ECCSECT409R1')
    assert generate_private_key('ECCSECT571R2')

    with pytest.raises(Exception):
        generate_private_key('LEMUR')
Example #17
0
def create_csr(**csr_config):
    """
    Given a list of domains create the appropriate csr
    for those domains

    :param csr_config:
    """
    private_key = generate_private_key(csr_config.get('key_type'))

    builder = x509.CertificateSigningRequestBuilder()
    name_list = [x509.NameAttribute(x509.OID_COMMON_NAME, csr_config['common_name'])]
    if current_app.config.get('LEMUR_OWNER_EMAIL_IN_SUBJECT', True):
        name_list.append(x509.NameAttribute(x509.OID_EMAIL_ADDRESS, csr_config['owner']))
    if 'organization' in csr_config and csr_config['organization'].strip():
        name_list.append(x509.NameAttribute(x509.OID_ORGANIZATION_NAME, csr_config['organization']))
    if 'organizational_unit' in csr_config and csr_config['organizational_unit'].strip():
        name_list.append(x509.NameAttribute(x509.OID_ORGANIZATIONAL_UNIT_NAME, csr_config['organizational_unit']))
    if 'country' in csr_config and csr_config['country'].strip():
        name_list.append(x509.NameAttribute(x509.OID_COUNTRY_NAME, csr_config['country']))
    if 'state' in csr_config and csr_config['state'].strip():
        name_list.append(x509.NameAttribute(x509.OID_STATE_OR_PROVINCE_NAME, csr_config['state']))
    if 'location' in csr_config and csr_config['location'].strip():
        name_list.append(x509.NameAttribute(x509.OID_LOCALITY_NAME, csr_config['location']))
    builder = builder.subject_name(x509.Name(name_list))

    extensions = csr_config.get('extensions', {})
    critical_extensions = ['basic_constraints', 'sub_alt_names', 'key_usage']
    noncritical_extensions = ['extended_key_usage']
    for k, v in extensions.items():
        if v:
            if k in critical_extensions:
                current_app.logger.debug('Adding Critical Extension: {0} {1}'.format(k, v))
                if k == 'sub_alt_names':
                    if v['names']:
                        builder = builder.add_extension(v['names'], critical=True)
                else:
                    builder = builder.add_extension(v, critical=True)

            if k in noncritical_extensions:
                current_app.logger.debug('Adding Extension: {0} {1}'.format(k, v))
                builder = builder.add_extension(v, critical=False)

    ski = extensions.get('subject_key_identifier', {})
    if ski.get('include_ski', False):
        builder = builder.add_extension(
            x509.SubjectKeyIdentifier.from_public_key(private_key.public_key()),
            critical=False
        )

    request = builder.sign(
        private_key, hashes.SHA256(), default_backend()
    )

    # serialize our private key and CSR
    private_key = private_key.private_bytes(
        encoding=serialization.Encoding.PEM,
        format=serialization.PrivateFormat.TraditionalOpenSSL,  # would like to use PKCS8 but AWS ELBs don't like it
        encryption_algorithm=serialization.NoEncryption()
    ).decode('utf-8')

    csr = request.public_bytes(
        encoding=serialization.Encoding.PEM
    ).decode('utf-8')

    return csr, private_key
Example #18
0
def create_csr(**csr_config):
    """
    Given a list of domains create the appropriate csr
    for those domains

    :param csr_config:
    """

    private_key = generate_private_key(csr_config.get('key_type'))

    # TODO When we figure out a better way to validate these options they should be parsed as str
    builder = x509.CertificateSigningRequestBuilder()
    builder = builder.subject_name(x509.Name([
        x509.NameAttribute(x509.OID_COMMON_NAME, csr_config['common_name']),
        x509.NameAttribute(x509.OID_ORGANIZATION_NAME, csr_config['organization']),
        x509.NameAttribute(x509.OID_ORGANIZATIONAL_UNIT_NAME, csr_config['organizational_unit']),
        x509.NameAttribute(x509.OID_COUNTRY_NAME, csr_config['country']),
        x509.NameAttribute(x509.OID_STATE_OR_PROVINCE_NAME, csr_config['state']),
        x509.NameAttribute(x509.OID_LOCALITY_NAME, csr_config['location']),
        x509.NameAttribute(x509.OID_EMAIL_ADDRESS, csr_config['owner'])
    ]))

    builder = builder.add_extension(
        x509.BasicConstraints(ca=False, path_length=None), critical=True,
    )

    if csr_config.get('extensions'):
        for k, v in csr_config.get('extensions', {}).items():
            if k == 'sub_alt_names':
                # map types to their x509 objects
                general_names = []
                for name in v['names']:
                    if name['name_type'] == 'DNSName':
                        general_names.append(x509.DNSName(name['value']))

                builder = builder.add_extension(
                    x509.SubjectAlternativeName(general_names), critical=True
                )

    # TODO support more CSR options, none of the authority plugins currently support these options
    #    builder.add_extension(
    #        x509.KeyUsage(
    #            digital_signature=digital_signature,
    #            content_commitment=content_commitment,
    #            key_encipherment=key_enipherment,
    #            data_encipherment=data_encipherment,
    #            key_agreement=key_agreement,
    #            key_cert_sign=key_cert_sign,
    #            crl_sign=crl_sign,
    #            encipher_only=enchipher_only,
    #            decipher_only=decipher_only
    #        ), critical=True
    #    )
    #
    #    # we must maintain our own list of OIDs here
    #    builder.add_extension(
    #        x509.ExtendedKeyUsage(
    #            server_authentication=server_authentication,
    #            email=
    #        )
    #    )
    #
    #    builder.add_extension(
    #        x509.AuthorityInformationAccess()
    #    )
    #
    #    builder.add_extension(
    #        x509.AuthorityKeyIdentifier()
    #    )
    #
    #    builder.add_extension(
    #        x509.SubjectKeyIdentifier()
    #    )
    #
    #    builder.add_extension(
    #        x509.CRLDistributionPoints()
    #    )
    #
    #    builder.add_extension(
    #        x509.ObjectIdentifier(oid)
    #    )

    request = builder.sign(
        private_key, hashes.SHA256(), default_backend()
    )

    # serialize our private key and CSR
    private_key = private_key.private_bytes(
        encoding=serialization.Encoding.PEM,
        format=serialization.PrivateFormat.TraditionalOpenSSL,  # would like to use PKCS8 but AWS ELBs don't like it
        encryption_algorithm=serialization.NoEncryption()
    )

    if isinstance(private_key, bytes):
        private_key = private_key.decode('utf-8')

    csr = request.public_bytes(
        encoding=serialization.Encoding.PEM
    ).decode('utf-8')

    return csr, private_key