Files
site-servaki-online/verify_live.py
T

65 lines
2.7 KiB
Python

"""Check the public Beget release over HTTP and inspect the TLS certificate."""
from pathlib import Path
from urllib.request import build_opener, ProxyHandler, HTTPSHandler, Request
import json
import socket
import ssl
import sys
ROOT = Path(__file__).resolve().parent
PUBLIC = ROOT / 'public'
sys.path.insert(0, str(ROOT / '.deps'))
from cryptography import x509
BASE = 'https://servaki.online'
opener = build_opener(ProxyHandler({}), HTTPSHandler(context=ssl._create_unverified_context()))
def get(path):
request = Request(BASE + path, headers={'Cache-Control': 'no-cache', 'Accept-Encoding': 'identity'})
with opener.open(request, timeout=20) as response:
return response.status, response.read(), response.url
def certificate():
with socket.create_connection(('servaki.online', 443), timeout=12) as conn:
with ssl._create_unverified_context().wrap_socket(conn, server_hostname='servaki.online') as tls:
cert = x509.load_der_x509_certificate(tls.getpeercert(binary_form=True))
valid = True
try:
with socket.create_connection(('servaki.online', 443), timeout=12) as conn:
with ssl.create_default_context().wrap_socket(conn, server_hostname='servaki.online'):
pass
except ssl.SSLError:
valid = False
return valid, cert.not_valid_after_utc.isoformat()
def main():
pages = sorted(PUBLIC.rglob('*.html'))
selected = pages + [PUBLIC / 'robots.txt', PUBLIC / 'sitemap.xml']
selected += [PUBLIC / 'assets/editorial/editorial.css',
PUBLIC / 'assets/editorial/photo-networks-vpn-960.webp',
PUBLIC / 'assets/editorial/networks-vpn-480.webp']
mismatches = []
for file in selected:
rel = file.relative_to(PUBLIC).as_posix()
path = '/' if rel == 'index.html' else '/' + rel.removesuffix('index.html')
try:
status, body, final_url = get(path)
if status != 200 or body != file.read_bytes() or not final_url.startswith(BASE + '/'):
mismatches.append({'path': path, 'status': status, 'bytes': len(body)})
except Exception as error:
mismatches.append({'path': path, 'error': type(error).__name__ + ': ' + str(error)[:130]})
valid, not_after = certificate()
report = {'checked': len(selected), 'exact_matches': len(selected) - len(mismatches),
'tls_valid': valid, 'tls_not_after': not_after, 'mismatches': mismatches}
(ROOT / 'live-verification.json').write_text(json.dumps(report, ensure_ascii=False, indent=2), encoding='utf-8')
print(json.dumps(report, ensure_ascii=False))
if mismatches or not valid:
raise SystemExit(1)
if __name__ == '__main__':
main()