text: # 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)
  