Exemple #1
0
def fetch(ids):
    """
    Attempt to get full certificates for each pending certificate listed.

    Args:
        ids: a list of ids of PendingCertificates (passed in by manager options when run as CLI)
             `python manager.py pending_certs fetch -i 123 321 all`
    """
    pending_certs = pending_certificate_service.get_pending_certs(ids)
    user = user_service.get_by_username('lemur')
    new = 0
    failed = 0

    for cert in pending_certs:
        authority = plugins.get(cert.authority.plugin_name)
        real_cert = authority.get_ordered_certificate(cert)
        if real_cert:
            # If a real certificate was returned from issuer, then create it in Lemur and delete
            # the pending certificate
            pending_certificate_service.create_certificate(
                cert, real_cert, user)
            pending_certificate_service.delete(cert)
            # add metrics to metrics extension
            new += 1
        else:
            pending_certificate_service.increment_attempt(cert)
            failed += 1
    print("[+] Certificates: New: {new} Failed: {failed}".format(
        new=new,
        failed=failed,
    ))
Exemple #2
0
def remove_old_acme_certs():
    """Prune old pending acme certificates from the database"""
    function = f"{__name__}.{sys._getframe().f_code.co_name}"
    task_id = None
    if celery.current_task:
        task_id = celery.current_task.request.id

    log_data = {
        "function": function,
        "message": "Starting job.",
        "task_id": task_id,
    }

    if task_id and is_task_active(function, task_id, None):
        log_data["message"] = "Skipping task: Task is already active"
        current_app.logger.debug(log_data)
        return

    pending_certs = pending_certificate_service.get_pending_certs("all")

    # Delete pending certs more than a week old
    for cert in pending_certs:
        if datetime.now(timezone.utc) - cert.last_updated > timedelta(days=7):
            log_data["pending_cert_id"] = cert.id
            log_data["pending_cert_name"] = cert.name
            log_data["message"] = "Deleting pending certificate"
            current_app.logger.debug(log_data)
            pending_certificate_service.delete(cert)

    metrics.send(f"{function}.success", "counter", 1)
    return log_data
Exemple #3
0
    def delete(self, pending_certificate_id, data=None):
        """
        .. http:delete:: /pending_certificates/1

           Cancel and delete a pending certificate

           **Example request**:

           .. sourcecode:: http

              DELETE /pending certificates/1 HTTP/1.1
              Host: example.com
              Accept: application/json, text/javascript

              {
                 "note": "Why I am cancelling this order"
              }

           **Example response**:

           .. sourcecode:: http

              HTTP/1.1 204 No Content

           :reqheader Authorization: OAuth token to authenticate
           :statuscode 204: no error
           :statuscode 401: unauthenticated
           :statuscode 403: unauthorized
           :statuscode 404: pending certificate id not found
           :statuscode 500: internal error
        """
        pending_cert = service.get(pending_certificate_id)

        if not pending_cert:
            return dict(
                message="Cannot find specified pending certificate"), 404

        # allow creators
        if g.current_user != pending_cert.user:
            owner_role = role_service.get_by_name(pending_cert.owner)
            permission = CertificatePermission(
                owner_role, [x.name for x in pending_cert.roles])

            if not permission.can():
                return dict(
                    message='You are not authorized to update this certificate'
                ), 403

        if service.cancel(pending_cert, **data):
            service.delete(pending_cert)
            return ('', 204)
        else:
            # service.cancel raises exception if there was an issue, but this will ensure something
            # is relayed to user in case of something unexpected (unsuccessful update somehow).
            return dict(
                message=
                "Unexpected error occurred while trying to cancel this certificate"
            ), 500
Exemple #4
0
def remove_old_acme_certs():
    """Prune old pending acme certificates from the database"""
    log_data = {"function": "{}.{}".format(__name__, sys._getframe().f_code.co_name)}
    pending_certs = pending_certificate_service.get_pending_certs("all")

    # Delete pending certs more than a week old
    for cert in pending_certs:
        if datetime.now(timezone.utc) - cert.last_updated > timedelta(days=7):
            log_data["pending_cert_id"] = cert.id
            log_data["pending_cert_name"] = cert.name
            log_data["message"] = "Deleting pending certificate"
            current_app.logger.debug(log_data)
            pending_certificate_service.delete(cert)
Exemple #5
0
    def delete(self, pending_certificate_id, data=None):
        """
        .. http:delete:: /pending_certificates/1

           Cancel and delete a pending certificate

           **Example request**:

           .. sourcecode:: http

              DELETE /pending certificates/1 HTTP/1.1
              Host: example.com
              Accept: application/json, text/javascript

              {
                 "note": "Why I am cancelling this order"
              }

           **Example response**:

           .. sourcecode:: http

              HTTP/1.1 204 No Content

           :reqheader Authorization: OAuth token to authenticate
           :statuscode 204: no error
           :statuscode 401: unauthenticated
           :statuscode 403: unauthorized
           :statuscode 404: pending certificate id not found
           :statuscode 500: internal error
        """
        pending_cert = service.get(pending_certificate_id)

        if not pending_cert:
            return dict(message="Cannot find specified pending certificate"), 404

        # allow creators
        if g.current_user != pending_cert.user:
            owner_role = role_service.get_by_name(pending_cert.owner)
            permission = CertificatePermission(owner_role, [x.name for x in pending_cert.roles])

            if not permission.can():
                return dict(message='You are not authorized to update this certificate'), 403

        if service.cancel(pending_cert, **data):
            service.delete(pending_cert)
            return('', 204)
        else:
            # service.cancel raises exception if there was an issue, but this will ensure something
            # is relayed to user in case of something unexpected (unsuccessful update somehow).
            return dict(message="Unexpected error occurred while trying to cancel this certificate"), 500
Exemple #6
0
def remove_old_acme_certs():
    """Prune old pending acme certificates from the database"""
    log_data = {
        "function": "{}.{}".format(__name__, sys._getframe().f_code.co_name)
    }
    pending_certs = pending_certificate_service.get_pending_certs('all')

    # Delete pending certs more than a week old
    for cert in pending_certs:
        if datetime.now(timezone.utc) - cert.last_updated > timedelta(days=7):
            log_data['pending_cert_id'] = cert.id
            log_data['pending_cert_name'] = cert.name
            log_data['message'] = "Deleting pending certificate"
            current_app.logger.debug(log_data)
            pending_certificate_service.delete(cert.id)
Exemple #7
0
def remove_old_acme_certs():
    """Prune old pending acme certificates from the database"""
    function = f"{__name__}.{sys._getframe().f_code.co_name}"
    log_data = {
        "function": function,
        "message": "Starting job.",
    }
    pending_certs = pending_certificate_service.get_pending_certs("all")

    # Delete pending certs more than a week old
    for cert in pending_certs:
        if datetime.now(timezone.utc) - cert.last_updated > timedelta(days=7):
            log_data["pending_cert_id"] = cert.id
            log_data["pending_cert_name"] = cert.name
            log_data["message"] = "Deleting pending certificate"
            current_app.logger.debug(log_data)
            pending_certificate_service.delete(cert)

    red.set(f'{function}.last_success', int(time.time()))
    metrics.send(f"{function}.success", 'counter', 1)
Exemple #8
0
def fetch_acme_cert(id):
    """
    Attempt to get the full certificate for the pending certificate listed.

    Args:
        id: an id of a PendingCertificate
    """
    log_data = {
        "function": "{}.{}".format(__name__,
                                   sys._getframe().f_code.co_name)
    }
    pending_certs = pending_certificate_service.get_pending_certs([id])
    user = user_service.get_by_username('lemur')
    new = 0
    failed = 0
    wrong_issuer = 0
    acme_certs = []

    # We only care about certs using the acme-issuer plugin
    for cert in pending_certs:
        cert_authority = get_authority(cert.authority_id)
        if cert_authority.plugin_name == 'acme-issuer':
            acme_certs.append(cert)
        else:
            wrong_issuer += 1

    authority = plugins.get("acme-issuer")
    resolved_certs = authority.get_ordered_certificates(acme_certs)

    for cert in resolved_certs:
        real_cert = cert.get("cert")
        # It's necessary to reload the pending cert due to detached instance: http://sqlalche.me/e/bhk3
        pending_cert = pending_certificate_service.get(
            cert.get("pending_cert").id)

        if real_cert:
            # If a real certificate was returned from issuer, then create it in Lemur and delete
            # the pending certificate
            pending_certificate_service.create_certificate(
                pending_cert, real_cert, user)
            pending_certificate_service.delete_by_id(pending_cert.id)
            # add metrics to metrics extension
            new += 1
        else:
            failed += 1
            error_log = copy.deepcopy(log_data)
            error_log["message"] = "Pending certificate creation failure"
            error_log["pending_cert_id"] = pending_cert.id
            error_log["last_error"] = cert.get("last_error")
            error_log["cn"] = pending_cert.cn

            if pending_cert.number_attempts > 4:
                error_log["message"] = "Deleting pending certificate"
                send_pending_failure_notification(
                    pending_cert, notify_owner=pending_cert.notify)
                pending_certificate_service.delete(
                    pending_certificate_service.cancel(pending_cert))
            else:
                pending_certificate_service.increment_attempt(pending_cert)
                pending_certificate_service.update(cert.get("pending_cert").id,
                                                   status=str(
                                                       cert.get("last_error")))
                # Add failed pending cert task back to queue
                fetch_acme_cert.delay(id)
            current_app.logger.error(error_log)
    log_data["message"] = "Complete"
    log_data["new"] = new
    log_data["failed"] = failed
    log_data["wrong_issuer"] = wrong_issuer
    current_app.logger.debug(log_data)
    print(
        "[+] Certificates: New: {new} Failed: {failed} Not using ACME: {wrong_issuer}"
        .format(new=new, failed=failed, wrong_issuer=wrong_issuer))