mirror of
https://github.com/netzbegruenung/green-spider.git
synced 2024-05-04 18:13:40 +02:00
Improve certificate check to support SNI (#71)
* Fix the certificate check to support SNI * Better tests for the certificate check * Activate verbose output when running make test * Add commenting on the spider test
This commit is contained in:
parent
ae6a2e83e9
commit
57f8dea4e0
2
Makefile
2
Makefile
|
@ -44,5 +44,5 @@ test: dockerimage
|
||||||
docker run --rm -ti \
|
docker run --rm -ti \
|
||||||
--entrypoint "python3" \
|
--entrypoint "python3" \
|
||||||
$(IMAGE) \
|
$(IMAGE) \
|
||||||
-m unittest discover -p '*_test.py'
|
-m unittest discover -p '*_test.py' -v
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@ Gathers information on the TLS/SSL certificate used by a server
|
||||||
|
|
||||||
from urllib.parse import urlparse
|
from urllib.parse import urlparse
|
||||||
import logging
|
import logging
|
||||||
|
import socket
|
||||||
import ssl
|
import ssl
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from datetime import timezone
|
from datetime import timezone
|
||||||
|
@ -36,8 +37,22 @@ class Checker(AbstractChecker):
|
||||||
}
|
}
|
||||||
|
|
||||||
parsed = urlparse(url)
|
parsed = urlparse(url)
|
||||||
|
port = 443
|
||||||
|
if parsed.port is not None:
|
||||||
|
port = parsed.port
|
||||||
|
|
||||||
|
try:
|
||||||
|
#cert = ssl.get_server_certificate((parsed.hostname, port))
|
||||||
|
|
||||||
|
context = ssl.create_default_context()
|
||||||
|
|
||||||
|
# get certificate with SNI
|
||||||
|
with socket.create_connection((parsed.hostname, port)) as sock:
|
||||||
|
with context.wrap_socket(sock, server_hostname=parsed.hostname) as sslsock:
|
||||||
|
der_cert = sslsock.getpeercert(True)
|
||||||
|
cert = ssl.DER_cert_to_PEM_cert(der_cert)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
cert = ssl.get_server_certificate((parsed.hostname, 443))
|
|
||||||
x509 = crypto.load_certificate(crypto.FILETYPE_PEM, cert)
|
x509 = crypto.load_certificate(crypto.FILETYPE_PEM, cert)
|
||||||
result['serial_number'] = str(x509.get_serial_number())
|
result['serial_number'] = str(x509.get_serial_number())
|
||||||
|
|
||||||
|
@ -51,6 +66,11 @@ class Checker(AbstractChecker):
|
||||||
# decode and convert from bytes to unicode
|
# decode and convert from bytes to unicode
|
||||||
result['subject'] = dict([tuple(map(lambda x: x.decode('utf-8'), tup)) for tup in x509.get_subject().get_components()])
|
result['subject'] = dict([tuple(map(lambda x: x.decode('utf-8'), tup)) for tup in x509.get_subject().get_components()])
|
||||||
result['issuer'] = dict([tuple(map(lambda x: x.decode('utf-8'), tup)) for tup in x509.get_issuer().get_components()])
|
result['issuer'] = dict([tuple(map(lambda x: x.decode('utf-8'), tup)) for tup in x509.get_issuer().get_components()])
|
||||||
|
except Exception as e:
|
||||||
|
result['exception'] = {
|
||||||
|
'type': str(type(e)),
|
||||||
|
'message': str(e),
|
||||||
|
}
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
result['exception'] = {
|
result['exception'] = {
|
||||||
|
|
|
@ -1,10 +1,13 @@
|
||||||
from checks import certificate
|
from checks import certificate
|
||||||
from checks.config import Config
|
from checks.config import Config
|
||||||
|
|
||||||
import unittest
|
import unittest
|
||||||
|
from pprint import pprint
|
||||||
|
|
||||||
class TestCertificateChecker(unittest.TestCase):
|
class TestCertificateChecker(unittest.TestCase):
|
||||||
|
|
||||||
def test_google(self):
|
def test_google(self):
|
||||||
|
"""Load cert from a site that should work"""
|
||||||
url = 'https://www.google.com/'
|
url = 'https://www.google.com/'
|
||||||
config = Config(urls=[url])
|
config = Config(urls=[url])
|
||||||
checker = certificate.Checker(config=config, previous_results={})
|
checker = certificate.Checker(config=config, previous_results={})
|
||||||
|
@ -14,6 +17,7 @@ class TestCertificateChecker(unittest.TestCase):
|
||||||
self.assertEqual(result[url]['issuer']['O'], 'Google Trust Services')
|
self.assertEqual(result[url]['issuer']['O'], 'Google Trust Services')
|
||||||
|
|
||||||
def test_kaarst(self):
|
def test_kaarst(self):
|
||||||
|
"""Real-workd example"""
|
||||||
url = 'https://www.gruenekaarst.de/'
|
url = 'https://www.gruenekaarst.de/'
|
||||||
config = Config(urls=[url])
|
config = Config(urls=[url])
|
||||||
checker = certificate.Checker(config=config, previous_results={})
|
checker = certificate.Checker(config=config, previous_results={})
|
||||||
|
@ -22,6 +26,37 @@ class TestCertificateChecker(unittest.TestCase):
|
||||||
self.assertIsNone(result[url]['exception'])
|
self.assertIsNone(result[url]['exception'])
|
||||||
self.assertEqual(result[url]['issuer']['O'], 'COMODO CA Limited')
|
self.assertEqual(result[url]['issuer']['O'], 'COMODO CA Limited')
|
||||||
|
|
||||||
|
def test_tls_v_1_0(self):
|
||||||
|
"""Load a certificate for a TLS v1.0 server"""
|
||||||
|
url = 'https://tls-v1-0.badssl.com:1010/'
|
||||||
|
config = Config(urls=[url])
|
||||||
|
checker = certificate.Checker(config=config, previous_results={})
|
||||||
|
result = checker.run()
|
||||||
|
self.assertIn(url, result)
|
||||||
|
self.assertIsNone(result[url]['exception'])
|
||||||
|
self.assertEqual(result[url]['subject']['CN'], '*.badssl.com')
|
||||||
|
|
||||||
|
def test_tls_v_1_1(self):
|
||||||
|
"""Load a certificate for a TLS v1.1 server"""
|
||||||
|
url = 'https://tls-v1-1.badssl.com:1011/'
|
||||||
|
config = Config(urls=[url])
|
||||||
|
checker = certificate.Checker(config=config, previous_results={})
|
||||||
|
result = checker.run()
|
||||||
|
self.assertIn(url, result)
|
||||||
|
self.assertIsNone(result[url]['exception'])
|
||||||
|
self.assertEqual(result[url]['subject']['CN'], '*.badssl.com')
|
||||||
|
|
||||||
|
def test_tls_v_1_2(self):
|
||||||
|
"""Load a certificate for a TLS v1.2 server"""
|
||||||
|
url = 'https://tls-v1-2.badssl.com:1012/'
|
||||||
|
config = Config(urls=[url])
|
||||||
|
checker = certificate.Checker(config=config, previous_results={})
|
||||||
|
result = checker.run()
|
||||||
|
self.assertIn(url, result)
|
||||||
|
self.assertIsNone(result[url]['exception'])
|
||||||
|
self.assertEqual(result[url]['subject']['CN'], '*.badssl.com')
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
|
|
@ -1,12 +1,19 @@
|
||||||
import unittest
|
import unittest
|
||||||
|
from pprint import pprint
|
||||||
|
|
||||||
from spider.spider import check_and_rate_site
|
from spider.spider import check_and_rate_site
|
||||||
|
|
||||||
from pprint import pprint
|
class TestSpider(unittest.TestCase):
|
||||||
|
|
||||||
class TestSpiderr(unittest.TestCase):
|
"""
|
||||||
|
Simply calls the spider.check_and_rate_site function
|
||||||
|
with httpbin.org URLs. We don't assert a lot here,
|
||||||
|
but at least make sure that most of our code is executed
|
||||||
|
in tests.
|
||||||
|
"""
|
||||||
|
|
||||||
def test_url1(self):
|
def test_html(self):
|
||||||
|
"""Loads a simple HTML web page"""
|
||||||
|
|
||||||
entry = {
|
entry = {
|
||||||
"url": "https://httpbin.org/html",
|
"url": "https://httpbin.org/html",
|
||||||
|
|
Loading…
Reference in a new issue