摘要:我将在第一遍中尝试解释,但是如果我错过了一些细节,请告诉我,我将继续进行下去。我正在从文本文件中提取服务器列表,并使用pyopenssl来解析,连接和检索SSL证书信息。根据到期日期,我正在计算证书到期之前的天数。我的结果通过数组传递,格式化,然后通过电子邮件发送。直到我的其中一台服务器无法解析并且得到socket.gaierror,它才能正常工作。
问题:如果主机无法解决,则会炸毁我的结果,并且出现以下错误。尽管它正确记录了错误,但是我尝试传递一些可以在主机,主机名,到期日期和到期日格式中记录我的结果的异常的东西,以便我可以传递给表并发送电子邮件。我希望它在主机字段中注明“无法解决”,并且可能导致到期日期和到期天数仅为“ 0”。谁能指出我实现这一目标的好方法?谢谢!
错误消息:
Checking certificate for server server.domain.com
--- Logging error ---
Traceback (most recent call last):
File "ssl_nag_script_test.py", line 80, in <module>
s.connect((host, int(port)))
socket.gaierror: [Errno 11001] getaddrinfo failed.
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "E:\Python36\lib\logging\__init__.py", line 992, in emit
msg = self.format(record)
File "E:\Python36\lib\logging\__init__.py", line 838, in format
return fmt.format(record)
File "E:\Python36\lib\logging\__init__.py", line 575, in format
record.message = record.getMessage()
File "E:\Python36\lib\logging\__init__.py", line 338, in getMessage
msg = msg % self.args
TypeError: not all arguments converted during string formatting
Call stack:
File "ssl_nag_script_test.py", line 106, in <module>
logger.warning('Error on connection to Server,', str(ip))
Message: 'Error on connection to Server,'
Arguments: ('server.domain.com:443\n',)
--- Logging error ---
Traceback (most recent call last):
File "ssl_nag_script_test.py", line 80, in <module>
s.connect((host, int(port)))
socket.gaierror: [Errno 11001] getaddrinfo failed.
**Then**
WARNING:root:ERROR ENCOUNTERED!
WARNING:root:Traceback (most recent call last):
File "ssl_nag_script - Copy.py", line 114, in <module>
key=lambda k: k[1]['days_to_expire'], reverse=False)
TypeError: '<' not supported between instances of 'str' and 'int'
Python代码
# Import the basic modules to run this script
import ssl
from datetime import datetime
import OpenSSL
import socket
from datetime import timedelta
import datetime
import traceback
import logging
# Import the needed libs for sending smtp emails
import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.base import MIMEBase
from email import encoders
# Set variables for email
email_sen = '[email protected]'
email_rec = '[email protected]'
subject = 'SSL Certificate Results'
# Create message container for email
msg = MIMEMultipart('alternative')
msg['From'] = email_sen
msg['To'] = email_rec
msg['Subject'] = subject
# Setup logging
logger = logging.getLogger(__name__)
logger.setLevel(logging.WARNING)
formatter = logging.Formatter('%(asctime)s:%(levelname)s:%(message)s')
file_handler = logging.FileHandler('log/SSLNag.log')
file_handler.setFormatter(formatter)
logger.addHandler(file_handler)
try:
# opening file with list of servers and set date and time
ipfile = open('server_ip.txt')
cur_date = datetime.datetime.utcnow()
# Create an array to house the results.
# Array will have sub arrays in the format of [host ip] = {host, hostname, expiration date, days to expire}
ssl_results = {}
except Exception as e:
logger.warning("ERROR ENCOUNTERED! \n\n")
logger.warning(str(traceback.format_exc()))
# scan each host in the ip file and check it's ssl
for ip in ipfile:
# Record an entry in the ssl_resutls array
# Always default to false
ssl_results[str(ip)] = {'host': '', 'server_name': '', 'exp_date': '', 'days_to_expire': ''}
try:
host = ip.strip().split(':')[0]
port = ip.strip().split(':')[1]
print('\nChecking certifcate for server ', host)
# Connect to server using SSL.
ctx = OpenSSL.SSL.Context(ssl.PROTOCOL_TLSv1)
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((host, int(port)))
cnx = OpenSSL.SSL.Connection(ctx, s)
cnx.set_connect_state()
cnx.do_handshake()
# Connection complete get SSL certificate and close connection.
cert = cnx.get_peer_certificate()
s.close()
# From SSL certificate get host name, expiration date and decode.
server_name = cert.get_subject().commonName
print(server_name)
edate = cert.get_notAfter()
edate = edate.decode()
# Get date and format. Calculate number of days until SSL expires.
exp_date = datetime.datetime.strptime(edate, '%Y%m%d%H%M%SZ')
days_to_expire = int((exp_date - cur_date).days)
print(exp_date)
print('day to expire', days_to_expire)
# Update the hosts entry
ssl_results[str(ip)]['host'] = host
ssl_results[str(ip)]['server_name'] = server_name
ssl_results[str(ip)]['exp_date'] = exp_date
ssl_results[str(ip)]['days_to_expire'] = days_to_expire
# Logging for errors
except Exception as e:
logger.warning('Error on connection to Server,', str(ip))
logger.warning("ERROR ENCOUNTERED", host, "\n\n")
logger.warning(str(traceback.format_exc()))
# Loop through the ssl_results entries and generate a email + results file
try:
# Sort the ssl_results
sorted_results = sorted(ssl_results.items(),
key=lambda k: k[1]['days_to_expire'], reverse=False)
# variable to hold html for email
SSLCertificates = """<html>
<head>
<style>
table{width: 1024px;}
table, th, td {
border: 1px solid black;
border-collapse: collapse;
}
th, td {
padding: 5px;
text-align: left;
}
ul:before{
content:attr(data-header);
font-size:120%;
font-weight:bold;
margin-left:-15px;
}
</style>
</head>
<body>
<p><h2>Hello, </h2>
<h3>SSL Expiration Summary:</h3>
<span style="color:red;"><b>NOTE: If any of the below SSL certificates have less than 90 days remaining please renew.<b></span><br><br>
<table id=\"exp_ssls\"><tr><th>Host</th><th>Hostname</th><th>Expiration Date</th><th>Remaining Days</th></tr>
"""
# Write results in an html table
# Apply this formatting if days to expire are equal to or less than 90 days
for server, data in sorted_results:
if float(str(data["days_to_expire"])) <= 90:
SSLCertificates += "<tr><td bgcolor=yellow><font color=red><b>" + str(server) + "</b></td><td bgcolor=yellow><font color=red><b>" + str(data["server_name"]) + "</b></td><td bgcolor=yellow><font color=red><b>" + str(
data["exp_date"]) + "</b></td><td bgcolor=yellow><font color=red><b>" + str(data["days_to_expire"]) + "</b></td></tr>"
# Apply this formatting if days to expire are equal to or greater than 91 days
if float(str(data["days_to_expire"])) >= 91:
SSLCertificates += "<tr><td>" + str(server) + "</td><td>" + str(data["server_name"]) + "</td><td>" + str(
data["exp_date"]) + "</td><td>" + str(data["days_to_expire"]) + "</td></tr>"
SSLCertificates += """</body>
</html>"""
# Write data to a file and attach it to the email
f = open('SSLCertificates.html', 'w')
f.write(SSLCertificates)
f.close()
filename = 'SSLCertificates.html'
attachment = open(filename, 'rb')
# Setup email attachment
msg.attach(MIMEText(SSLCertificates, 'html'))
part = MIMEBase('application', 'octet-stream')
part.set_payload(attachment.read())
encoders.encode_base64(part)
part.add_header('Content-Disposition', "attachment; filename=" + filename)
# Send email
msg.attach(part)
text = msg.as_string()
server = smtplib.SMTP('smtp.server.com', 25)
server.sendmail(email_sen, email_rec, text)
server.quit()
# Logging for errors
except Exception as e:
logging.warning("ERROR ENCOUNTERED! \n\n")
logging.warning(str(traceback.format_exc()))
您有
logger.warning('Error on connection to Server,', str(ip))
但应该是:
logger.warning('Error on connection to Server "%s"', str(ip))
或同等学历。
您正在传递一个额外的参数str(ip)
,但是消息中没有放置它的占位符,因此,错误的以下部分:
File "E:\Python36\lib\logging\__init__.py", line 338, in getMessage
msg = msg % self.args
TypeError: not all arguments converted during string formatting
Call stack:
File "ssl_nag_script_test.py", line 106, in <module>
logger.warning('Error on connection to Server,', str(ip))