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
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)
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
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'
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 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))
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
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
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))
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
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)
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
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
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 ) )
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 ) )
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