python - 获取 socket.gaierror : [Errno 11001] getaddrinfo failed using pyopenssl in Python 的处理错误

标签 python ssl exception ssl-certificate pyopenssl

总结: 我会尝试在第一次通过时进行解释,但如果我遗漏了一些相关细节,请告诉我,我会跟进。我正在从文本文件中获取服务器列表,并使用 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 = 'sen@email.com'
email_rec = 'rec@email.com'
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))

关于python - 获取 socket.gaierror : [Errno 11001] getaddrinfo failed using pyopenssl in Python 的处理错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59505940/

相关文章:

java - 方法异常未处理且代码编译成功

java - 在 DAO 层中捕获通用异常是一种不好的做法吗?

java - 由于 java.net.ssl.SSLHandshakeException,phpstorm 上的连接已关闭

javascript - 使用用 JavaScript 编写的客户端连接到用 C++ 编写的安全套接字服务器

maven - 目标特定的 javax.net.ssl.trustStore

c# - 如何查找 OpenReadAsync 方法抛出的异常

python - 如果 sqlite 安装在非标准位置,则构建 python 2.6 w/sqlite3 模块

python - 在 Ubuntu 上通过 pyODBC 连接到 Microsoft SQL Server

python - PyQt:搜索项目 QTableWidget 并获取它的坐标?

python - 在 pandas 的帮助下按条件删除行