blob: 57d1ef9a21929db5d6eecb83fb08d155bb9a4cff [file] [log] [blame]
# Copyright 2015 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Utility library to add SSL support to the RPC server."""
import logging
import ssl
import subprocess
import tempfile
from legion.lib import common_lib
from legion.lib.rpc import jsonrpclib
from legion.lib.rpc import SimpleJSONRPCServer
class Error(Exception):
pass
def CreateKeyFile():
"""Creates an SSL keyfile and returns the path."""
keyfile = tempfile.mkstemp()[1]
cmd = [
'openssl',
'genrsa',
'-out', keyfile,
'2048'
]
_RunCommand(cmd)
return keyfile
def CreateCsrFile(keyfile):
"""Creates an SSL CSR file and returns the path."""
csrfile = tempfile.mkstemp()[1]
cmd = [
'openssl',
'req',
'-new',
'-key', keyfile,
'-out', csrfile,
'-subj', '/C=NA/ST=NA/L=NA/O=Chromium/OU=Test/CN=chromium.org'
]
_RunCommand(cmd)
return csrfile
def CreateCrtFile(keyfile, csrfile):
"""Creates an SSL CRT file and returns the path."""
crtfile = tempfile.mkstemp()[1]
cmd = [
'openssl',
'x509',
'-req',
'-days', '1',
'-in', csrfile,
'-signkey', keyfile,
'-out', crtfile
]
_RunCommand(cmd)
return crtfile
def CreatePemFile():
"""Creates an SSL PEM file and returns the path."""
keyfile = CreateKeyFile()
csrfile = CreateCsrFile(keyfile)
crtfile = CreateCrtFile(keyfile, csrfile)
pemfile = tempfile.mkstemp()[1]
with open(keyfile) as k:
with open(crtfile) as c:
with open(pemfile, 'wb') as p:
p.write('%s\n%s' % (k.read(), c.read()))
return pemfile
def _RunCommand(cmd):
try:
p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
except OSError as e:
raise Error('Failed to run %s: %s' % (' '.join(cmd), e))
out, err = p.communicate()
if p.returncode != 0:
raise Error(err)
return out
class SslRpcServer(SimpleJSONRPCServer.SimpleJSONRPCServer):
"""Class to add SSL support to the RPC server."""
def __init__(self, *args, **kwargs):
SimpleJSONRPCServer.SimpleJSONRPCServer.__init__(self, *args, **kwargs)
self.socket = ssl.wrap_socket(self.socket, certfile=CreatePemFile(),
server_side=True)
@staticmethod
def Connect(server, port=common_lib.SERVER_PORT):
"""Creates and returns a connection to an SSL RPC server."""
addr = 'https://%s:%d' % (server, port)
logging.debug('Connecting to RPC server at %s', addr)
return jsonrpclib.ServerProxy(addr, allow_none=True)