Added HTTPS support to Xend. There are new configuration options for the

Xen-API and legacy XML-RPC servers to set key and certificate files, and
xm simply needs to be configured use an https rather than an http URL.

Signed-off-by: Ewan Mellor <ewan@xensource.com>
This commit is contained in:
Ewan Mellor committed 2007-03-27 23:23:01 +01:00
1 parent 2a5cee571c
commit b843dd7af8
6 files changed
+248 -39

No files matched your search

+29 -1
View File
@@ -32,7 +32,6 @@ except ImportError:
ssh_enabled = False
# A new ServerProxy that also supports httpu urls. An http URL comes in the
# form:
#
@@ -57,6 +56,33 @@ class UnixTransport(xmlrpclib.Transport):
return HTTPUnix(self.__handler)
# We need our own transport for HTTPS, because xmlrpclib.SafeTransport is
# broken -- it does not handle ERROR_ZERO_RETURN properly.
class HTTPSTransport(xmlrpclib.SafeTransport):
def _parse_response(self, file, sock):
p, u = self.getparser()
while 1:
try:
if sock:
response = sock.recv(1024)
else:
response = file.read(1024)
except socket.sslerror, exn:
if exn[0] == socket.SSL_ERROR_ZERO_RETURN:
break
raise
if not response:
break
if self.verbose:
print 'body:', repr(response)
p.feed(response)
file.close()
p.close()
return u.close()
# See xmlrpclib2.TCPXMLRPCServer._marshalled_dispatch.
def conv_string(x):
if isinstance(x, StringTypes):
@@ -75,6 +101,8 @@ class ServerProxy(xmlrpclib.ServerProxy):
if protocol == 'httpu':
uri = 'http:' + rest
transport = UnixTransport()
elif protocol == 'https':
transport = HTTPSTransport()
elif protocol == 'ssh':
global ssh_enabled
if ssh_enabled:
+7 -1
View File
@@ -165,7 +165,13 @@ class XendOptions:
def get_xend_tcp_xmlrpc_server_address(self):
return self.get_config_string("xend-tcp-xmlrpc-server-address",
self.xend_tcp_xmlrpc_server_address_default)
self.xend_tcp_xmlrpc_server_address_default)
def get_xend_tcp_xmlrpc_server_ssl_key_file(self):
return self.get_config_string("xend-tcp-xmlrpc-server-ssl-key-file")
def get_xend_tcp_xmlrpc_server_ssl_cert_file(self):
return self.get_config_string("xend-tcp-xmlrpc-server-ssl-cert-file")
def get_xend_unix_xmlrpc_server(self):
return self.get_config_bool("xend-unix-xmlrpc-server",
@@ -0,0 +1,103 @@
#============================================================================
# This library is free software; you can redistribute it and/or
# modify it under the terms of version 2.1 of the GNU Lesser General Public
# License as published by the Free Software Foundation.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#============================================================================
# Copyright (C) 2007 XenSource Inc.
#============================================================================
"""
HTTPS wrapper for an XML-RPC server interface. Requires PyOpenSSL (Debian
package python-pyopenssl).
"""
import socket
from OpenSSL import SSL
from xen.util.xmlrpclib2 import XMLRPCRequestHandler, TCPXMLRPCServer
class SSLXMLRPCRequestHandler(XMLRPCRequestHandler):
def setup(self):
self.connection = self.request
self.rfile = socket._fileobject(self.request, "rb", self.rbufsize)
self.wfile = socket._fileobject(self.request, "wb", self.wbufsize)
#
# Taken from pyOpenSSL-0.6 examples (public-domain)
#
class SSLWrapper:
"""
"""
def __init__(self, conn):
"""
Connection is not yet a new-style class,
so I'm making a proxy instead of subclassing.
"""
self.__dict__["conn"] = conn
def __getattr__(self, name):
return getattr(self.__dict__["conn"], name)
def __setattr__(self, name, value):
setattr(self.__dict__["conn"], name, value)
def close(self):
self.shutdown()
return self.__dict__["conn"].close()
def shutdown(self, how=1):
"""
SimpleXMLRpcServer.doPOST calls shutdown(1),
and Connection.shutdown() doesn't take
an argument. So we just discard the argument.
"""
# Block until the shutdown is complete
self.__dict__["conn"].shutdown()
self.__dict__["conn"].shutdown()
def accept(self):
"""
This is the other part of the shutdown() workaround.
Since servers create new sockets, we have to infect
them with our magic. :)
"""
c, a = self.__dict__["conn"].accept()
return (SSLWrapper(c), a)
#
# End of pyOpenSSL-0.6 example code.
#
class SSLXMLRPCServer(TCPXMLRPCServer):
def __init__(self, addr, allowed, xenapi, logRequests = 1,
ssl_key_file = None, ssl_cert_file = None):
TCPXMLRPCServer.__init__(self, addr, allowed, xenapi,
SSLXMLRPCRequestHandler, logRequests)
if not ssl_key_file or not ssl_cert_file:
raise ValueError("SSLXMLRPCServer requires ssl_key_file "
"and ssl_cert_file to be set.")
# make a SSL socket
ctx = SSL.Context(SSL.SSLv23_METHOD)
ctx.set_options(SSL.OP_NO_SSLv2)
ctx.use_privatekey_file (ssl_key_file)
ctx.use_certificate_file(ssl_cert_file)
self.socket = SSLWrapper(SSL.Connection(ctx,
socket.socket(self.address_family,
self.socket_type)))
self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
self.server_bind()
self.server_activate()
+53 -28
View File
@@ -185,33 +185,49 @@ def _loadConfig(servers, root, reload):
api_cfg = xoptions.get_xen_api_server()
if api_cfg:
try:
addrs = [(str(x[0]).split(':'),
len(x) > 1 and x[1] or XendAPI.AUTH_PAM,
len(x) > 2 and x[2] and map(re.compile, x[2].split(" "))
or None)
for x in api_cfg]
for addrport, auth, allowed in addrs:
if auth not in [XendAPI.AUTH_PAM, XendAPI.AUTH_NONE]:
log.error('Xen-API server configuration %s is invalid, ' +
'as %s is not a valid authentication type.',
api_cfg, auth)
break
for server_cfg in api_cfg:
# Parse the xen-api-server config
host = 'localhost'
port = 0
use_tcp = False
ssl_key_file = None
ssl_cert_file = None
auth_method = XendAPI.AUTH_NONE
hosts_allowed = None
host_addr = server_cfg[0].split(':', 1)
if len(host_addr) == 1 and host_addr[0].lower() == 'unix':
use_tcp = False
elif len(host_addr) == 1:
use_tcp = True
port = int(host_addr[0])
elif len(host_addr) == 2:
use_tcp = True
host = str(host_addr[0])
port = int(host_addr[1])
if len(server_cfg) > 1:
if server_cfg[1] in [XendAPI.AUTH_PAM, XendAPI.AUTH_NONE]:
auth_method = server_cfg[1]
if len(server_cfg) > 2:
hosts_allowed = server_cfg[2] or None
if len(server_cfg) > 4:
# SSL key and cert file
ssl_key_file = server_cfg[3]
ssl_cert_file = server_cfg[4]
servers.add(XMLRPCServer(auth_method, True, use_tcp = use_tcp,
ssl_key_file = ssl_key_file,
ssl_cert_file = ssl_cert_file,
host = host, port = port,
path = XEN_API_SOCKET,
hosts_allowed = hosts_allowed))
if len(addrport) == 1:
if addrport[0] == 'unix':
servers.add(XMLRPCServer(auth, True,
path = XEN_API_SOCKET,
hosts_allowed = allowed))
else:
servers.add(
XMLRPCServer(auth, True, True, '',
int(addrport[0]),
hosts_allowed = allowed))
else:
addr, port = addrport
servers.add(XMLRPCServer(auth, True, True, addr,
int(port),
hosts_allowed = allowed))
except (ValueError, TypeError), exn:
log.exception('Xen API Server init failed')
log.error('Xen-API server configuration %s is invalid.', api_cfg)
@@ -219,8 +235,17 @@ def _loadConfig(servers, root, reload):
if xoptions.get_xend_tcp_xmlrpc_server():
addr = xoptions.get_xend_tcp_xmlrpc_server_address()
port = xoptions.get_xend_tcp_xmlrpc_server_port()
servers.add(XMLRPCServer(XendAPI.AUTH_PAM, False, use_tcp = True,
host = addr, port = port))
ssl_key_file = xoptions.get_xend_tcp_xmlrpc_server_ssl_key_file()
ssl_cert_file = xoptions.get_xend_tcp_xmlrpc_server_ssl_cert_file()
if ssl_key_file and ssl_cert_file:
servers.add(XMLRPCServer(XendAPI.AUTH_PAM, False, use_tcp = True,
ssl_key_file = ssl_key_file,
ssl_cert_file = ssl_cert_file,
host = addr, port = port))
else:
servers.add(XMLRPCServer(XendAPI.AUTH_PAM, False, use_tcp = True,
host = addr, port = port))
if xoptions.get_xend_unix_xmlrpc_server():
servers.add(XMLRPCServer(XendAPI.AUTH_PAM, False))
+43 -8
View File
@@ -21,6 +21,11 @@ import socket
import types
import xmlrpclib
from xen.util.xmlrpclib2 import UnixXMLRPCServer, TCPXMLRPCServer
try:
from SSLXMLRPCServer import SSLXMLRPCServer
ssl_enabled = True
except ImportError:
ssl_enabled = False
from xen.xend import XendAPI, XendDomain, XendDomainInfo, XendNode
from xen.xend import XendLogging, XendDmesg
@@ -87,14 +92,20 @@ methods = ['device_create', 'device_configure',
exclude = ['domain_create', 'domain_restore']
class XMLRPCServer:
def __init__(self, auth, use_xenapi, use_tcp=False, host = "localhost",
port = 8006, path = XML_RPC_SOCKET, hosts_allowed = None):
def __init__(self, auth, use_xenapi, use_tcp = False,
ssl_key_file = None, ssl_cert_file = None,
host = "localhost", port = 8006, path = XML_RPC_SOCKET,
hosts_allowed = None):
self.use_tcp = use_tcp
self.port = port
self.host = host
self.path = path
self.hosts_allowed = hosts_allowed
self.ssl_key_file = ssl_key_file
self.ssl_cert_file = ssl_cert_file
self.ready = False
self.running = True
self.auth = auth
@@ -107,14 +118,33 @@ class XMLRPCServer:
try:
if self.use_tcp:
log.info("Opening TCP XML-RPC server on %s%d%s",
using_ssl = self.ssl_key_file and self.ssl_cert_file
log.info("Opening %s XML-RPC server on %s%d%s",
using_ssl and 'HTTPS' or 'TCP',
self.host and '%s:' % self.host or
'all interfaces, port ',
self.port, authmsg)
self.server = TCPXMLRPCServer((self.host, self.port),
self.hosts_allowed,
self.xenapi is not None,
logRequests = False)
if not ssl_enabled:
raise ValueError("pyOpenSSL not installed. "
"Unable to start HTTPS XML-RPC server")
if using_ssl:
self.server = SSLXMLRPCServer(
(self.host, self.port),
self.hosts_allowed,
self.xenapi is not None,
logRequests = False,
ssl_key_file = self.ssl_key_file,
ssl_cert_file = self.ssl_cert_file)
else:
self.server = TCPXMLRPCServer(
(self.host, self.port),
self.hosts_allowed,
self.xenapi is not None,
logRequests = False)
else:
log.info("Opening Unix domain socket XML-RPC server on %s%s",
self.path, authmsg)
@@ -126,7 +156,12 @@ class XMLRPCServer:
ready = True
running = False
return
except Exception, e:
log.exception('Cannot start server: %s!', e)
ready = True
running = False
return
# Register Xen API Functions
# -------------------------------------------------------------------
# exportable functions are ones that do not begin with '_'
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.