forked from Corollarium/localtls
-
Notifications
You must be signed in to change notification settings - Fork 0
/
httpserver.py
117 lines (104 loc) · 3.86 KB
/
httpserver.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
#-*- coding: utf-8 -*-
import os
import sys
import confs
import cherrypy
import subprocess
import logging
INDEX_HTML='<html><body>Hi.</body></html>'
CERT_PATH='/etc/letsencrypt/live/' + confs.BASE_DOMAIN
logger = logging.getLogger('localtls')
class Root(object):
@cherrypy.expose
def index(self):
return INDEX_HTML
@cherrypy.expose
@cherrypy.tools.json_out()
def keys(self):
privkey = cert = chain = fullchain = ''
try:
with open(os.path.join(CERT_PATH, 'cert.pem')) as f:
cert = f.read()
with open(os.path.join(CERT_PATH, 'chain.pem')) as f:
chain = f.read()
with open(os.path.join(CERT_PATH, 'fullchain.pem')) as f:
fullchain = f.read()
with open(os.path.join(CERT_PATH, 'privkey.pem')) as f:
privkey = f.read()
except ValueError as e:
cherrypy.log(str(e))
except FileNotFoundError as e:
cherrypy.log(str(e))
except:
cherrypy.log("Unexpected error:", sys.exc_info()[0])
return {'privkey': privkey, 'cert': cert, 'chain': chain, 'fullchain': fullchain}
@cherrypy.expose
def favicon_ico(self):
raise cherrypy.HTTPError(404)
def listCertificates():
command = [
'certbot', 'certificates'
]
output = subprocess.Popen(command, stdout=subprocess.PIPE, bufsize=1, universal_newlines=True)
current_certificate = ''
current_domain = ''
paths = {}
for line in iter(output.stdout.readline,''):
if line.find('Certificate Name') > -1:
current_certificate = line.split(':')[1].strip()
continue
elif line.find('Domains') > -1:
domains = line.split(':')[1].strip()
current_domain = domains
elif line.find('Certificate Path') > -1:
p = line.split(':')[1].strip()
paths[domains] = os.path.dirname(p)
return paths
def force_tls(self=None):
# check if url is in https and redirect if http
if cherrypy.request.scheme == "http":
raise cherrypy.HTTPRedirect(cherrypy.url().replace("http:", "https:"), status=301)
def run(port, index, certpath=''):
global INDEX_HTML, CERT_PATH
try:
with open(index) as f:
INDEX_HTML=bytes(f.read(), "utf8")
except:
pass
# get certificates
try:
paths = listCertificates()
if ('*.' + confs.BASE_DOMAIN) in paths:
CERT_PATH = paths['*.' + confs.BASE_DOMAIN]
else:
logger.critical("Cannot find wildcard certificate. Run certbotdns.py now and then restart this. Meanwhile HTTP will not work.")
return
except:
logger.critical("Cannot list certificates: {}. Is certbot installed?".format(sys.exc_info()[0]))
#return
cherrypy.config.update({
'log.screen': False,
'log.access_file': '',
'log.error_file': 'http_error_log',
'environment': 'production',
'server.socket_host': '::',
'server.socket_port': int(port)
})
if port == 443 and confs.BASE_DOMAIN in paths:
logger.info('Starting TLS server.')
cert = paths[confs.BASE_DOMAIN]
cherrypy.tools.force_tls = cherrypy.Tool("before_handler", force_tls)
cherrypy.config.update({
'server.ssl_module': 'builtin',
'server.ssl_certificate': os.path.join(cert, "cert.pem"),
'server.ssl_private_key': os.path.join(cert, "privkey.pem"),
'server.ssl_certificate_chain': os.path.join(cert, "fullchain.pem"),
'tools.force_tls.on': True
})
# extra server instance to dispatch HTTP
server = cherrypy._cpserver.Server()
server.socket_host = '::'
server.socket_port = 80
server.subscribe()
logger.info('Starting HTTP server.')
cherrypy.quickstart(Root(), '/')