Beispiel #1
0
def sync(source, user, ttl_hours=2):
    try:
        new_certs, updated_certs, updated_certs_by_hash = sync_certificates(
            source, user)
        metrics.send("sync.updated_certs_by_hash",
                     "gauge",
                     updated_certs_by_hash,
                     metric_tags={"source": source.label})

        new_endpoints, updated_endpoints, updated_endpoints_by_hash = sync_endpoints(
            source)
        metrics.send("sync.updated_endpoints_by_hash",
                     "gauge",
                     updated_endpoints_by_hash,
                     metric_tags={"source": source.label})

        expired_endpoints = expire_endpoints(source, ttl_hours)

        source.last_run = arrow.utcnow()
        database.update(source)

        return {
            "endpoints": (new_endpoints, updated_endpoints, expired_endpoints),
            "certificates": (new_certs, updated_certs),
        }
    except Exception as e:  # noqa
        current_app.logger.warning(
            f"Sync source '{source.label}' aborted: {e}")
        capture_exception()
        raise e
Beispiel #2
0
def create(**kwargs):
    """
    Creates a new certificate.
    """
    from lemur.notifications import service as notification_service
    cert, private_key, cert_chain = mint(kwargs)

    cert.owner = kwargs['owner']

    database.create(cert)
    cert.description = kwargs['description']
    g.user.certificates.append(cert)
    database.update(g.user)

    # do this after the certificate has already been created because if it fails to upload to the third party
    # we do not want to lose the certificate information.
    database.update_list(cert, 'destinations', Destination, kwargs.get('destinations'))
    database.update_list(cert, 'replaces', Certificate, kwargs['replacements'])
    database.update_list(cert, 'notifications', Notification, kwargs.get('notifications'))

    # create default notifications for this certificate if none are provided
    notifications = cert.notifications
    if not kwargs.get('notifications'):
        notification_name = "DEFAULT_{0}".format(cert.owner.split('@')[0].upper())
        notifications += notification_service.create_default_expiration_notifications(notification_name, [cert.owner])

    notification_name = 'DEFAULT_SECURITY'
    notifications += notification_service.create_default_expiration_notifications(notification_name,
                                                                                  current_app.config.get('LEMUR_SECURITY_TEAM_EMAIL'))
    cert.notifications = notifications

    database.update(cert)
    return cert
Beispiel #3
0
def increment_attempt(pending_certificate):
    """
    Increments pending certificate attempt counter and updates it in the database.
    """
    pending_certificate.number_attempts += 1
    database.update(pending_certificate)
    return pending_certificate.number_attempts
Beispiel #4
0
def create(kwargs):
    """
    Create a new authority.

    :return:
    """

    issuer = plugins.get(kwargs.get('pluginName'))

    kwargs['creator'] = g.current_user.email
    cert_body, intermediate, issuer_roles = issuer.create_authority(kwargs)

    cert = Certificate(cert_body, chain=intermediate)
    cert.owner = kwargs['ownerEmail']

    if kwargs['caType'] == 'subca':
        cert.description = "This is the ROOT certificate for the {0} sub certificate authority the parent \
                                authority is {1}.".format(
            kwargs.get('caName'), kwargs.get('caParent'))
    else:
        cert.description = "This is the ROOT certificate for the {0} certificate authority.".format(
            kwargs.get('caName'))

    cert.user = g.current_user

    cert.notifications = notification_service.create_default_expiration_notifications(
        'DEFAULT_SECURITY',
        current_app.config.get('LEMUR_SECURITY_TEAM_EMAIL'))

    # we create and attach any roles that the issuer gives us
    role_objs = []
    for r in issuer_roles:

        role = role_service.create(
            r['name'],
            password=r['password'],
            description="{0} auto generated role".format(
                kwargs.get('pluginName')),
            username=r['username'])

        # the user creating the authority should be able to administer it
        if role.username == 'admin':
            g.current_user.roles.append(role)

        role_objs.append(role)

    authority = Authority(kwargs.get('caName'),
                          kwargs['ownerEmail'],
                          kwargs['pluginName'],
                          cert_body,
                          description=kwargs['caDescription'],
                          chain=intermediate,
                          roles=role_objs)

    database.update(cert)
    authority = database.create(authority)

    g.current_user.authorities.append(authority)

    return authority
Beispiel #5
0
def cleanup_after_revoke(certificate):
    """
    Perform the needed cleanup for a revoked certificate. This includes -
    1. Disabling notification
    2. Disabling auto-rotation
    3. Update certificate status to 'revoked'
    4. Remove from AWS
    :param certificate: Certificate object to modify and update in DB
    :return: None
    """
    certificate.notify = False
    certificate.rotation = False
    certificate.status = 'revoked'

    error_message = ""

    for destination in list(certificate.destinations):
        try:
            remove_from_destination(certificate, destination)
            certificate.destinations.remove(destination)
        except Exception as e:
            # This cleanup is the best-effort since certificate is already revoked at this point.
            # We will capture the exception and move on to the next destination
            sentry.captureException()
            error_message = error_message + f"Failed to remove destination: {destination.label}. {str(e)}. "

    database.update(certificate)
    return error_message
Beispiel #6
0
def update(endpoint_id, **kwargs):
    endpoint = database.get(Endpoint, endpoint_id)

    endpoint.policy = kwargs["policy"]
    endpoint.certificate = kwargs["certificate"]
    endpoint.source = kwargs["source"]
    endpoint.certificate_path = kwargs.get("certificate_path")
    endpoint.registry_type = kwargs.get("registry_type")
    existing_alias = {}
    for e in endpoint.aliases:
        existing_alias[e.alias] = e
    endpoint.aliases = []
    if "aliases" in kwargs:
        for name in kwargs["aliases"]:
            if name in existing_alias:
                endpoint.aliases.append(existing_alias[name])
            else:
                endpoint.aliases.append(EndpointDnsAlias(alias=name))
    endpoint.last_updated = arrow.utcnow()
    metrics.send(
        "endpoint_updated", "counter", 1,
        metric_tags={"source": endpoint.source.label, "type": endpoint.type}
    )
    database.update(endpoint)
    return endpoint
Beispiel #7
0
def increment_attempt(pending_certificate):
    """
    Increments pending certificate attempt counter and updates it in the database.
    """
    pending_certificate.number_attempts += 1
    database.update(pending_certificate)
    return pending_certificate.number_attempts
Beispiel #8
0
def create(**kwargs):
    """
    Creates a new certificate.
    """
    from lemur.notifications import service as notification_service

    cert, private_key, cert_chain = mint(kwargs)

    cert.owner = kwargs["owner"]

    database.create(cert)
    cert.description = kwargs["description"]
    g.user.certificates.append(cert)
    database.update(g.user)

    # do this after the certificate has already been created because if it fails to upload to the third party
    # we do not want to lose the certificate information.
    database.update_list(cert, "destinations", Destination, kwargs.get("destinations"))

    database.update_list(cert, "notifications", Notification, kwargs.get("notifications"))

    # create default notifications for this certificate if none are provided
    notifications = []
    if not kwargs.get("notifications"):
        notification_name = "DEFAULT_{0}".format(cert.owner.split("@")[0].upper())
        notifications += notification_service.create_default_expiration_notifications(notification_name, [cert.owner])

    notification_name = "DEFAULT_SECURITY"
    notifications += notification_service.create_default_expiration_notifications(
        notification_name, current_app.config.get("LEMUR_SECURITY_TEAM_EMAIL")
    )
    cert.notifications = notifications

    database.update(cert)
    return cert
Beispiel #9
0
def mint(issuer_options):
    """
    Minting is slightly different for each authority.
    Support for multiple authorities is handled by individual plugins.

    :param issuer_options:
    """
    authority = issuer_options['authority']

    issuer = plugins.get(authority.plugin_name)

    # allow the CSR to be specified by the user
    if not issuer_options.get('csr'):
        csr, private_key = create_csr(issuer_options)
    else:
        csr = str(issuer_options.get('csr'))
        private_key = None

    issuer_options['creator'] = g.user.email
    cert_body, cert_chain = issuer.create_certificate(csr, issuer_options)

    cert = Certificate(cert_body, private_key, cert_chain)

    cert.user = g.user
    cert.authority = authority
    database.update(cert)
    return cert, private_key, cert_chain,
Beispiel #10
0
def mint(issuer_options):
    """
    Minting is slightly different for each authority.
    Support for multiple authorities is handled by individual plugins.

    :param issuer_options:
    """
    authority = issuer_options['authority']

    issuer = plugins.get(authority.plugin_name)

    # allow the CSR to be specified by the user
    if not issuer_options.get('csr'):
        csr, private_key = create_csr(issuer_options)
    else:
        csr = issuer_options.get('csr')
        private_key = None

    issuer_options['creator'] = g.user.email
    cert_body, cert_chain = issuer.create_certificate(csr, issuer_options)

    cert = Certificate(cert_body, private_key, cert_chain)

    cert.user = g.user
    cert.authority = authority
    database.update(cert)
    return cert, private_key, cert_chain,
Beispiel #11
0
def update(endpoint_id, **kwargs):
    endpoint = database.get(Endpoint, endpoint_id)

    endpoint.policy = kwargs['policy']
    endpoint.certificate = kwargs['certificate']
    database.update(endpoint)
    return endpoint
Beispiel #12
0
def set_domains(dns_provider, domains):
    """
    Increments pending certificate attempt counter and updates it in the database.
    """
    dns_provider.domains = domains
    database.update(dns_provider)
    return dns_provider
Beispiel #13
0
def check_revoked():
    """
    Function attempts to update Lemur's internal cache with revoked
    certificates. This is called periodically by Lemur. It checks both
    CRLs and OCSP to see if a certificate is revoked. If Lemur is unable
    encounters an issue with verification it marks the certificate status
    as `unknown`.
    """
    for cert in get_all_certs():
        try:
            if cert.chain:
                status = verify_string(cert.body, cert.chain)
            else:
                status = verify_string(cert.body, "")

            if status is None:
                cert.status = 'unknown'
            else:
                cert.status = 'valid' if status else 'revoked'

        except Exception as e:
            sentry.captureException()
            current_app.logger.exception(e)
            cert.status = 'unknown'

        database.update(cert)
Beispiel #14
0
def create_certificate(pending_certificate, certificate, user):
    """
    Create and store a certificate with pending certificate's info

    :arg pending_certificate: PendingCertificate which will populate the certificate
    :arg certificate: dict from Authority, which contains the body, chain and external id
    :arg user: User that called this function, used as 'creator' of the certificate if it does not have an owner
    """
    certificate["owner"] = pending_certificate.owner
    data, errors = CertificateUploadInputSchema().load(certificate)
    if errors:
        raise Exception(
            "Unable to create certificate: {reasons}".format(reasons=errors))

    data.update(vars(pending_certificate))
    # Copy relationships, vars doesn't copy this without explicit fields
    data["notifications"] = list(pending_certificate.notifications)
    data["destinations"] = list(pending_certificate.destinations)
    data["sources"] = list(pending_certificate.sources)
    data["roles"] = list(pending_certificate.roles)
    data["replaces"] = list(pending_certificate.replaces)
    data["rotation_policy"] = pending_certificate.rotation_policy

    # Replace external id and chain with the one fetched from source
    data["external_id"] = certificate["external_id"]
    data["chain"] = certificate["chain"]
    creator = user_service.get_by_email(pending_certificate.owner)
    if not creator:
        # Owner of the pending certificate is not the creator, so use the current user who called
        # this as the creator (usually lemur)
        creator = user

    if pending_certificate.rename:
        # If generating name from certificate, remove the one from pending certificate
        del data["name"]
    data["creator"] = creator

    cert = certificate_service.import_certificate(**data)
    database.update(cert)

    metrics.send("certificate_issued",
                 "counter",
                 1,
                 metric_tags=dict(owner=cert.owner, issuer=cert.issuer))
    log_service.audit_log(
        "certificate_from_pending_certificate", cert.name,
        f"Created from the pending certificate {pending_certificate.name}")
    log_data = {
        "function": "lemur.certificates.service.create",
        "owner": cert.owner,
        "name": cert.name,
        "serial": cert.serial,
        "issuer": cert.issuer,
        "not_after": cert.not_after.format('YYYY-MM-DD HH:mm:ss'),
        "not_before": cert.not_before.format('YYYY-MM-DD HH:mm:ss'),
        "sans": cert.san,
    }
    current_app.logger.info(log_data)
    return cert
Beispiel #15
0
def sync(source, user):
    new_certs, updated_certs = sync_certificates(source, user)
    new_endpoints, updated_endpoints = sync_endpoints(source)

    source.last_run = arrow.utcnow()
    database.update(source)

    return {'endpoints': (new_endpoints, updated_endpoints), 'certificates': (new_certs, updated_certs)}
Beispiel #16
0
def sync(source, user):
    new, updated = sync_certificates(source, user)
    new, updated = sync_endpoints(source)

    source.last_run = arrow.utcnow()
    database.update(source)

    return {'endpoints': (new, updated), 'certificates': (new, updated)}
Beispiel #17
0
def certificate_update(certificate, source):
    for s in certificate.sources:
        if s.label == source.label:
            break
    else:
        certificate.sources.append(source)

    sync_update_destination(certificate, source)
    database.update(certificate)
Beispiel #18
0
def certificate_update(certificate, source):
    for s in certificate.sources:
        if s.label == source.label:
            break
    else:
        certificate.sources.append(source)

    sync_update_destination(certificate, source)
    database.update(certificate)
Beispiel #19
0
def update(endpoint_id, **kwargs):
    endpoint = database.get(Endpoint, endpoint_id)

    endpoint.policy = kwargs['policy']
    endpoint.certificate = kwargs['certificate']
    endpoint.source = kwargs['source']
    metrics.send('endpoint_added', 'counter', 1)
    database.update(endpoint)
    return endpoint
Beispiel #20
0
def update(endpoint_id, **kwargs):
    endpoint = database.get(Endpoint, endpoint_id)

    endpoint.policy = kwargs['policy']
    endpoint.certificate = kwargs['certificate']
    endpoint.source = kwargs['source']
    endpoint.last_updated = arrow.utcnow()
    metrics.send('endpoint_updated', 'counter', 1, metric_tags={'source': endpoint.source.label})
    database.update(endpoint)
    return endpoint
Beispiel #21
0
def update(endpoint_id, **kwargs):
    endpoint = database.get(Endpoint, endpoint_id)

    endpoint.policy = kwargs['policy']
    endpoint.certificate = kwargs['certificate']
    endpoint.source = kwargs['source']
    endpoint.last_updated = arrow.utcnow()
    metrics.send('endpoint_updated', 'counter', 1, metric_tags={'source': endpoint.source.label})
    database.update(endpoint)
    return endpoint
Beispiel #22
0
def create(kwargs):
    """
    Create a new authority.

    :rtype : Authority
    :return:
    """

    issuer = plugins.get(kwargs.get('pluginName'))

    kwargs['creator'] = g.current_user.email
    cert_body, intermediate, issuer_roles = issuer.create_authority(kwargs)

    cert = Certificate(cert_body, chain=intermediate)
    cert.owner = kwargs['ownerEmail']
    cert.description = "This is the ROOT certificate for the {0} certificate authority".format(kwargs.get('caName'))
    cert.user = g.current_user

    cert.notifications = notification_service.create_default_expiration_notifications(
        'DEFAULT_SECURITY',
        current_app.config.get('LEMUR_SECURITY_TEAM_EMAIL')
    )

    # we create and attach any roles that the issuer gives us
    role_objs = []
    for r in issuer_roles:

        role = role_service.create(
            r['name'],
            password=r['password'],
            description="{0} auto generated role".format(kwargs.get('pluginName')),
            username=r['username'])

        # the user creating the authority should be able to administer it
        if role.username == 'admin':
            g.current_user.roles.append(role)

        role_objs.append(role)

    authority = Authority(
        kwargs.get('caName'),
        kwargs['ownerEmail'],
        kwargs['pluginName'],
        cert_body,
        description=kwargs['caDescription'],
        chain=intermediate,
        roles=role_objs
    )

    database.update(cert)
    authority = database.create(authority)

    g.current_user.authorities.append(authority)

    return authority
Beispiel #23
0
def rotate_certificate(endpoint, new_cert):
    """Rotates a certificate on a given endpoint."""
    try:
        endpoint.source.plugin.update_endpoint(endpoint, new_cert)
        endpoint.certificate = new_cert
        database.update(endpoint)
        metrics.send('certificate_rotate_success', 'counter', 1, metric_tags={'endpoint': endpoint.name, 'source': endpoint.source.label})
    except Exception as e:
        metrics.send('certificate_rotate_failure', 'counter', 1, metric_tags={'endpoint': endpoint.name})
        current_app.logger.exception(e)
        raise e
Beispiel #24
0
def sync(source, user):
    new_certs, updated_certs = sync_certificates(source, user)
    new_endpoints, updated_endpoints = sync_endpoints(source)

    source.last_run = arrow.utcnow()
    database.update(source)

    return {
        "endpoints": (new_endpoints, updated_endpoints),
        "certificates": (new_certs, updated_certs),
    }
Beispiel #25
0
def increment_attempt(pending_certificate):
    """
    Increments pending certificate attempt counter and updates it in the database.
    """
    pending_certificate.number_attempts += 1
    database.update(pending_certificate)

    log_service.audit_log("increment_attempt_pending_certificate",
                          pending_certificate.name,
                          "Incremented attempts for the pending certificate")
    return pending_certificate.number_attempts
Beispiel #26
0
    def run(self, elb_list, chain_path, cert_name, cert_prefix, description):

        for e in open(elb_list, 'r').readlines():
            elb_name, account_id, region, from_port, to_port, protocol = e.strip().split(',')

            if cert_name:
                arn = "arn:aws:iam::{0}:server-certificate/{1}".format(account_id, cert_name)

            else:
                # if no cert name is provided we need to discover it
                listeners = elb.get_listeners(account_id, region, elb_name)

                # get the listener we care about
                for listener in listeners:
                    if listener[0] == int(from_port) and listener[1] == int(to_port):
                        arn = listener[4]
                        name = get_name_from_arn(arn)
                        certificate = cert_service.get_by_name(name)
                        break
                else:
                    sys.stdout.write("[-] Could not find ELB {0}".format(elb_name))
                    continue

                if not certificate:
                    sys.stdout.write("[-] Could not find certificate {0} in Lemur".format(name))
                    continue

                dests = []
                for d in certificate.destinations:
                    dests.append({'id': d.id})

                nots = []
                for n in certificate.notifications:
                    nots.append({'id': n.id})

                new_certificate = database.clone(certificate)

                if cert_prefix:
                    new_certificate.name = "{0}-{1}".format(cert_prefix, new_certificate.name)

                new_certificate.chain = open(chain_path, 'r').read()
                new_certificate.description = "{0} - {1}".format(new_certificate.description, description)

                new_certificate = database.create(new_certificate)
                database.update_list(new_certificate, 'destinations', Destination, dests)
                database.update_list(new_certificate, 'notifications', Notification, nots)
                database.update(new_certificate)

                arn = new_certificate.get_arn(account_id)

            elb.update_listeners(account_id, region, elb_name, [(from_port, to_port, protocol, arn)], [from_port])

            sys.stdout.write("[+] Updated {0} to use {1}\n".format(elb_name, new_certificate.name))
Beispiel #27
0
def remove_source_association(certificate, source):
    certificate.sources.remove(source)
    database.update(certificate)

    metrics.send(
        "delete_certificate_source_association",
        "counter",
        1,
        metric_tags={"status": SUCCESS_METRIC_STATUS,
                     "source": source.label,
                     "certificate": certificate.name}
    )
Beispiel #28
0
def rotate_certificate(endpoint, new_cert):
    """
    Rotates a certificate on a given endpoint.

    :param endpoint:
    :param new_cert:
    :return:
    """
    # ensure that certificate is available for rotation
    endpoint.source.plugin.update_endpoint(endpoint, new_cert)
    endpoint.certificate = new_cert
    database.update(endpoint)
Beispiel #29
0
    def run(self, elb_list, chain_path, cert_name, cert_prefix, description):

        for e in open(elb_list, 'r').readlines():
            elb_name, account_id, region, from_port, to_port, protocol = e.strip().split(',')

            if cert_name:
                arn = "arn:aws:iam::{0}:server-certificate/{1}".format(account_id, cert_name)

            else:
                # if no cert name is provided we need to discover it
                listeners = elb.get_listeners(account_id, region, elb_name)

                # get the listener we care about
                for listener in listeners:
                    if listener[0] == int(from_port) and listener[1] == int(to_port):
                        arn = listener[4]
                        name = get_name_from_arn(arn)
                        certificate = cert_service.get_by_name(name)
                        break
                else:
                    sys.stdout.write("[-] Could not find ELB {0}".format(elb_name))
                    continue

                if not certificate:
                    sys.stdout.write("[-] Could not find certificate {0} in Lemur".format(name))
                    continue

                dests = []
                for d in certificate.destinations:
                    dests.append({'id': d.id})

                nots = []
                for n in certificate.notifications:
                    nots.append({'id': n.id})

                new_certificate = database.clone(certificate)

                if cert_prefix:
                    new_certificate.name = "{0}-{1}".format(cert_prefix, new_certificate.name)

                new_certificate.chain = open(chain_path, 'r').read()
                new_certificate.description = "{0} - {1}".format(new_certificate.description, description)

                new_certificate = database.create(new_certificate)
                database.update_list(new_certificate, 'destinations', Destination, dests)
                database.update_list(new_certificate, 'notifications', Notification, nots)
                database.update(new_certificate)

                arn = new_certificate.get_arn(account_id)

            elb.update_listeners(account_id, region, elb_name, [(from_port, to_port, protocol, arn)], [from_port])

            sys.stdout.write("[+] Updated {0} to use {1}\n".format(elb_name, new_certificate.name))
Beispiel #30
0
def set_third_party(role_id, third_party_status=False):
    """
    Sets a role to be a third party role. A user should pretty much never
    call this directly.

    :param role_id:
    :param third_party_status:
    :return:
    """
    role = get(role_id)
    role.third_party = third_party_status
    database.update(role)
    return role
Beispiel #31
0
def cancel(pending_certificate, **kwargs):
    """
    Cancel a pending certificate.  A check should be done prior to this function to decide to
    revoke the certificate or just abort cancelling.
    Args:
        pending_certificate: PendingCertificate to be cancelled
    Returns: the pending certificate if successful, raises Exception if there was an issue
    """
    plugin = plugins.get(pending_certificate.authority.plugin_name)
    plugin.cancel_ordered_certificate(pending_certificate, **kwargs)
    pending_certificate.status = 'Cancelled'
    database.update(pending_certificate)
    return pending_certificate
Beispiel #32
0
def update(domain_id, name, sensitive):
    """
    Update an existing domain

    :param domain_id:
    :param name:
    :param sensitive:
    :return:
    """
    domain = get(domain_id)
    domain.name = name
    domain.sensitive = sensitive
    database.update(domain)
Beispiel #33
0
def cancel(pending_certificate, **kwargs):
    """
    Cancel a pending certificate.  A check should be done prior to this function to decide to
    revoke the certificate or just abort cancelling.
    Args:
        pending_certificate: PendingCertificate to be cancelled
    Returns: the pending certificate if successful, raises Exception if there was an issue
    """
    plugin = plugins.get(pending_certificate.authority.plugin_name)
    plugin.cancel_ordered_certificate(pending_certificate, **kwargs)
    pending_certificate.status = 'Cancelled'
    database.update(pending_certificate)
    return pending_certificate
Beispiel #34
0
def set_third_party(role_id, third_party_status=False):
    """
    Sets a role to be a third party role. A user should pretty much never
    call this directly.

    :param role_id:
    :param third_party_status:
    :return:
    """
    role = get(role_id)
    role.third_party = third_party_status
    database.update(role)
    return role
Beispiel #35
0
def update(endpoint_id, **kwargs):
    endpoint = database.get(Endpoint, endpoint_id)

    endpoint.policy = kwargs["policy"]
    endpoint.certificate = kwargs["certificate"]
    endpoint.source = kwargs["source"]
    endpoint.last_updated = arrow.utcnow()
    metrics.send("endpoint_updated",
                 "counter",
                 1,
                 metric_tags={"source": endpoint.source.label})
    database.update(endpoint)
    return endpoint
Beispiel #36
0
def update(domain_id, name, sensitive):
    """
    Update an existing domain

    :param domain_id:
    :param name:
    :param sensitive:
    :return:
    """
    domain = get(domain_id)
    domain.name = name
    domain.sensitive = sensitive
    database.update(domain)
Beispiel #37
0
def certificate_create(certificate, source):
    data, errors = CertificateUploadInputSchema().load(certificate)

    if errors:
        raise Exception(
            "Unable to import certificate: {reasons}".format(reasons=errors))

    cert = cert_service.import_certificate(**data)
    cert.description = "This certificate was automatically discovered by Lemur"
    cert.sources.append(source)
    sync_update_destination(cert, source)
    database.update(cert)
    return cert
Beispiel #38
0
def create_certificate(pending_certificate, certificate, user):
    """
    Create and store a certificate with pending certificate's info
    Args:
        pending_certificate: PendingCertificate which will populate the certificate
        certificate: dict from Authority, which contains the body, chain and external id
        user: User that called this function, used as 'creator' of the certificate if it does
              not have an owner
    """
    # check if the pending_certificate already has been resolved, in that case return
    # existing certificate
    maybe_resolved_cert = get(pending_certificate.id)
    if maybe_resolved_cert and maybe_resolved_cert.resolved and maybe_resolved_cert.resolved_cert_id:
        current_app.logger.warning(
            "Trying to resolve an already resolved certificate, returning existing resolved certificate"
        )
        return certificate_service.get(maybe_resolved_cert.resolved_cert_id)

    certificate["owner"] = pending_certificate.owner
    data, errors = CertificateUploadInputSchema().load(certificate)
    if errors:
        raise Exception(
            "Unable to create certificate: {reasons}".format(reasons=errors))

    data.update(vars(pending_certificate))
    # Copy relationships, vars doesn't copy this without explicit fields
    data["notifications"] = list(pending_certificate.notifications)
    data["destinations"] = list(pending_certificate.destinations)
    data["sources"] = list(pending_certificate.sources)
    data["roles"] = list(pending_certificate.roles)
    data["replaces"] = list(pending_certificate.replaces)
    data["rotation_policy"] = pending_certificate.rotation_policy
    data["authority"] = pending_certificate.authority

    # Replace external id and chain with the one fetched from source
    data["external_id"] = certificate["external_id"]
    data["chain"] = certificate["chain"]
    creator = user_service.get_by_email(pending_certificate.owner)
    if not creator:
        # Owner of the pending certificate is not the creator, so use the current user who called
        # this as the creator (usually lemur)
        creator = user

    if pending_certificate.rename:
        # If generating name from certificate, remove the one from pending certificate
        del data["name"]
    data["creator"] = creator

    cert = certificate_service.import_certificate(**data)
    database.update(cert)
    return cert
Beispiel #39
0
def certificate_create(certificate, source):
    data, errors = CertificateUploadInputSchema().load(certificate)

    if errors:
        raise Exception("Unable to import certificate: {reasons}".format(reasons=errors))

    data['creator'] = certificate['creator']

    cert = certificate_service.import_certificate(**data)
    cert.description = "This certificate was automatically discovered by Lemur"
    cert.sources.append(source)
    sync_update_destination(cert, source)
    database.update(cert)
    return cert
Beispiel #40
0
def check_revoked():
    """
    Function attempts to update Lemur's internal cache with revoked
    certificates. This is called periodically by Lemur. It checks both
    CRLs and OCSP to see if a certificate is revoked. If Lemur is unable
    encounters an issue with verification it marks the certificate status
    as `unknown`.
    """

    log_data = {
        "function": f"{__name__}.{sys._getframe().f_code.co_name}",
        "message": "Checking for revoked Certificates"
    }

    certs = get_all_valid_certs(
        current_app.config.get("SUPPORTED_REVOCATION_AUTHORITY_PLUGINS", []))
    for cert in certs:
        try:
            if cert.chain:
                status = verify_string(cert.body, cert.chain)
            elif cert.issuer == '<selfsigned>':
                status = True
            else:
                status = verify_string(cert.body, "")

            cert.status = "valid" if status else "revoked"

            if cert.status == "revoked":
                log_data["valid"] = cert.status
                log_data["certificate_name"] = cert.name
                log_data["certificate_id"] = cert.id
                metrics.send(
                    "certificate_revoked",
                    "counter",
                    1,
                    metric_tags={
                        "status": log_data["valid"],
                        "certificate_name": log_data["certificate_name"],
                        "certificate_id": log_data["certificate_id"]
                    },
                )
                current_app.logger.info(log_data)

        except Exception as e:
            sentry.captureException()
            current_app.logger.exception(e)
            cert.status = "unknown"

        database.update(cert)
Beispiel #41
0
def certificate_create(certificate, source):
    data, errors = CertificateUploadInputSchema().load(certificate)

    if errors:
        current_app.logger.error(f"Unable to import certificate: {errors}")
        return

    data["creator"] = certificate["creator"]

    cert = certificate_service.import_certificate(**data)
    cert.description = "This certificate was automatically discovered by Lemur"
    cert.sources.append(source)
    sync_update_destination(cert, source)
    database.update(cert)
    return cert
Beispiel #42
0
def backfill_signing_algo():
    """
    Will attempt to backfill the signing_algorithm column

    :return:
    """
    from cryptography import x509
    from cryptography.hazmat.backends import default_backend
    from lemur.certificates.models import get_signing_algorithm
    for c in cert_service.get_all_certs():
        cert = x509.load_pem_x509_certificate(str(c.body), default_backend())
        c.signing_algorithm = get_signing_algorithm(cert)
        c.signing_algorithm
        database.update(c)
        print(c.signing_algorithm)
Beispiel #43
0
def backfill_signing_algo():
    """
    Will attempt to backfill the signing_algorithm column

    :return:
    """
    from cryptography import x509
    from cryptography.hazmat.backends import default_backend
    from lemur.certificates.models import get_signing_algorithm
    for c in cert_service.get_all_certs():
        cert = x509.load_pem_x509_certificate(str(c.body), default_backend())
        c.signing_algorithm = get_signing_algorithm(cert)
        c.signing_algorithm
        database.update(c)
        print(c.signing_algorithm)
Beispiel #44
0
def update(role_id, name, description, users):
    """
    Update a role

    :param role_id:
    :param name:
    :param description:
    :param users:
    :return:
    """
    role = get(role_id)
    role.name = name
    role.description = description
    role.users = users
    database.update(role)
    return role
Beispiel #45
0
def upload(**kwargs):
    """
    Allows for pre-made certificates to be imported into Lemur.
    """
    roles = create_certificate_roles(**kwargs)

    if kwargs.get('roles'):
        kwargs['roles'] += roles
    else:
        kwargs['roles'] = roles

    if kwargs.get('private_key'):
        private_key = kwargs['private_key']
        if not isinstance(private_key, bytes):
            kwargs['private_key'] = private_key.encode('utf-8')

    cert = Certificate(**kwargs)

    cert = database.create(cert)

    kwargs['creator'].certificates.append(cert)

    cert = database.update(cert)
    certificate_imported.send(certificate=cert, authority=cert.authority)
    return cert
Beispiel #46
0
def update(cert_id, owner, description, active, destinations, notifications):
    """
    Updates a certificate.

    :param cert_id:
    :param owner:
    :param active:
    :return:
    """
    from lemur.notifications import service as notification_service

    cert = get(cert_id)
    cert.active = active
    cert.description = description

    # we might have to create new notifications if the owner changes
    new_notifications = []
    # get existing names to remove
    notification_name = "DEFAULT_{0}".format(cert.owner.split("@")[0].upper())
    for n in notifications:
        if notification_name not in n.label:
            new_notifications.append(n)

    notification_name = "DEFAULT_{0}".format(owner.split("@")[0].upper())
    new_notifications += notification_service.create_default_expiration_notifications(notification_name, owner)

    cert.notifications = new_notifications

    database.update_list(cert, "destinations", Destination, destinations)

    cert.owner = owner

    return database.update(cert)
Beispiel #47
0
def sync(labels=None, type=None):
    for source in database.get_all(Source, True, field='active'):
        # we should be able to specify, individual sources to sync
        if labels:
            if source.label not in labels:
                continue

        if type == 'endpoints':
            sync_endpoints(source)
        elif type == 'certificates':
            sync_certificates(source)
        else:
            sync_certificates(source)
            sync_endpoints(source)

        source.last_run = datetime.datetime.utcnow()
        database.update(source)
Beispiel #48
0
def update(pending_cert_id, **kwargs):
    """
    Updates a pending certificate.  The allowed fields are validated by
    PendingCertificateEditInputSchema.
    """
    pending_cert = get(pending_cert_id)
    for key, value in kwargs.items():
        setattr(pending_cert, key, value)
    return database.update(pending_cert)
Beispiel #49
0
def upload(**kwargs):
    """
    Allows for pre-made certificates to be imported into Lemur.
    """
    roles = create_certificate_roles(**kwargs)

    if kwargs.get('roles'):
        kwargs['roles'] += roles
    else:
        kwargs['roles'] = roles

    cert = Certificate(**kwargs)

    cert = database.create(cert)
    g.user.certificates.append(cert)

    database.update(cert)
    return cert
Beispiel #50
0
def check_revoked():
    """
    Function attempts to update Lemur's internal cache with revoked
    certificates. This is called periodically by Lemur. It checks both
    CRLs and OCSP to see if a certificate is revoked. If Lemur is unable
    encounters an issue with verification it marks the certificate status
    as `unknown`.
    """
    for cert in cert_service.get_all_certs():
        try:
            if cert.chain:
                status = verify_string(cert.body, cert.chain)
            else:
                status = verify_string(cert.body, "")

            cert.status = 'valid' if status else 'invalid'
        except Exception as e:
            cert.status = 'unknown'
        database.update(cert)
Beispiel #51
0
def update(cert_id, **kwargs):
    """
    Updates a certificate
    :param cert_id:
    :return:
    """
    cert = get(cert_id)

    for key, value in kwargs.items():
        setattr(cert, key, value)

    return database.update(cert)
Beispiel #52
0
def create_certificate(pending_certificate, certificate, user):
    """
    Create and store a certificate with pending certificate's info
    Args:
        pending_certificate: PendingCertificate which will populate the certificate
        certificate: dict from Authority, which contains the body, chain and external id
        user: User that called this function, used as 'creator' of the certificate if it does
              not have an owner
    """
    certificate['owner'] = pending_certificate.owner
    data, errors = CertificateUploadInputSchema().load(certificate)
    if errors:
        raise Exception("Unable to create certificate: {reasons}".format(reasons=errors))

    data.update(vars(pending_certificate))
    # Copy relationships, vars doesn't copy this without explicit fields
    data['notifications'] = list(pending_certificate.notifications)
    data['destinations'] = list(pending_certificate.destinations)
    data['sources'] = list(pending_certificate.sources)
    data['roles'] = list(pending_certificate.roles)
    data['replaces'] = list(pending_certificate.replaces)
    data['rotation_policy'] = pending_certificate.rotation_policy

    # Replace external id and chain with the one fetched from source
    data['external_id'] = certificate['external_id']
    data['chain'] = certificate['chain']
    creator = user_service.get_by_email(pending_certificate.owner)
    if not creator:
        # Owner of the pending certificate is not the creator, so use the current user who called
        # this as the creator (usually lemur)
        creator = user

    if pending_certificate.rename:
        # If generating name from certificate, remove the one from pending certificate
        del data['name']
    data['creator'] = creator

    cert = certificate_service.import_certificate(**data)
    database.update(cert)
    return cert
Beispiel #53
0
def mint(issuer_options):
    """
    Minting is slightly different for each authority.
    Support for multiple authorities is handled by individual plugins.

    :param issuer_options:
    """
    authority = issuer_options["authority"]

    issuer = plugins.get(authority.plugin_name)

    csr, private_key = create_csr(issuer_options)

    issuer_options["creator"] = g.user.email
    cert_body, cert_chain = issuer.create_certificate(csr, issuer_options)

    cert = Certificate(cert_body, private_key, cert_chain)

    cert.user = g.user
    cert.authority = authority
    database.update(cert)
    return cert, private_key, cert_chain
Beispiel #54
0
def update(policy_id, **kwargs):
    """
    Updates a policy.
    :param policy_id:
    :param kwargs:
    :return:
    """
    policy = get(policy_id)

    for key, value in kwargs.items():
        setattr(policy, key, value)

    return database.update(policy)
Beispiel #55
0
def upload(**kwargs):
    """
    Allows for pre-made certificates to be imported into Lemur.
    """
    from lemur.notifications import service as notification_service
    cert = Certificate(
        kwargs.get('public_cert'),
        kwargs.get('private_key'),
        kwargs.get('intermediate_cert'),
    )

    # we override the generated name if one is provided
    if kwargs.get('name'):
        cert.name = kwargs['name']

    cert.description = kwargs.get('description')

    cert.owner = kwargs['owner']
    cert = database.create(cert)

    g.user.certificates.append(cert)

    database.update_list(cert, 'destinations', Destination, kwargs['destinations'])
    database.update_list(cert, 'notifications', Notification, kwargs['notifications'])
    database.update_list(cert, 'replaces', Certificate, kwargs['replacements'])

    # create default notifications for this certificate if none are provided
    notifications = []
    if not kwargs.get('notifications'):
        notification_name = "DEFAULT_{0}".format(cert.owner.split('@')[0].upper())
        notifications += notification_service.create_default_expiration_notifications(notification_name, [cert.owner])

    notification_name = 'DEFAULT_SECURITY'
    notifications += notification_service.create_default_expiration_notifications(notification_name, current_app.config.get('LEMUR_SECURITY_TEAM_EMAIL'))
    cert.notifications = notifications

    database.update(cert)
    return cert
Beispiel #56
0
def create(**kwargs):
    """
    Creates a new certificate.
    """
    from lemur.notifications import service as notification_service
    cert, private_key, cert_chain = mint(kwargs)

    cert.owner = kwargs['owner']

    # we override the generated name if one is provided
    if kwargs.get('name'):
        cert.name = kwargs['name']

    database.create(cert)
    cert.description = kwargs.get('description')
    g.user.certificates.append(cert)
    database.update(g.user)

    # do this after the certificate has already been created because if it fails to upload to the third party
    # we do not want to lose the certificate information.
    database.update_list(cert, 'destinations', Destination, kwargs['destinations'])
    database.update_list(cert, 'replaces', Certificate, kwargs['replacements'])
    database.update_list(cert, 'notifications', Notification, kwargs['notifications'])

    # create default notifications for this certificate if none are provided
    notifications = cert.notifications
    if not kwargs.get('notifications'):
        notification_name = "DEFAULT_{0}".format(cert.owner.split('@')[0].upper())
        notifications += notification_service.create_default_expiration_notifications(notification_name, [cert.owner])

    notification_name = 'DEFAULT_SECURITY'
    notifications += notification_service.create_default_expiration_notifications(notification_name,
                                                                                  current_app.config.get('LEMUR_SECURITY_TEAM_EMAIL'))
    cert.notifications = notifications

    database.update(cert)
    metrics.send('certificate_issued', 'counter', 1, metric_tags=dict(owner=cert.owner, issuer=cert.issuer))
    return cert
Beispiel #57
0
def upload(**kwargs):
    """
    Allows for pre-made certificates to be imported into Lemur.
    """
    from lemur.notifications import service as notification_service

    cert = Certificate(kwargs.get("public_cert"), kwargs.get("private_key"), kwargs.get("intermediate_cert"))

    # we override the generated name if one is provided
    if kwargs.get("name"):
        cert.name = kwargs["name"]

    cert.description = kwargs.get("description")

    cert.owner = kwargs["owner"]
    cert = database.create(cert)

    g.user.certificates.append(cert)

    database.update_list(cert, "destinations", Destination, kwargs.get("destinations"))

    database.update_list(cert, "notifications", Notification, kwargs.get("notifications"))

    # create default notifications for this certificate if none are provided
    notifications = []
    if not kwargs.get("notifications"):
        notification_name = "DEFAULT_{0}".format(cert.owner.split("@")[0].upper())
        notifications += notification_service.create_default_expiration_notifications(notification_name, [cert.owner])

    notification_name = "DEFAULT_SECURITY"
    notifications += notification_service.create_default_expiration_notifications(
        notification_name, current_app.config.get("LEMUR_SECURITY_TEAM_EMAIL")
    )
    cert.notifications = notifications

    database.update(cert)
    return cert
Beispiel #58
0
def update(source_id, label, options, description):
    """
    Updates an existing source.

    :param source_id:  Lemur assigned ID
    :param label: Source common name
    :rtype : Source
    :return:
    """
    source = get(source_id)

    source.label = label
    source.options = options
    source.description = description

    return database.update(source)