diff --git a/certclient.py b/certclient.py index ce8b842..6cde853 100755 --- a/certclient.py +++ b/certclient.py @@ -2,6 +2,7 @@ import argparse import requests +import sys parser = argparse.ArgumentParser(description='certclient') @@ -20,11 +21,6 @@ parser.add_argument( dest='client_key', action='store', required=True) -parser.add_argument( - '--csr', - dest='csr', - action='store', - required=True) parser.add_argument( '--server', dest='server', @@ -35,7 +31,7 @@ FLAGS = parser.parse_args() class CertClient(object): - def __init__(self, server, ca_cert, client_cert, client_key, csr): + def __init__(self, server, ca_cert, client_cert, client_key): self._session = requests.Session() self._session.verify = ca_cert self._session.cert = (client_cert, client_key) @@ -43,11 +39,12 @@ class CertClient(object): 'Content-Type': 'application/x-pem-file', }) self._server = server - self._csr = csr - def Request(self): - with open(self._csr, 'r') as fh: - self._session.post(self._server, data=fh.read()) + def Request(self, csr): + resp = self._session.post(self._server, data=csr) + assert resp.status_code == requests.codes.ok + assert resp.headers['Content-Type'] == 'application/x-pem-file' + return resp.text def main(): @@ -55,9 +52,9 @@ def main(): FLAGS.server, FLAGS.ca_cert, FLAGS.client_cert, - FLAGS.client_key, - FLAGS.csr) - client.Request() + FLAGS.client_key) + cert = client.Request(sys.stdin.read()) + print(cert, end='') if __name__ == '__main__': diff --git a/certserver.py b/certserver.py index 439282c..90c438a 100755 --- a/certserver.py +++ b/certserver.py @@ -1,9 +1,11 @@ #!/usr/bin/python3 import argparse +import json from http import server import socket import ssl +import subprocess parser = argparse.ArgumentParser(description='certserver') @@ -33,6 +35,11 @@ parser.add_argument( dest='server_cert', action='store', required=True) +parser.add_argument( + '--sign-command', + dest='sign_command', + action='store', + required=True) FLAGS = parser.parse_args() @@ -42,15 +49,31 @@ class HTTPServer6(server.HTTPServer): class CertServer(object): - def __init__(self, listen_host, listen_port, server_key, server_cert, ca_cert): + def __init__(self, listen_host, listen_port, server_key, server_cert, ca_cert, sign_command): class RequestHandler(server.BaseHTTPRequestHandler): def do_POST(self): + 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']) - print(self.rfile.read(size)) - self.send_response(200) - self.end_headers() + 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) self._httpd.socket = ssl.wrap_socket( @@ -73,7 +96,8 @@ def main(): FLAGS.listen_port, FLAGS.server_key, FLAGS.server_cert, - FLAGS.ca_cert) + FLAGS.ca_cert, + FLAGS.sign_command) server.Serve()