Vérifiez la date limite de renouvellement du certificat SSL à l'aide de la bibliothèque Python3 M2Crypto

Contexte

Dans le domaine où le certificat est automatiquement renouvelé par Let's Encrypt, si vous suivez le manuel, le certificat SSL doit être renouvelé au moment de moins de 30 jours avec le paramètre par défaut, mais le renouvellement est effectué. Je l'ai implémenté dans un script car j'avais besoin de vérifier si c'était le cas. En fait, ce qui suit est opéré en alimentant le fichier de configuration de la liste de domaines à vérifier, mais comme il n'y avait pas beaucoup d'explications sur la bibliothèque M2Crypto utilisée pour l'implémentation, je vais la transcrire en incluant l'enregistrement de l'opération réelle. .. J'aimerais pouvoir l'implémenter avec urllib, ce à quoi je suis habitué, mais je ne savais pas comment vérifier le certificat SSL, j'ai donc utilisé la bibliothèque M2Crypto.

environnement

Bibliothèque à utiliser

Environnement d'exécution Python

Un environnement python3 a été créé en utilisant Pyenv comme celui-ci.

 pwd
/root/python3

 pyenv versions
  system
* 3.5.6 (set by /root/python3/.python-version)

 python -V
Python 3.5.6

Confirmation de la date d'expiration du certificat SSL

Nous préparerons ce dont vous avez besoin tout en vérifiant l'état des données, etc. en utilisant le mode interactif interactif.

import ssl
import M2Crypto
import datetime

port = 443
 hostname = 'www.qiita.com' # Le domaine est le vôtre.

cert = ssl.get_server_certificate((hostname, port))

x509 = M2Crypto.X509.load_cert_string(cert)

x509.get_subject().as_text()    # 'CN=qiita.com'

De ce domaine, je ne sais pas grand-chose car je ne trouve pas beaucoup de documentation, je vais donc continuer en recherchant des méthodes utilisables.

dir(x509)
 ['__class__', '__del__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__',
 '__gt__', '__hash__', '__init__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__',
 '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', '_ptr', '_pyfree', 'add_ext', 'as_der', 'as_pem',
 'as_text', 'check_ca', 'check_purpose', 'get_ext', 'get_ext_at', 'get_ext_count', 'get_fingerprint', 'get_issuer', 'get_not_after',
 'get_not_before', 'get_pubkey', 'get_serial_number', 'get_subject', 'get_version', 'm2_x509_free', 'save', 'save_pem', 'set_issuer',
 'set_issuer_name', 'set_not_after', 'set_not_before', 'set_pubkey', 'set_serial_number', 'set_subject', 'set_subject_name',
 'set_version', 'sign', 'verify', 'x509']

J'ai trouvé get_not_after qui semble utilisable.

type(x509.get_not_after())         # <M2Crypto.ASN1.ASN1_TIME object at 0x7f26999f1940>

dir(x509.get_not_after())
 ['__class__', '__del__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__',
 '__gt__', '__hash__', '__init__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__',
 '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', '_ptr', '_pyfree', '_ssl_months', 'asn1_time',
 'get_datetime', 'm2_asn1_time_free', 'set_datetime', 'set_string', 'set_time']

J'ai trouvé quelque chose appelé get_datetime qui pourrait être généré avec datetime.

type(x509.get_not_after().get_datetime())  # <class 'datetime.datetime'>

x509.get_not_after().get_datetime()        # datetime.datetime(2020, 4, 30, 12, 0, tzinfo=<Timezone: UTC>)

Étant donné que les données ont été acquises par datetime, vous pouvez utiliser la bibliothèque datetime pour trouver le timedelta.

exp_date = x509.get_not_after().get_datetime()

now = datetime.datetime.now()            # datetime.datetime(2019, 11, 29, 10, 52, 24, 89337)

exp_date - now
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: can't subtract offset-naive and offset-aware datetimes

Il semble que la soustraction entre datetime ne soit pas possible si les fuseaux horaires sont associés. Référence: Gestion du fuseau horaire Python Donc, j'ai réduit les informations de fuseau horaire et comparé.

remaining_time = exp_date.replace(tzinfo=None) - now       # datetime.timedelta(53, 15629, 910663)

remaining_time.days
152

J'ai pu obtenir avec succès les jours restants du certificat SSL.

Le code final est ci-dessous. Il est relativement compact.

import ssl
import M2Crypto
from cryptography import x509
from cryptography.hazmat.backends import default_backend
import datetime

port = 443
 hostname = 'www.qiita.com' # Veuillez réécrire comme il convient ou lire l'argument

cert = ssl.get_server_certificate((hostname, port))
x509 = M2Crypto.X509.load_cert_string(cert)
exp_date = x509.get_not_after().get_datetime()
now = datetime.datetime.now()
remaining_time = exp_date.replace(tzinfo=None) - now

print(remaining_time.days)
152

Informations de référence

Recommended Posts

Vérifiez la date limite de renouvellement du certificat SSL à l'aide de la bibliothèque Python3 M2Crypto
Vérifiez le style de code python à l'aide de pep8
Installez la bibliothèque python sur Lambda à l'aide de [/ tmp]
Vérifiez les cours des actions avec Slackbot en utilisant Python
[Hyperledger Iroha] Créez un compte à l'aide de la bibliothèque Python
[Personal memo] julia --Utiliser la bibliothèque Python avec Julia en utilisant PyCall
Agréger les résultats des tests à l'aide de la bibliothèque Python QualityForward
Reconnaissance d'accords à l'aide du chromagramme de la bibliothèque de python librosa
Introduction de la bibliothèque d'imagerie Python (PIL) à l'aide de HomeBrew