Beispiel #1
0
    def create_certificate(self, csr, issuer_options):
        """
        Creates an ACME certificate.

        :param csr:
        :param issuer_options:
        :return: :raise Exception:
        """
        authority = issuer_options.get('authority')
        create_immediately = issuer_options.get('create_immediately', False)
        acme_client, registration = setup_acme_client(authority)
        dns_provider = issuer_options.get('dns_provider')
        dns_provider_options = dns_provider.options
        if not dns_provider:
            raise InvalidConfiguration(
                "DNS Provider setting is required for ACME certificates.")
        credentials = json.loads(dns_provider.credentials)

        current_app.logger.debug("Using DNS provider: {0}".format(
            dns_provider.provider_type))
        dns_provider_type = __import__(dns_provider.provider_type, globals(),
                                       locals(), [], 1)
        account_number = credentials.get("account_id")
        if dns_provider.provider_type == 'route53' and not account_number:
            error = "Route53 DNS Provider {} does not have an account number configured.".format(
                dns_provider.name)
            current_app.logger.error(error)
            raise InvalidConfiguration(error)
        domains = get_domains(issuer_options)
        if not create_immediately:
            # Create pending authorizations that we'll need to do the creation
            authz_domains = []
            for d in domains:
                if type(d) == str:
                    authz_domains.append(d)
                else:
                    authz_domains.append(d.value)

            dns_authorization = authorization_service.create(
                account_number, authz_domains, dns_provider.provider_type)
            # Return id of the DNS Authorization
            return None, None, dns_authorization.id

        authorizations = get_authorizations(acme_client, account_number,
                                            domains, dns_provider_type,
                                            dns_provider_options)
        finalize_authorizations(acme_client, account_number, dns_provider_type,
                                authorizations, dns_provider_options)
        pem_certificate, pem_certificate_chain = request_certificate(
            acme_client, authorizations, csr)
        # TODO add external ID (if possible)
        return pem_certificate, pem_certificate_chain, None
Beispiel #2
0
    def __init__(self, *args, **kwargs):
        """Initialize the plugin with the appropriate details."""
        sender = current_app.config.get("LEMUR_EMAIL_SENDER", "ses").lower()

        if sender not in ["ses", "smtp"]:
            raise InvalidConfiguration(
                "Email sender type {0} is not recognized.")
Beispiel #3
0
    def revoke_certificate(self, certificate, crl_reason=0):
        if not self.reuse_account(certificate.authority):
            raise InvalidConfiguration(
                "There is no ACME account saved, unable to revoke the certificate."
            )
        acme_client, _ = self.setup_acme_client(certificate.authority)

        fullchain_com = jose.ComparableX509(
            OpenSSL.crypto.load_certificate(OpenSSL.crypto.FILETYPE_PEM,
                                            certificate.body))

        try:
            acme_client.revoke(
                fullchain_com, crl_reason
            )  # revocation reason as int (per RFC 5280 section 5.3.1)
        except (errors.ConflictError, errors.ClientError, errors.Error) as e:
            # Certificate already revoked.
            current_app.logger.error(
                "Certificate revocation failed with message: " + e.detail)
            metrics.send("acme_revoke_certificate_failure", "counter", 1)
            return False

        current_app.logger.warning("Certificate succesfully revoked: " +
                                   certificate.name)
        metrics.send("acme_revoke_certificate_success", "counter", 1)
        return True
Beispiel #4
0
    def create_certificate(self, csr, issuer_options):
        """
        Creates an ACME certificate.

        :param csr:
        :param issuer_options:
        :return: :raise Exception:
        """
        self.acme = AcmeDnsHandler()
        authority = issuer_options.get("authority")
        create_immediately = issuer_options.get("create_immediately", False)
        acme_client, registration = self.acme.setup_acme_client(authority)
        dns_provider = issuer_options.get("dns_provider", {})

        if dns_provider:
            dns_provider_options = dns_provider.options
            credentials = json.loads(dns_provider.credentials)
            current_app.logger.debug("Using DNS provider: {0}".format(
                dns_provider.provider_type))
            dns_provider_plugin = __import__(dns_provider.provider_type,
                                             globals(), locals(), [], 1)
            account_number = credentials.get("account_id")
            provider_type = dns_provider.provider_type
            if provider_type == "route53" and not account_number:
                error = "Route53 DNS Provider {} does not have an account number configured.".format(
                    dns_provider.name)
                current_app.logger.error(error)
                raise InvalidConfiguration(error)
        else:
            dns_provider = {}
            dns_provider_options = None
            account_number = None
            provider_type = None

        domains = self.acme.get_domains(issuer_options)
        if not create_immediately:
            # Create pending authorizations that we'll need to do the creation
            dns_authorization = authorization_service.create(
                account_number, domains, provider_type)
            # Return id of the DNS Authorization
            return None, None, dns_authorization.id

        authorizations = self.acme.get_authorizations(
            acme_client,
            account_number,
            domains,
            dns_provider_plugin,
            dns_provider_options,
        )
        self.acme.finalize_authorizations(
            acme_client,
            account_number,
            dns_provider_plugin,
            authorizations,
            dns_provider_options,
        )
        pem_certificate, pem_certificate_chain = self.acme.request_certificate(
            acme_client, authorizations, csr)
        # TODO add external ID (if possible)
        return pem_certificate, pem_certificate_chain, None
Beispiel #5
0
    def create_authority(options):
        """
        Creates an authority, this authority is then used by Lemur to allow a user
        to specify which Certificate Authority they want to sign their certificate.

        :param options:
        :return:
        """
        role = {"username": "", "password": "", "name": "ejbca"}

        plugin_options = options.get("plugin", {}).get("plugin_options")
        if not plugin_options:
            error = "Invalid options for lemur_ejbca plugin: {}".format(
                options)
            current_app.logger.error(error)
            raise InvalidConfiguration(error)
        # Define static auth_root based off configuration variable by default. However, if user has passed a
        # certificate, use this certificate as the root.
        ejbca_root = current_app.config.get("EJBCA_ROOT")
        chain = ""

        for option in plugin_options:
            if option.get("name") == "certificate":
                ejbca_root = option.get("value")
            elif option.get("name") == "chain":
                chain = option.get("chain")
        return ejbca_root, chain, [role]
Beispiel #6
0
    def create_authority(options):
        """
        Creates an authority, this authority is then used by Lemur to allow a user
        to specify which Certificate Authority they want to sign their certificate.

        :param options:
        :return:
        """
        name = "acme"
        if options['name']:
            name += "_" + '_'.join(options['name'].split(" "))
        role = {"username": "", "password": "", "name": name}

        plugin_options = options.get("plugin", {}).get("plugin_options")
        if not plugin_options:
            error = "Invalid options for lemur_acme plugin: {}".format(options)
            current_app.logger.error(error)
            raise InvalidConfiguration(error)
        # Define static acme_root based off configuration variable by default. However, if user has passed a
        # certificate, use this certificate as the root.
        acme_root = current_app.config.get("ACME_ROOT")
        for option in plugin_options:
            if option.get("name") == "certificate":
                acme_root = option.get("value")
        return acme_root, "", [role]
Beispiel #7
0
def validate_conf(app, required_vars):
    """
    Ensures that the given fields are set in the applications conf.

    :param app:
    :param required_vars: list
    """
    for var in required_vars:
        if not app.config.get(var):
            raise InvalidConfiguration("Required variable '{var}' is not set in Lemur's conf.".format(var=var))
Beispiel #8
0
    def create_certificate(self, csr, issuer_options):
        """
        Creates an ACME certificate.

        :param csr:
        :param issuer_options:
        :return: :raise Exception:
        """
        self.acme = AcmeDnsHandler()
        authority = issuer_options.get("authority")
        create_immediately = issuer_options.get("create_immediately", False)
        acme_client, registration = self.acme.setup_acme_client(authority)
        domains = self.acme.get_domains(issuer_options)
        dns_provider = issuer_options.get("dns_provider", {})

        if dns_provider:
            for domain in domains:
                # Currently, we only support specifying one DNS provider per certificate, even if that
                # certificate has multiple SANs that may belong to different provid
                self.acme.dns_providers_for_domain[domain] = [dns_provider]

            credentials = json.loads(dns_provider.credentials)
            current_app.logger.debug("Using DNS provider: {0}".format(
                dns_provider.provider_type))
            account_number = credentials.get("account_id")
            provider_type = dns_provider.provider_type
            if provider_type == "route53" and not account_number:
                error = "Route53 DNS Provider {} does not have an account number configured.".format(
                    dns_provider.name)
                current_app.logger.error(error)
                raise InvalidConfiguration(error)
        else:
            dns_provider = {}
            account_number = None
            provider_type = None

            for domain in domains:
                self.acme.autodetect_dns_providers(domain)

        # Create pending authorizations that we'll need to do the creation
        dns_authorization = authorization_service.create(
            account_number, domains, provider_type)

        if not create_immediately:
            # Return id of the DNS Authorization
            return None, None, dns_authorization.id

        pem_certificate, pem_certificate_chain = self.create_certificate_immediately(
            acme_client, dns_authorization, csr)
        # TODO add external ID (if possible)
        return pem_certificate, pem_certificate_chain, None
Beispiel #9
0
def check_validation(validation):
    """
    Checks that the given validation string compiles successfully.

    :param validation:
    :return str: The validation pattern, if compilation succeeds
    """

    try:
        compiled = re.compile(validation)
    except re.error as e:
        raise InvalidConfiguration(f"Validation {validation} couldn't compile. Reason: {e}")

    return compiled.pattern
Beispiel #10
0
    def create_authority(options):
        """
        Creates an authority, this authority is then used by Lemur to allow a user
        to specify which Certificate Authority they want to sign their certificate.

        :param options:
        :return:
        """
        role = {'username': '', 'password': '', 'name': 'acme'}
        plugin_options = options.get('plugin', {}).get('plugin_options')
        if not plugin_options:
            error = "Invalid options for lemur_acme plugin: {}".format(options)
            current_app.logger.error(error)
            raise InvalidConfiguration(error)
        # Define static acme_root based off configuration variable by default. However, if user has passed a
        # certificate, use this certificate as the root.
        acme_root = current_app.config.get('ACME_ROOT')
        for option in plugin_options:
            if option.get('name') == 'certificate':
                acme_root = option.get('value')
        return acme_root, "", [role]