示例#1
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
示例#2
0
def test_pending_upload(pending_certificate_from_full_chain_ca):
    from lemur.pending_certificates.service import upload
    from lemur.certificates.service import get

    cert = {"body": WILDCARD_CERT_STR, "chain": None, "external_id": None}

    pending_cert = upload(pending_certificate_from_full_chain_ca.id, **cert)
    assert pending_cert.resolved
    assert get(pending_cert.resolved_cert_id)
def test_pending_upload_with_chain(pending_certificate_from_partial_chain_ca):
    from lemur.pending_certificates.service import upload
    from lemur.certificates.service import get

    cert = {'body': WILDCARD_CERT_STR,
            'chain': INTERMEDIATE_CERT_STR,
            'external_id': None
    }

    pending_cert = upload(pending_certificate_from_partial_chain_ca.id, **cert)
    assert pending_cert.resolved
    assert get(pending_cert.resolved_cert_id)
示例#4
0
文件: views.py 项目: Netflix/lemur
    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
示例#5
0
    def get(self, pending_certificate_id):
        """
        .. http:get:: /pending_certificates/1/key

           Retrieves the private key for a given pneding certificate

           **Example request**:

           .. sourcecode:: http

              GET /pending_certificates/1/key HTTP/1.1
              Host: example.com
              Accept: application/json, text/javascript

           **Example response**:

           .. sourcecode:: http

              HTTP/1.1 200 OK
              Vary: Accept
              Content-Type: text/javascript

              {
                 "key": "-----BEGIN ..."
              }

           :reqheader Authorization: OAuth token to authenticate
           :statuscode 200: no error
           :statuscode 403: unauthenticated
        """
        cert = service.get(pending_certificate_id)
        if not cert:
            return dict(
                message="Cannot find specified pending certificate"), 404

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

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

        response = make_response(jsonify(key=cert.private_key), 200)
        response.headers[
            'cache-control'] = 'private, max-age=0, no-cache, no-store'
        response.headers['pragma'] = 'no-cache'
        return response
def test_create_pending(pending_certificate, user, session):
    import copy
    from lemur.pending_certificates.service import create_certificate, get
    cert = {'body': WILDCARD_CERT_STR,
            'chain': INTERMEDIATE_CERT_STR,
            'external_id': '54321'}

    # Weird copy because the session behavior.  pending_certificate is a valid object but the
    # return of vars(pending_certificate) is a sessionobject, and so nothing from the pending_cert
    # is used to create the certificate.  Maybe a bug due to using vars(), and should copy every
    # field explicitly.
    pending_certificate = copy.copy(get(pending_certificate.id))
    real_cert = create_certificate(pending_certificate, cert, user['user'])
    assert real_cert.owner == pending_certificate.owner
    assert real_cert.notify == pending_certificate.notify
    assert real_cert.private_key == pending_certificate.private_key
    assert real_cert.external_id == '54321'
示例#7
0
文件: views.py 项目: Netflix/lemur
    def get(self, pending_certificate_id):
        """
        .. http:get:: /pending_certificates/1/key

           Retrieves the private key for a given pneding certificate

           **Example request**:

           .. sourcecode:: http

              GET /pending_certificates/1/key HTTP/1.1
              Host: example.com
              Accept: application/json, text/javascript

           **Example response**:

           .. sourcecode:: http

              HTTP/1.1 200 OK
              Vary: Accept
              Content-Type: text/javascript

              {
                 "key": "-----BEGIN ..."
              }

           :reqheader Authorization: OAuth token to authenticate
           :statuscode 200: no error
           :statuscode 403: unauthenticated
        """
        cert = service.get(pending_certificate_id)
        if not cert:
            return dict(message="Cannot find specified pending certificate"), 404

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

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

        response = make_response(jsonify(key=cert.private_key), 200)
        response.headers['cache-control'] = 'private, max-age=0, no-cache, no-store'
        response.headers['pragma'] = 'no-cache'
        return response
示例#8
0
def test_create_pending(pending_certificate, user, session):
    import copy
    from lemur.pending_certificates.service import create_certificate, get
    cert = {'body': WILDCARD_CERT_STR,
            'chain': INTERMEDIATE_CERT_STR,
            'external_id': '54321'}

    # Weird copy because the session behavior.  pending_certificate is a valid object but the
    # return of vars(pending_certificate) is a sessionobject, and so nothing from the pending_cert
    # is used to create the certificate.  Maybe a bug due to using vars(), and should copy every
    # field explicitly.
    pending_certificate = copy.copy(get(pending_certificate.id))
    real_cert = create_certificate(pending_certificate, cert, user['user'])
    assert real_cert.owner == pending_certificate.owner
    assert real_cert.notify == pending_certificate.notify
    assert real_cert.private_key == pending_certificate.private_key
    assert real_cert.external_id == '54321'
示例#9
0
文件: cli.py 项目: tchen0123/lemur
def fetch_all_acme():
    """
    Attempt to get full certificates for each pending certificate listed with the acme-issuer. This is more efficient
    for acme-issued certificates because it will configure all of the DNS challenges prior to resolving any
    certificates.
    """
    pending_certs = pending_certificate_service.get_pending_certs('all')
    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:
            pending_certificate_service.increment_attempt(pending_cert)
            failed += 1
    print(
        "[+] Certificates: New: {new} Failed: {failed} Not using ACME: {wrong_issuer}"
        .format(new=new, failed=failed, wrong_issuer=wrong_issuer))
示例#10
0
def test_create_pending_already_resolved(pending_certificate, user, session):
    import copy
    from lemur.pending_certificates.service import create_certificate, get, update

    cert = {
        "body": WILDCARD_CERT_STR,
        "chain": INTERMEDIATE_CERT_STR,
        "external_id": "54321",
    }

    pending_certificate = copy.copy(get(pending_certificate.id))
    first_cert = create_certificate(pending_certificate, cert, user["user"])

    # mark resolved on pending_certificate
    update(pending_certificate.id, resolved_cert_id=first_cert.id)
    update(pending_certificate.id, resolved=True)
    second_cert = create_certificate(pending_certificate, cert, user["user"])

    assert first_cert.id == second_cert.id
示例#11
0
def test_create_pending(pending_certificate, user, session):
    import copy
    from lemur.pending_certificates.service import create_certificate, get

    cert = {
        "body": WILDCARD_CERT_STR,
        "chain": INTERMEDIATE_CERT_STR,
        "external_id": "54321",
    }

    # Weird copy because the session behavior.  pending_certificate is a valid object but the
    # return of vars(pending_certificate) is a sessionobject, and so nothing from the pending_cert
    # is used to create the certificate.  Maybe a bug due to using vars(), and should copy every
    # field explicitly.
    pending_certificate = copy.copy(get(pending_certificate.id))
    real_cert = create_certificate(pending_certificate, cert, user["user"])
    assert real_cert.owner == pending_certificate.owner
    assert real_cert.notify == pending_certificate.notify
    assert real_cert.private_key == pending_certificate.private_key
    assert real_cert.external_id == "54321"
    assert real_cert.key_type == "RSA2048"
    assert real_cert.authority_id == pending_certificate.authority_id
示例#12
0
文件: celery.py 项目: pks-os/lemur
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))
示例#13
0
    def put(self, pending_certificate_id, data=None):
        """
        .. http:put:: /pending_certificates/1

           Update a pending certificate

           **Example request**:

           .. sourcecode:: http

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

              {
                 "owner": "*****@*****.**",
                 "active": false
                 "notifications": [],
                 "destinations": [],
                 "replacements": []
              }

           **Example response**:

           .. sourcecode:: http

              HTTP/1.1 200 OK
              Vary: Accept
              Content-Type: text/javascript

              {
                "status": null,
                "cn": "*.test.example.net",
                "chain": "",
                "authority": {
                    "active": true,
                    "owner": "*****@*****.**",
                    "id": 1,
                    "description": "verisign test authority",
                    "name": "verisign"
                },
                "owner": "*****@*****.**",
                "serial": "82311058732025924142789179368889309156",
                "id": 2288,
                "issuer": "SymantecCorporation",
                "destinations": [],
                "description": null,
                "deleted": null,
                "notifications": [{
                    "id": 1
                }]
                "user": {
                    "username": "******",
                    "active": true,
                    "email": "*****@*****.**",
                    "id": 2
                },
                "active": true,
                "number_attempts": 1,
                "csr": "-----BEGIN CERTIFICATE REQUEST-----...",
                "external_id": 12345,
                "domains": [{
                    "sensitive": false,
                    "id": 1090,
                    "name": "*.test.example.net"
                }],
                "replaces": [],
                "name": "WILDCARD.test.example.net-SymantecCorporation-20160603-20180112",
                "roles": [{
                    "id": 464,
                    "description": "This is a google group based role created by Lemur",
                    "name": "*****@*****.**"
                }],
                "rotation": true,
                "rotationPolicy": {"name": "default"},
              }

           :reqheader Authorization: OAuth token to authenticate
           :statuscode 200: no error
           :statuscode 403: unauthenticated

        """
        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

        for destination in data['destinations']:
            if destination.plugin.requires_key:
                if not pending_cert.private_key:
                    return dict(
                        message=
                        'Unable to add destination: {0}. Certificate does not have required private key.'
                        .format(destination.label)), 400

        pending_cert = service.update(pending_certificate_id, **data)
        return pending_cert
示例#14
0
    def get(self, pending_certificate_id):
        """
        .. http:get:: /pending_certificates/1

           One pending certificate

           **Example request**:

           .. sourcecode:: http

              GET /pending_certificates/1 HTTP/1.1
              Host: example.com
              Accept: application/json, text/javascript

           **Example response**:

           .. sourcecode:: http

              HTTP/1.1 200 OK
              Vary: Accept
              Content-Type: text/javascript

              {
                "status": null,
                "cn": "*.test.example.net",
                "chain": "",
                "authority": {
                    "active": true,
                    "owner": "*****@*****.**",
                    "id": 1,
                    "description": "verisign test authority",
                    "name": "verisign"
                },
                "owner": "*****@*****.**",
                "serial": "82311058732025924142789179368889309156",
                "id": 1,
                "issuer": "SymantecCorporation",
                "notBefore": "2016-06-03T00:00:00+00:00",
                "notAfter": "2018-01-12T23:59:59+00:00",
                "destinations": [],
                "description": null,
                "deleted": null,
                "notifications": [{
                    "id": 1
                }],
                "signingAlgorithm": "sha256",
                "user": {
                    "username": "******",
                    "active": true,
                    "email": "*****@*****.**",
                    "id": 2
                },
                "active": true,
                "domains": [{
                    "sensitive": false,
                    "id": 1090,
                    "name": "*.test.example.net"
                }],
                "rotation": true,
                "rotationPolicy": {"name": "default"},
                "replaces": [],
                "replaced": [],
                "name": "WILDCARD.test.example.net-SymantecCorporation-20160603-20180112",
                "roles": [{
                    "id": 464,
                    "description": "This is a google group based role created by Lemur",
                    "name": "*****@*****.**"
                }],
                "san": null
              }

           :reqheader Authorization: OAuth token to authenticate
           :statuscode 200: no error
           :statuscode 403: unauthenticated

        """
        return service.get(pending_certificate_id)
示例#15
0
def fetch_acme_cert(id):
    """
    Attempt to get the full certificate for the pending certificate listed.

    Args:
        id: an id of a PendingCertificate
    """
    task_id = None
    if celery.current_task:
        task_id = celery.current_task.request.id

    function = f"{__name__}.{sys._getframe().f_code.co_name}"
    log_data = {
        "function": function,
        "message": "Resolving pending certificate {}".format(id),
        "task_id": task_id,
        "id": id,
    }

    current_app.logger.debug(log_data)

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

    pending_certs = pending_certificate_service.get_pending_certs([id])
    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 not pending_cert or pending_cert.resolved:
            # pending_cert is cleared or it was resolved by another process
            log_data[
                "message"] = "Pending certificate doesn't exist anymore. Was it resolved by another process?"
            current_app.logger.error(log_data)
            continue
        if real_cert:
            # If a real certificate was returned from issuer, then create it in Lemur and mark
            # the pending certificate as resolved
            final_cert = pending_certificate_service.create_certificate(
                pending_cert, real_cert, pending_cert.user)
            pending_certificate_service.update(cert.get("pending_cert").id,
                                               resolved_cert_id=final_cert.id)
            pending_certificate_service.update(cert.get("pending_cert").id,
                                               resolved=True)
            # 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 > ACME_ADDITIONAL_ATTEMPTS:
                error_log["message"] = "Deleting pending certificate"
                send_pending_failure_notification(
                    pending_cert, notify_owner=pending_cert.notify)
                # Mark the pending cert as resolved
                pending_certificate_service.update(cert.get("pending_cert").id,
                                                   resolved=True)
            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)
    metrics.send(f"{function}.resolved", "gauge", new)
    metrics.send(f"{function}.failed", "gauge", failed)
    metrics.send(f"{function}.wrong_issuer", "gauge", wrong_issuer)
    print(
        "[+] Certificates: New: {new} Failed: {failed} Not using ACME: {wrong_issuer}"
        .format(new=new, failed=failed, wrong_issuer=wrong_issuer))
    return log_data
示例#16
0
def fetch_cert(id):
    """
    Attempt to get the full certificate for the pending certificate listed.

    Args:
        id: an id of a PendingCertificate
    """
    task_id = None
    if celery.current_task:
        task_id = celery.current_task.request.id

    function = f"{__name__}.{sys._getframe().f_code.co_name}"
    log_data = {
        "function": function,
        "message": "Resolving pending certificate {}".format(id),
        "task_id": task_id,
        "id": id,
    }

    current_app.logger.debug(log_data)

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

    pending_certs = pending_certificate_service.get_pending_certs([id])
    new = 0
    failed = 0
    for cert in pending_certs:
        cert_authority = get_authority(cert.authority_id)
        if cert_authority.plugin_name == "acme-issuer":
            current_app.logger.warning(
                "Skipping acme cert (use `fetch_acme_cert()` instead).")
            continue
        plugin = plugins.get(cert_authority.plugin_name)
        real_cert = plugin.get_ordered_certificate(cert)
        if real_cert:
            # If a real certificate was returned from issuer, then create it in
            # Lemur and mark the pending certificate as resolved
            # Ideally, this should be a db transaction that would check resolved status
            # before creating a new one
            final_cert = pending_certificate_service.create_certificate(
                cert, real_cert, cert.user)
            pending_certificate_service.update(cert.id,
                                               resolved_cert_id=final_cert.id)
            pending_certificate_service.update(cert.id, resolved=True)
            # add metrics to metrics extension
            new += 1
        else:
            # Double check the pending certificate still exists in the database
            # before updating the failed attempt counter
            if not pending_certificate_service.get(cert.id):
                current_app.logger.info(
                    f"Not incrementing failed attempt counter because {cert.name} was cancelled before."
                )
            else:
                pending_certificate_service.increment_attempt(cert)
                failed += 1
    log_data["message"] = "Complete"
    log_data["new"] = new
    log_data["failed"] = failed
    current_app.logger.debug(log_data)
    metrics.send(f"{function}.resolved", "gauge", new)
    metrics.send(f"{function}.failed", "gauge", failed)
    print(f"[+] Certificates: New: {new} Failed: {failed}")
    return log_data
示例#17
0
文件: celery.py 项目: Netflix/lemur
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),
        "message": "Resolving pending certificate {}".format(id)
    }
    current_app.logger.debug(log_data)
    pending_certs = pending_certificate_service.get_pending_certs([id])
    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 not pending_cert:
            log_data["message"] = "Pending certificate doesn't exist anymore. Was it resolved by another process?"
            current_app.logger.error(log_data)
            continue
        if real_cert:
            # If a real certificate was returned from issuer, then create it in Lemur and mark
            # the pending certificate as resolved
            final_cert = pending_certificate_service.create_certificate(pending_cert, real_cert, pending_cert.user)
            pending_certificate_service.update(
                cert.get("pending_cert").id,
                resolved=True
            )
            pending_certificate_service.update(
                cert.get("pending_cert").id,
                resolved_cert_id=final_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)
                # Mark the pending cert as resolved
                pending_certificate_service.update(
                    cert.get("pending_cert").id,
                    resolved=True
                )
            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
        )
    )
示例#18
0
文件: cli.py 项目: x-lhan/lemur
def fetch_all_acme():
    """
    Attempt to get full certificates for each pending certificate listed with the acme-issuer. This is more efficient
    for acme-issued certificates because it will configure all of the DNS challenges prior to resolving any
    certificates.
    """

    log_data = {
        "function": "{}.{}".format(__name__, sys._getframe().f_code.co_name)
    }
    pending_certs = pending_certificate_service.get_unresolved_pending_certs()
    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 mark
            # the pending certificate as resolved
            final_cert = pending_certificate_service.create_certificate(pending_cert, real_cert, pending_cert.user)
            pending_certificate_service.update(
                pending_cert.id,
                resolved=True
            )
            pending_certificate_service.update(
                pending_cert.id,
                resolved_cert_id=final_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"] = "Marking pending certificate as resolved"
                send_pending_failure_notification(pending_cert, notify_owner=pending_cert.notify)
                # Mark "resolved" as True
                pending_certificate_service.update(
                    cert.id,
                    resolved=True
                )
            else:
                pending_certificate_service.increment_attempt(pending_cert)
                pending_certificate_service.update(
                    cert.get("pending_cert").id,
                    status=str(cert.get("last_error"))
                )
            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
        )
    )
示例#19
0
文件: views.py 项目: Netflix/lemur
    def put(self, pending_certificate_id, data=None):
        """
        .. http:put:: /pending_certificates/1

           Update a pending certificate

           **Example request**:

           .. sourcecode:: http

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

              {
                 "owner": "*****@*****.**",
                 "active": false
                 "notifications": [],
                 "destinations": [],
                 "replacements": []
              }

           **Example response**:

           .. sourcecode:: http

              HTTP/1.1 200 OK
              Vary: Accept
              Content-Type: text/javascript

              {
                "status": null,
                "cn": "*.test.example.net",
                "chain": "",
                "authority": {
                    "active": true,
                    "owner": "*****@*****.**",
                    "id": 1,
                    "description": "verisign test authority",
                    "name": "verisign"
                },
                "owner": "*****@*****.**",
                "serial": "82311058732025924142789179368889309156",
                "id": 2288,
                "issuer": "SymantecCorporation",
                "destinations": [],
                "description": null,
                "deleted": null,
                "notifications": [{
                    "id": 1
                }]
                "user": {
                    "username": "******",
                    "active": true,
                    "email": "*****@*****.**",
                    "id": 2
                },
                "active": true,
                "number_attempts": 1,
                "csr": "-----BEGIN CERTIFICATE REQUEST-----...",
                "external_id": 12345,
                "domains": [{
                    "sensitive": false,
                    "id": 1090,
                    "name": "*.test.example.net"
                }],
                "replaces": [],
                "name": "WILDCARD.test.example.net-SymantecCorporation-20160603-20180112",
                "roles": [{
                    "id": 464,
                    "description": "This is a google group based role created by Lemur",
                    "name": "*****@*****.**"
                }],
                "rotation": true,
                "rotationPolicy": {"name": "default"},
              }

           :reqheader Authorization: OAuth token to authenticate
           :statuscode 200: no error
           :statuscode 403: unauthenticated

        """
        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

        for destination in data['destinations']:
            if destination.plugin.requires_key:
                if not pending_cert.private_key:
                    return dict(
                        message='Unable to add destination: {0}. Certificate does not have required private key.'.format(
                            destination.label
                        )
                    ), 400

        pending_cert = service.update(pending_certificate_id, **data)
        return pending_cert
示例#20
0
文件: views.py 项目: Netflix/lemur
    def get(self, pending_certificate_id):
        """
        .. http:get:: /pending_certificates/1

           One pending certificate

           **Example request**:

           .. sourcecode:: http

              GET /pending_certificates/1 HTTP/1.1
              Host: example.com
              Accept: application/json, text/javascript

           **Example response**:

           .. sourcecode:: http

              HTTP/1.1 200 OK
              Vary: Accept
              Content-Type: text/javascript

              {
                "status": null,
                "cn": "*.test.example.net",
                "chain": "",
                "authority": {
                    "active": true,
                    "owner": "*****@*****.**",
                    "id": 1,
                    "description": "verisign test authority",
                    "name": "verisign"
                },
                "owner": "*****@*****.**",
                "serial": "82311058732025924142789179368889309156",
                "id": 1,
                "issuer": "SymantecCorporation",
                "notBefore": "2016-06-03T00:00:00+00:00",
                "notAfter": "2018-01-12T23:59:59+00:00",
                "destinations": [],
                "description": null,
                "deleted": null,
                "notifications": [{
                    "id": 1
                }],
                "signingAlgorithm": "sha256",
                "user": {
                    "username": "******",
                    "active": true,
                    "email": "*****@*****.**",
                    "id": 2
                },
                "active": true,
                "domains": [{
                    "sensitive": false,
                    "id": 1090,
                    "name": "*.test.example.net"
                }],
                "rotation": true,
                "rotationPolicy": {"name": "default"},
                "replaces": [],
                "replaced": [],
                "name": "WILDCARD.test.example.net-SymantecCorporation-20160603-20180112",
                "roles": [{
                    "id": 464,
                    "description": "This is a google group based role created by Lemur",
                    "name": "*****@*****.**"
                }],
                "san": null
              }

           :reqheader Authorization: OAuth token to authenticate
           :statuscode 200: no error
           :statuscode 403: unauthenticated

        """
        return service.get(pending_certificate_id)