Show and send error for pending certs
This commit is contained in:
parent
4fa8f9ecc0
commit
2a6dda07eb
|
@ -24,6 +24,7 @@ from lemur.common.utils import windowed_query
|
||||||
|
|
||||||
from lemur.certificates.schemas import certificate_notification_output_schema
|
from lemur.certificates.schemas import certificate_notification_output_schema
|
||||||
from lemur.certificates.models import Certificate
|
from lemur.certificates.models import Certificate
|
||||||
|
from lemur.pending_certificates.schemas import pending_certificate_output_schema
|
||||||
|
|
||||||
from lemur.plugins import plugins
|
from lemur.plugins import plugins
|
||||||
from lemur.plugins.utils import get_plugin_option
|
from lemur.plugins.utils import get_plugin_option
|
||||||
|
@ -172,6 +173,44 @@ def send_rotation_notification(certificate, notification_plugin=None):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
def send_pending_failure_notification(pending_cert, notify_owner=True, notify_security=True, notification_plugin=None):
|
||||||
|
"""
|
||||||
|
Sends a report to certificate owners when their pending certificate failed to be created.
|
||||||
|
|
||||||
|
:param pending_cert:
|
||||||
|
:param notification_plugin:
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
status = FAILURE_METRIC_STATUS
|
||||||
|
|
||||||
|
if not notification_plugin:
|
||||||
|
notification_plugin = plugins.get(
|
||||||
|
current_app.config.get('LEMUR_DEFAULT_NOTIFICATION_PLUGIN', 'email-notification')
|
||||||
|
)
|
||||||
|
|
||||||
|
data = pending_certificate_output_schema.dump(pending_cert).data
|
||||||
|
data["security_email"] = current_app.config.get('LEMUR_SECURITY_TEAM_EMAIL')
|
||||||
|
|
||||||
|
if notify_owner:
|
||||||
|
try:
|
||||||
|
notification_plugin.send('failed', data, [data['owner']], pending_cert)
|
||||||
|
status = SUCCESS_METRIC_STATUS
|
||||||
|
except Exception as e:
|
||||||
|
sentry.captureException()
|
||||||
|
|
||||||
|
if notify_security:
|
||||||
|
try:
|
||||||
|
notification_plugin.send('failed', data, data["security_email"], pending_cert)
|
||||||
|
status = SUCCESS_METRIC_STATUS
|
||||||
|
except Exception as e:
|
||||||
|
sentry.captureException()
|
||||||
|
|
||||||
|
metrics.send('notification', 'counter', 1, metric_tags={'status': status, 'event_type': 'rotation'})
|
||||||
|
|
||||||
|
if status == SUCCESS_METRIC_STATUS:
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
def needs_notification(certificate):
|
def needs_notification(certificate):
|
||||||
"""
|
"""
|
||||||
Determine if notifications for a given certificate should
|
Determine if notifications for a given certificate should
|
||||||
|
|
|
@ -4,9 +4,15 @@
|
||||||
.. moduleauthor:: James Chuong <jchuong@instartlogic.com>
|
.. moduleauthor:: James Chuong <jchuong@instartlogic.com>
|
||||||
.. moduleauthor:: Curtis Castrapel <ccastrapel@netflix.com>
|
.. moduleauthor:: Curtis Castrapel <ccastrapel@netflix.com>
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
import copy
|
||||||
|
import sys
|
||||||
|
|
||||||
|
from flask import current_app
|
||||||
from flask_script import Manager
|
from flask_script import Manager
|
||||||
|
|
||||||
from lemur.authorities.service import get as get_authority
|
from lemur.authorities.service import get as get_authority
|
||||||
|
from lemur.notifications.messaging import send_pending_failure_notification
|
||||||
from lemur.pending_certificates import service as pending_certificate_service
|
from lemur.pending_certificates import service as pending_certificate_service
|
||||||
from lemur.plugins.base import plugins
|
from lemur.plugins.base import plugins
|
||||||
from lemur.users import service as user_service
|
from lemur.users import service as user_service
|
||||||
|
@ -56,6 +62,10 @@ def fetch_all_acme():
|
||||||
for acme-issued certificates because it will configure all of the DNS challenges prior to resolving any
|
for acme-issued certificates because it will configure all of the DNS challenges prior to resolving any
|
||||||
certificates.
|
certificates.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
log_data = {
|
||||||
|
"function": "{}.{}".format(__name__, sys._getframe().f_code.co_name)
|
||||||
|
}
|
||||||
pending_certs = pending_certificate_service.get_pending_certs('all')
|
pending_certs = pending_certificate_service.get_pending_certs('all')
|
||||||
user = user_service.get_by_username('lemur')
|
user = user_service.get_by_username('lemur')
|
||||||
new = 0
|
new = 0
|
||||||
|
@ -88,7 +98,26 @@ def fetch_all_acme():
|
||||||
new += 1
|
new += 1
|
||||||
else:
|
else:
|
||||||
pending_certificate_service.increment_attempt(pending_cert)
|
pending_certificate_service.increment_attempt(pending_cert)
|
||||||
|
pending_certificate_service.update(
|
||||||
|
cert.get("pending_cert").id,
|
||||||
|
status=str(cert.get("last_error"))[0:128]
|
||||||
|
)
|
||||||
failed += 1
|
failed += 1
|
||||||
|
if pending_cert.number_attempts > 0:
|
||||||
|
error_log = copy.deepcopy(log_data)
|
||||||
|
error_log["message"] = "Deleting pending certificate"
|
||||||
|
error_log["pending_cert_id"] = pending_cert.id
|
||||||
|
error_log["last_error"] = cert.get("last_error")
|
||||||
|
error_log["cn"] = pending_cert.cn
|
||||||
|
current_app.logger.error(error_log)
|
||||||
|
if 1 == 0:
|
||||||
|
send_pending_failure_notification(pending_cert, notify_owner=pending_cert.notify)
|
||||||
|
pending_certificate_service.delete_by_id(pending_cert.id)
|
||||||
|
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(
|
print(
|
||||||
"[+] Certificates: New: {new} Failed: {failed} Not using ACME: {wrong_issuer}".format(
|
"[+] Certificates: New: {new} Failed: {failed} Not using ACME: {wrong_issuer}".format(
|
||||||
new=new,
|
new=new,
|
||||||
|
|
|
@ -300,11 +300,12 @@ class ACMEIssuerPlugin(IssuerPlugin):
|
||||||
"order": order,
|
"order": order,
|
||||||
"dns_provider_options": dns_provider_options,
|
"dns_provider_options": dns_provider_options,
|
||||||
})
|
})
|
||||||
except (ClientError, ValueError, Exception):
|
except (ClientError, ValueError, Exception) as e:
|
||||||
current_app.logger.error("Unable to resolve pending cert: {}".format(pending_cert), exc_info=True)
|
current_app.logger.error("Unable to resolve pending cert: {}".format(pending_cert), exc_info=True)
|
||||||
certs.append({
|
certs.append({
|
||||||
"cert": False,
|
"cert": False,
|
||||||
"pending_cert": pending_cert,
|
"pending_cert": pending_cert,
|
||||||
|
"last_error": e,
|
||||||
})
|
})
|
||||||
|
|
||||||
for entry in pending:
|
for entry in pending:
|
||||||
|
|
|
@ -0,0 +1,161 @@
|
||||||
|
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
|
||||||
|
"http://www.w3.org/TR/html4/loose.dtd">
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||||
|
<meta name="viewport" content="initial-scale=1.0"> <!-- So that mobile webkit will display zoomed in -->
|
||||||
|
<meta name="format-detection" content="telephone=no"> <!-- disable auto telephone linking in iOS -->
|
||||||
|
|
||||||
|
<title>Lemur</title>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<div style="margin:0;padding:0" bgcolor="#FFFFFF">
|
||||||
|
<table width="100%" height="100%" style="min-width:348px" border="0" cellspacing="0" cellpadding="0">
|
||||||
|
<tbody>
|
||||||
|
<tr height="32px"></tr>
|
||||||
|
<tr align="center">
|
||||||
|
<td width="32px"></td>
|
||||||
|
<td>
|
||||||
|
<table border="0" cellspacing="0" cellpadding="0" style="max-width:600px">
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<table width="100%" border="0" cellspacing="0" cellpadding="0">
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td align="left" style="font-family:Roboto-Regular,Helvetica,Arial,sans-serif;font-size:35px;color:#727272; line-height:1.5">
|
||||||
|
Lemur
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr height="16"></tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<table bgcolor="#F44336" width="100%" border="0" cellspacing="0" cellpadding="0"
|
||||||
|
style="min-width:332px;max-width:600px;border:1px solid #e0e0e0;border-bottom:0;border-top-left-radius:3px;border-top-right-radius:3px">
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td height="72px" colspan="3"></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td width="32px"></td>
|
||||||
|
<td style="font-family:Roboto-Regular,Helvetica,Arial,sans-serif;font-size:24px;color:#ffffff;line-height:1.25">
|
||||||
|
Your certificate request has failed!
|
||||||
|
</td>
|
||||||
|
<td width="32px"></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td height="18px" colspan="3"></td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<table width="100%" border="0" cellspacing="0" cellpadding="0"
|
||||||
|
style="min-width:332px;max-width:600px;border:1px solid #f0f0f0;border-bottom:1px solid #c0c0c0;border-top:0;border-bottom-left-radius:3px;border-bottom-right-radius:3px">
|
||||||
|
<tbody>
|
||||||
|
<tr height="16px">
|
||||||
|
<td width="32px" rowspan="3"></td>
|
||||||
|
<td></td>
|
||||||
|
<td width="32px" rowspan="3"></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<table style="min-width:300px" border="0" cellspacing="0" cellpadding="0">
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td style="font-family:Roboto-Regular,Helvetica,Arial,sans-serif;font-size:13px;color:#202020;line-height:1.5">
|
||||||
|
Hi,
|
||||||
|
<br>This is a Lemur certificate failure notice. We were unable to create or rotate your certificate. Please retry your request. The reason for the failure is listed below.
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td style="font-family:Roboto-Regular,Helvetica,Arial,sans-serif;font-size:13px;color:#202020;line-height:1.5">
|
||||||
|
<table border="0" cellspacing="0" cellpadding="0"
|
||||||
|
style="margin-top:48px;margin-bottom:48px">
|
||||||
|
<tbody>
|
||||||
|
<tr valign="middle">
|
||||||
|
<td width="32px"></td>
|
||||||
|
<td width="16px"></td>
|
||||||
|
<td style="line-height:1.2">
|
||||||
|
<span style="font-family:Roboto-Regular,Helvetica,Arial,sans-serif;font-size:20px;color:#202020">{{ message.certificates.name }}</span>
|
||||||
|
<br>
|
||||||
|
<span style="font-family:Roboto-Regular,Helvetica,Arial,sans-serif;font-size:13px;color:#727272">
|
||||||
|
<br>{{ message.certificates.owner }}
|
||||||
|
<br>{{ message.certificates.status }}
|
||||||
|
</span>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td style="font-family:Roboto-Regular,Helvetica,Arial,sans-serif;font-size:13px;color:#202020;line-height:1.5">
|
||||||
|
If you are having any trouble, please reach out to {{ ", ".join(message.certificates.security_email) }}.</span>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td style="font-family:Roboto-Regular,Helvetica,Arial,sans-serif;font-size:13px;color:#202020;line-height:1.5">
|
||||||
|
<br>Best,<br><span class="il">Lemur</span>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr height="16px"></tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<table style="font-family:Roboto-Regular,Helvetica,Arial,sans-serif;font-size:12px;color:#b9b9b9;line-height:1.5">
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td>*All times are in UTC<br></td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr height="32px"></tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr height="16"></tr>
|
||||||
|
<tr>
|
||||||
|
<td style="max-width:600px;font-family:Roboto-Regular,Helvetica,Arial,sans-serif;font-size:10px;color:#bcbcbc;line-height:1.5"></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<table style="font-family:Roboto-Regular,Helvetica,Arial,sans-serif;font-size:10px;color:#666666;line-height:18px;padding-bottom:10px">
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td>You received this mandatory email announcement to update you about
|
||||||
|
important changes to your <span class="il">TLS certificate</span>.
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<div style="direction:ltr;text-align:left">© 2016 <span class="il">Lemur</span></div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</td>
|
||||||
|
<td width="32px"></td>
|
||||||
|
</tr>
|
||||||
|
<tr height="32px"></tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
|
@ -80,6 +80,12 @@
|
||||||
{{ pendingCertificate.numberAttempts }}
|
{{ pendingCertificate.numberAttempts }}
|
||||||
</span>
|
</span>
|
||||||
</li>
|
</li>
|
||||||
|
<li class="list-group-item">
|
||||||
|
<strong>Latest Status</strong>
|
||||||
|
<span class="pull-right">
|
||||||
|
{{ pendingCertificate.status }}
|
||||||
|
</span>
|
||||||
|
</li>
|
||||||
<li class="list-group-item">
|
<li class="list-group-item">
|
||||||
<strong>Date Created</strong>
|
<strong>Date Created</strong>
|
||||||
<span class="pull-right">
|
<span class="pull-right">
|
||||||
|
|
Loading…
Reference in New Issue