diff options
author | mmeade <mmeade@chromium.org> | 2015-06-23 13:14:11 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-06-23 20:14:51 +0000 |
commit | b7d5efb668de61028b5df1116ceb33a5327c79df (patch) | |
tree | 44faed7a276f8e8d600918c68ff0f9bfed943d7e | |
parent | f48fe876ae18ebe0a639eb271c3b7192f410bc0b (diff) | |
download | chromium_src-b7d5efb668de61028b5df1116ceb33a5327c79df.zip chromium_src-b7d5efb668de61028b5df1116ceb33a5327c79df.tar.gz chromium_src-b7d5efb668de61028b5df1116ceb33a5327c79df.tar.bz2 |
Changing the RPC connections from HTTP to HTTPS
This change adds SSL support to the servers. This adds another layer of security
on top of the current security measures.
BUG=
Review URL: https://codereview.chromium.org/1205593003
Cr-Commit-Position: refs/heads/master@{#335728}
-rw-r--r-- | testing/legion/common_lib.py | 7 | ||||
-rw-r--r-- | testing/legion/legion.isolate | 1 | ||||
-rw-r--r-- | testing/legion/rpc_server.py | 6 | ||||
-rwxr-xr-x | testing/legion/run_task.py | 5 | ||||
-rw-r--r-- | testing/legion/ssl_util.py | 103 | ||||
-rw-r--r-- | testing/legion/task_controller.py | 3 | ||||
-rw-r--r-- | testing/legion/task_registration_server.py | 4 |
7 files changed, 114 insertions, 15 deletions
diff --git a/testing/legion/common_lib.py b/testing/legion/common_lib.py index 6e7954b..bc3222c 100644 --- a/testing/legion/common_lib.py +++ b/testing/legion/common_lib.py @@ -34,10 +34,3 @@ def InitLogging(): logging.basicConfig( format='%(asctime)s %(filename)s:%(lineno)s %(levelname)s] %(message)s', datefmt='%H:%M:%S', level=args.verbosity) - - -def ConnectToServer(server): - """Connect to an RPC server.""" - addr = 'http://%s:%d' % (server, SERVER_PORT) - logging.debug('Connecting to RPC server at %s', addr) - return xmlrpclib.Server(addr, allow_none=True) diff --git a/testing/legion/legion.isolate b/testing/legion/legion.isolate index 18e0b3b..44bc2e1 100644 --- a/testing/legion/legion.isolate +++ b/testing/legion/legion.isolate @@ -13,6 +13,7 @@ 'rpc_methods.py', 'rpc_server.py', 'run_task.py', + 'ssl_util.py', 'task_controller.py', 'task_registration_server.py', 'test_controller.py', diff --git a/testing/legion/rpc_server.py b/testing/legion/rpc_server.py index 43b4317..d9d98cc 100644 --- a/testing/legion/rpc_server.py +++ b/testing/legion/rpc_server.py @@ -24,6 +24,7 @@ import SocketServer #pylint: disable=relative-import import common_lib import rpc_methods +import ssl_util class RequestHandler(SimpleXMLRPCServer.SimpleXMLRPCRequestHandler): @@ -47,17 +48,16 @@ class RequestHandler(SimpleXMLRPCServer.SimpleXMLRPCRequestHandler): return SimpleXMLRPCServer.SimpleXMLRPCRequestHandler.do_POST(self) -class RPCServer(SimpleXMLRPCServer.SimpleXMLRPCServer, +class RpcServer(ssl_util.SslRpcServer, SocketServer.ThreadingMixIn): """Restricts all endpoints to only specified IP addresses.""" def __init__(self, authorized_address, idle_timeout_secs=common_lib.DEFAULT_TIMEOUT_SECS): - SimpleXMLRPCServer.SimpleXMLRPCServer.__init__( + ssl_util.SslRpcServer.__init__( self, (common_lib.SERVER_ADDRESS, common_lib.SERVER_PORT), allow_none=True, logRequests=False, requestHandler=RequestHandler) - self.authorized_address = authorized_address self.idle_timeout_secs = idle_timeout_secs self.register_instance(rpc_methods.RPCMethods(self)) diff --git a/testing/legion/run_task.py b/testing/legion/run_task.py index 26c6e5c..cb0b90f 100755 --- a/testing/legion/run_task.py +++ b/testing/legion/run_task.py @@ -14,6 +14,7 @@ import time #pylint: disable=relative-import import common_lib import rpc_server +import ssl_util def main(): @@ -34,10 +35,10 @@ def main(): logging.info( 'Registering with registration server at %s using OTP "%s"', args.controller, args.otp) - common_lib.ConnectToServer(args.controller).RegisterTask( + ssl_util.SslRpcServer.Connect(args.controller).RegisterTask( args.otp, common_lib.MY_IP) - server = rpc_server.RPCServer(args.controller, args.idle_timeout) + server = rpc_server.RpcServer(args.controller, args.idle_timeout) server.serve_forever() logging.info('Server shutdown complete') diff --git a/testing/legion/ssl_util.py b/testing/legion/ssl_util.py new file mode 100644 index 0000000..1571c77 --- /dev/null +++ b/testing/legion/ssl_util.py @@ -0,0 +1,103 @@ +# 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 +import xmlrpclib +import SimpleXMLRPCServer + +#pylint: disable=relative-import +import common_lib + + +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(SimpleXMLRPCServer.SimpleXMLRPCServer): + """Class to add SSL support to the RPC server.""" + + def __init__(self, *args, **kwargs): + SimpleXMLRPCServer.SimpleXMLRPCServer.__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 xmlrpclib.Server(addr, allow_none=True) diff --git a/testing/legion/task_controller.py b/testing/legion/task_controller.py index 9514f44..5522a2b 100644 --- a/testing/legion/task_controller.py +++ b/testing/legion/task_controller.py @@ -18,6 +18,7 @@ import xmlrpclib #pylint: disable=relative-import import common_lib import process +import ssl_util ISOLATE_PY = os.path.join(common_lib.SWARMING_DIR, 'isolate.py') SWARMING_PY = os.path.join(common_lib.SWARMING_DIR, 'swarming.py') @@ -208,6 +209,6 @@ class TaskController(object): """Receives task ip address on connection.""" self._ip_address = ip_address self._connected = True - self._rpc = common_lib.ConnectToServer(self._ip_address) + self._rpc = ssl_util.SslRpcServer.Connect(self._ip_address) logging.info('%s connected from %s', self._name, ip_address) self._connect_event.set() diff --git a/testing/legion/task_registration_server.py b/testing/legion/task_registration_server.py index fe92dcd..85d6eab 100644 --- a/testing/legion/task_registration_server.py +++ b/testing/legion/task_registration_server.py @@ -12,10 +12,10 @@ is based on an OTP passed to the run_task binary on startup. import logging import threading import xmlrpclib -import SimpleXMLRPCServer #pylint: disable=relative-import import common_lib +import ssl_util class TaskRegistrationServer(object): @@ -40,7 +40,7 @@ class TaskRegistrationServer(object): def Start(self): """Starts the registration server.""" logging.info('Starting task registration server') - self._rpc_server = SimpleXMLRPCServer.SimpleXMLRPCServer( + self._rpc_server = ssl_util.SslRpcServer( (common_lib.SERVER_ADDRESS, common_lib.SERVER_PORT), allow_none=True, logRequests=False) self._rpc_server.register_function( |