Author: tmckay
Date: 2012-05-10 20:44:07 +0000 (Thu, 10 May 2012)
New Revision: 5372
Modified:
trunk/cumin/bin/cumin-web
trunk/cumin/etc/cumin.conf
trunk/cumin/python/cumin/config.py
trunk/cumin/python/cumin/errors.py
trunk/cumin/python/cumin/main.py
trunk/cumin/python/cumin/server.py
trunk/wooly/python/wooly/server.py
trunk/wooly/python/wooly/wsgiserver/ssl_builtin.py
trunk/wooly/python/wooly/wsgiserver/ssl_pyopenssl.py
Log:
Modifications to use the ssl support provided by cherrypy
BZ820681
Modified: trunk/cumin/bin/cumin-web
===================================================================
--- trunk/cumin/bin/cumin-web 2012-05-10 15:14:01 UTC (rev 5371)
+++ trunk/cumin/bin/cumin-web 2012-05-10 20:44:07 UTC (rev 5372)
@@ -67,6 +67,30 @@
cumin.ldap_tls_cacertdir = values.ldap_tls_cacertdir
cumin.ldap_tls_cacertfile = values.ldap_tls_cacertfile
+def check_cert_files(opts):
+ # If a certificate or key file has been specified,
+ # check to make sure that both exist and that the
+ # app has permission to read them.
+ if opts.server_cert or opts.server_key:
+ for attr in ("server_cert", "server_key"):
+ attr_name = attr.replace("_", "-")
+ f = getattr(opts, attr)
+ if f == "":
+ log.error("parameter %s must have a value" % \
+ attr_name)
+ return False
+
+ if not os.path.isfile(f):
+ log.error("%s is not a file." % f)
+ return False
+
+ try:
+ open(f, "r")
+ except Exception, e:
+ log.error("Exception reading %s, %s" % (attr_name, e))
+ return False
+ return True
+
def adjust_return(passed_init, ret):
# Shift non-zer0 return codes left 1 bit
# and OR in whether or not init passed
@@ -114,6 +138,9 @@
class ArgError(Exception):
pass
+ class CertificateError(Exception):
+ pass
+
try:
cumin = None
@@ -124,6 +151,8 @@
# Add additional parameters for web
parser.add_option("--host")
parser.add_option("--port", type=int)
+ parser.add_option("--server-cert")
+ parser.add_option("--server-key")
parser.add_option("--section", default="web")
parser.add_option("--daemon", action="store_true",
default=False)
@@ -145,6 +174,9 @@
values.log_max_mb,
values.log_max_archives)
+ if not check_cert_files(opts):
+ raise CertificateError
+
if len(args) != 0:
log.error("Extra arguments:" + "".join([" "+arg
for arg in args]))
raise ArgError
@@ -152,7 +184,9 @@
broker_uris = [x.strip() for x in opts.brokers.split(",")]
authmech = [x.strip() for x in values.auth.split(";")]
cumin = Cumin(config.get_home(), broker_uris, opts.database,
- opts.host, opts.port, values.persona, authmech)
+ opts.host, opts.port,
+ opts.server_cert, opts.server_key,
+ values.persona, authmech)
# If the mech_list was set explicitly, honor it.
# Otherwise Cumin will default based on whether or not
@@ -231,6 +265,11 @@
log.info("Run 'cumin-admin upgrade-schema' as root")
return_code = CuminErrors.SCHEMA_VER_ERROR
+ except CertificateError:
+ log.error("Server certificate or key file is not a valid file "\
+ "or is unreadable")
+ return_code = CuminErrors.CERTIFICATE_ERROR
+
except:
traceback.print_exc()
return_code = CuminErrors.UNHANDLED_ERROR
Modified: trunk/cumin/etc/cumin.conf
===================================================================
--- trunk/cumin/etc/cumin.conf 2012-05-10 15:14:01 UTC (rev 5371)
+++ trunk/cumin/etc/cumin.conf 2012-05-10 20:44:07 UTC (rev 5372)
@@ -105,6 +105,8 @@
# log-file: $CUMIN_HOME/log/web.log
# host: localhost ('0.0.0.0' binds to all local interfaces)
# port: 45672
+# server-cert:
+# server-key:
# operator-email: [none]
# update-interval: 10
# max-qmf-table-sort: 1000
@@ -280,6 +282,18 @@
## [web]
+## server-cert:
+## This is a server certificate file in PEM format.
+## If server-cert and server-key are both set and valid,
+## Cumin will use ssl. The scheme in the Cumin URL will
+## be "https://" instead of "http://".
+
+## server-key:
+## This is a key file in PEM format that corresponds to
+## the server-cert. If server-cert and server-key are both
+## set and valid, Cumin will use ssl. The scheme in the
+## Cumin URL will be "https://" instead of "http://".
+
## persona: grid
## Controls content of the top level page.
## Valid values are "default", "grid", and "messaging".
Modified: trunk/cumin/python/cumin/config.py
===================================================================
--- trunk/cumin/python/cumin/config.py 2012-05-10 15:14:01 UTC (rev 5371)
+++ trunk/cumin/python/cumin/config.py 2012-05-10 20:44:07 UTC (rev 5372)
@@ -182,6 +182,12 @@
param = ConfigParameter(self, "aviary-query-servers", str)
param.default = "http://localhost:9091"
+ param = ConfigParameter(self, "server-cert", str)
+ param.default = ""
+
+ param = ConfigParameter(self, "server-key", str)
+ param.default = ""
+
param = ConfigParameter(self, "aviary-locator", str)
param.default = ""
Modified: trunk/cumin/python/cumin/errors.py
===================================================================
--- trunk/cumin/python/cumin/errors.py 2012-05-10 15:14:01 UTC (rev 5371)
+++ trunk/cumin/python/cumin/errors.py 2012-05-10 20:44:07 UTC (rev 5372)
@@ -8,6 +8,7 @@
SCHEMA_ERROR = 4
SCHEMA_VER_ERROR = 5
WEB_SERVER_ERROR = 6
+ CERTIFICATE_ERROR = 7
errors = \
{NO_ERROR: ("no error", "normal operation"),
@@ -28,7 +29,10 @@
"run 'cumin-admin upgrade-schema' as root"),
WEB_SERVER_ERROR: \
("web server error",
- "web server process has exited")
+ "web server process has exited"),
+ CERTIFICATE_ERROR: \
+ ("certificate error",
+ "certificate or key file is not a valid file or is unreadable")
}
@classmethod
Modified: trunk/cumin/python/cumin/main.py
===================================================================
--- trunk/cumin/python/cumin/main.py 2012-05-10 15:14:01 UTC (rev 5371)
+++ trunk/cumin/python/cumin/main.py 2012-05-10 20:44:07 UTC (rev 5372)
@@ -33,7 +33,9 @@
class Cumin(Application):
def __init__(self, home, broker_uris, database_dsn,
- host="localhost", port=45672, persona="default",
+ host="localhost", port=45672,
+ server_cert="", server_key="",
+ persona="default",
authmech=["internal"]):
super(Cumin, self).__init__()
@@ -51,7 +53,7 @@
self.session = CuminSession(self, broker_uris)
self.database = CuminDatabase(self, database_dsn)
- self.server = CuminServer(self, host, port)
+ self.server = CuminServer(self, host, port, server_cert, server_key)
self.admin = CuminAdmin(self)
self.add_resource_dir(os.path.join(self.home, "resources-wooly"))
Modified: trunk/cumin/python/cumin/server.py
===================================================================
--- trunk/cumin/python/cumin/server.py 2012-05-10 15:14:01 UTC (rev 5371)
+++ trunk/cumin/python/cumin/server.py 2012-05-10 20:44:07 UTC (rev 5372)
@@ -3,5 +3,12 @@
from wooly.server import WebServer
class CuminServer(WebServer):
+ def __init__(self, app, host, port, server_cert="",
server_key=""):
+
+ # Elements of WebServer will look for the cert/key fields
+ self.server_cert = server_cert
+ self.server_key = server_key
+ super(CuminServer, self).__init__(app, host, port)
+
def authorized(self, session):
return True
Modified: trunk/wooly/python/wooly/server.py
===================================================================
--- trunk/wooly/python/wooly/server.py 2012-05-10 15:14:01 UTC (rev 5371)
+++ trunk/wooly/python/wooly/server.py 2012-05-10 20:44:07 UTC (rev 5372)
@@ -223,7 +223,34 @@
request_queue_size=32,
numthreads=32,
max=32)
+
+ if self.server.server_cert and self.server.server_key:
+ ssl_adapter = None
+ # Try the Python ssl module solution first
+ try:
+ from wsgiserver.ssl_builtin import BuiltinSSLAdapter
+ ssl_adapter = BuiltinSSLAdapter(self.server.server_cert,
+ self.server.server_key)
+ log.info("Webserver: ssl enabled via the Python ssl module.")
+ except:
+ pass
+
+ if ssl_adapter is None:
+ try:
+ from wsgiserver.ssl_pyopenssl import pyOpenSSLAdapter
+ ssl_adapter = pyOpenSSLAdapter(self.server.server_cert,
+ self.server.server_key)
+ log.info("Webserver: ssl enabled via the pyOpenSSL
module.")
+ except:
+ pass
+
+ if ssl_adapter is None:
+ log.warn("Webserver: SSL was requested, but imports failed "
+ "for SSL implementations. Running with http only.")
+ else:
+ self.wsgi_server.ssl_adapter = ssl_adapter
+
self.wsgi_server.environ["wsgi.version"] = (1, 1)
def run(self):
Modified: trunk/wooly/python/wooly/wsgiserver/ssl_builtin.py
===================================================================
--- trunk/wooly/python/wooly/wsgiserver/ssl_builtin.py 2012-05-10 15:14:01 UTC (rev 5371)
+++ trunk/wooly/python/wooly/wsgiserver/ssl_builtin.py 2012-05-10 20:44:07 UTC (rev 5372)
@@ -14,7 +14,7 @@
except ImportError:
ssl = None
-from cherrypy import wsgiserver
+from wooly import wsgiserver
class BuiltinSSLAdapter(wsgiserver.SSLAdapter):
Modified: trunk/wooly/python/wooly/wsgiserver/ssl_pyopenssl.py
===================================================================
--- trunk/wooly/python/wooly/wsgiserver/ssl_pyopenssl.py 2012-05-10 15:14:01 UTC (rev
5371)
+++ trunk/wooly/python/wooly/wsgiserver/ssl_pyopenssl.py 2012-05-10 20:44:07 UTC (rev
5372)
@@ -34,7 +34,7 @@
import threading
import time
-from cherrypy import wsgiserver
+from wooly import wsgiserver
try:
from OpenSSL import SSL