Files
certserver/certserver.py

107 lines
2.8 KiB
Python
Raw Normal View History

2016-04-03 12:08:55 -07:00
#!/usr/bin/python3
2016-04-03 12:14:26 -07:00
import argparse
2016-04-05 06:42:42 +00:00
import json
2016-04-03 12:08:55 -07:00
from http import server
import socket
import ssl
2016-04-05 06:42:42 +00:00
import subprocess
2016-04-03 12:08:55 -07:00
2016-04-03 12:14:26 -07:00
parser = argparse.ArgumentParser(description='certserver')
2016-04-03 12:50:30 -07:00
parser.add_argument(
'--ca-cert',
dest='ca_cert',
action='store',
required=True)
2016-04-03 12:14:26 -07:00
parser.add_argument(
'--listen-host',
dest='listen_host',
action='store',
default='::')
parser.add_argument(
'--listen-port',
dest='listen_port',
type=int,
action='store',
default=443)
parser.add_argument(
'--server-key',
dest='server_key',
action='store',
required=True)
parser.add_argument(
'--server-cert',
dest='server_cert',
action='store',
required=True)
2016-04-05 06:42:42 +00:00
parser.add_argument(
'--sign-command',
dest='sign_command',
action='store',
required=True)
2016-04-03 12:14:26 -07:00
FLAGS = parser.parse_args()
2016-04-03 12:08:55 -07:00
class HTTPServer6(server.HTTPServer):
address_family = socket.AF_INET6
2016-04-03 12:14:26 -07:00
class CertServer(object):
2016-04-05 06:42:42 +00:00
def __init__(self, listen_host, listen_port, server_key, server_cert, ca_cert, sign_command):
class RequestHandler(server.BaseHTTPRequestHandler):
def do_POST(self):
2016-04-05 06:42:42 +00:00
print('Request from: [%s]:%d' % (self.client_address[0], self.client_address[1]))
peer_cert = json.dumps(dict(x[0] for x in self.request.getpeercert()['subject']), sort_keys=True)
print('Client cert:\n\t%s' % peer_cert.replace('\n', '\n\t'))
assert self.headers['Content-Type'] == 'application/x-pem-file'
size = int(self.headers['Content-Length'])
2016-04-05 06:42:42 +00:00
cert = self.rfile.read(size)
with subprocess.Popen(sign_command, shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE) as proc:
proc.stdin.write(cert)
proc.stdin.close()
signed = proc.stdout.read()
stderr = proc.stderr.read().decode('ascii')
print('OpenSSL output:\n\t%s' % stderr.replace('\n', '\n\t').strip())
if proc.wait() == 0:
self.send_response(200)
self.send_header('Content-Type', 'application/x-pem-file')
self.end_headers()
self.wfile.write(signed)
else:
self.send_response(500)
self.end_headers()
self._httpd = HTTPServer6((listen_host, listen_port), RequestHandler)
2016-04-03 12:14:26 -07:00
self._httpd.socket = ssl.wrap_socket(
self._httpd.socket,
keyfile=server_key,
certfile=server_cert,
2016-04-03 12:50:30 -07:00
ca_certs=ca_cert,
2016-04-03 12:14:26 -07:00
server_side=True,
cert_reqs=ssl.CERT_REQUIRED,
ssl_version=ssl.PROTOCOL_TLSv1_2,
ciphers='ECDHE-ECDSA-AES256-GCM-SHA384')
2016-04-10 21:51:08 +00:00
self._httpd.settimeout(5.0)
2016-04-03 12:14:26 -07:00
def Serve(self):
self._httpd.serve_forever()
def main():
server = CertServer(
FLAGS.listen_host,
FLAGS.listen_port,
FLAGS.server_key,
2016-04-03 12:50:30 -07:00
FLAGS.server_cert,
2016-04-05 06:42:42 +00:00
FLAGS.ca_cert,
FLAGS.sign_command)
2016-04-03 12:14:26 -07:00
server.Serve()
if __name__ == '__main__':
main()