diff --git a/etc/sahara/sahara.conf.sample b/etc/sahara/sahara.conf.sample index 5bbd539f06..29ce6aa18f 100644 --- a/etc/sahara/sahara.conf.sample +++ b/etc/sahara/sahara.conf.sample @@ -82,7 +82,7 @@ #logging_exception_prefix = %(asctime)s.%(msecs)03d %(process)d TRACE %(name)s %(instance)s # List of logger=LEVEL pairs. (list value) -#default_log_levels = amqplib=WARN,qpid.messaging=INFO,stevedore=INFO,eventlet.wsgi.server=WARN,sqlalchemy=WARN,boto=WARN,suds=INFO,keystone=INFO,paramiko=WARN,requests=WARN,iso8601=WARN +#default_log_levels = amqp=WARN,amqplib=WARN,boto=WARN,qpid=WARN,sqlalchemy=WARN,suds=INFO,oslo.messaging=INFO,iso8601=WARN,requests.packages.urllib3.connectionpool=WARN,urllib3.connectionpool=WARN,websocket=WARN,keystonemiddleware=WARN,routes.middleware=WARN,stevedore=WARN # Enables or disables publication of error events. (boolean value) #publish_errors = false @@ -914,6 +914,25 @@ #allow_insecure_clients = false +[ssl] + +# +# From ssl.config +# + +# CA certificate file to use to verify connecting clients. (string +# value) +#ca_file = + +# Certificate file to use when starting the server securely. (string +# value) +#cert_file = + +# Private key file to use when starting the server securely. (string +# value) +#key_file = + + [swift] # diff --git a/openstack-common.conf b/openstack-common.conf index d0844d8cde..e24aa0e726 100644 --- a/openstack-common.conf +++ b/openstack-common.conf @@ -4,6 +4,7 @@ module=log module=periodic_task module=policy +module=sslutils module=threadgroup module=uuidutils diff --git a/sahara/cli/sahara_all.py b/sahara/cli/sahara_all.py index cd3405db89..55b5498de2 100644 --- a/sahara/cli/sahara_all.py +++ b/sahara/cli/sahara_all.py @@ -21,8 +21,6 @@ patches.patch_all() import os import sys -import eventlet -from eventlet import wsgi from oslo import i18n @@ -59,6 +57,4 @@ def main(): server.setup_sahara_engine() server.setup_auth_policy() - from oslo.config import cfg - wsgi.server(eventlet.listen((cfg.CONF.host, cfg.CONF.port), backlog=500), - app, log=logging.WritableLogger(LOG), debug=False) + server.start_server(app) diff --git a/sahara/cli/sahara_api.py b/sahara/cli/sahara_api.py index afc4414fb5..158b8009f2 100644 --- a/sahara/cli/sahara_api.py +++ b/sahara/cli/sahara_api.py @@ -21,8 +21,6 @@ patches.patch_all() import os import sys -import eventlet -from eventlet import wsgi from oslo import i18n @@ -58,6 +56,4 @@ def main(): server.setup_sahara_api('distributed') server.setup_auth_policy() - from oslo.config import cfg - wsgi.server(eventlet.listen((cfg.CONF.host, cfg.CONF.port), backlog=500), - app, log=logging.WritableLogger(LOG), debug=False) + server.start_server(app) diff --git a/sahara/main.py b/sahara/main.py index 9308a0c0ab..4234bbed98 100644 --- a/sahara/main.py +++ b/sahara/main.py @@ -15,6 +15,8 @@ import os +import eventlet +from eventlet import wsgi import flask from oslo.config import cfg import six @@ -31,6 +33,7 @@ from sahara import context from sahara.i18n import _LI from sahara.i18n import _LW from sahara.openstack.common import log +from sahara.openstack.common import sslutils from sahara.plugins import base as plugins_base from sahara.service import api as service_api from sahara.service.edp import api as edp_api @@ -191,3 +194,12 @@ def _get_ops_driver(driver_name): LOG.info(_LI("Loading '%s' ops"), driver_name) return _load_driver('sahara.run.mode', driver_name) + + +def start_server(app): + sock = eventlet.listen((cfg.CONF.host, cfg.CONF.port), backlog=500) + if sslutils.is_enabled(): + LOG.info(_LI("Using HTTPS for port %s"), cfg.CONF.port) + sock = sslutils.wrap(sock) + + wsgi.server(sock, app, log=log.WritableLogger(LOG), debug=False) diff --git a/sahara/openstack/common/sslutils.py b/sahara/openstack/common/sslutils.py new file mode 100644 index 0000000000..d3628c3dda --- /dev/null +++ b/sahara/openstack/common/sslutils.py @@ -0,0 +1,101 @@ +# Copyright 2013 IBM Corp. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +import copy +import os +import ssl + +from oslo.config import cfg + +from sahara.openstack.common._i18n import _ + + +ssl_opts = [ + cfg.StrOpt('ca_file', + help="CA certificate file to use to verify " + "connecting clients."), + cfg.StrOpt('cert_file', + help="Certificate file to use when starting " + "the server securely."), + cfg.StrOpt('key_file', + help="Private key file to use when starting " + "the server securely."), +] + +CONF = cfg.CONF +config_section = 'ssl' +CONF.register_opts(ssl_opts, config_section) + + +def list_opts(): + """Entry point for oslo.config-generator.""" + return [(config_section, copy.deepcopy(ssl_opts))] + + +def is_enabled(): + cert_file = CONF.ssl.cert_file + key_file = CONF.ssl.key_file + ca_file = CONF.ssl.ca_file + use_ssl = cert_file or key_file + + if cert_file and not os.path.exists(cert_file): + raise RuntimeError(_("Unable to find cert_file : %s") % cert_file) + + if ca_file and not os.path.exists(ca_file): + raise RuntimeError(_("Unable to find ca_file : %s") % ca_file) + + if key_file and not os.path.exists(key_file): + raise RuntimeError(_("Unable to find key_file : %s") % key_file) + + if use_ssl and (not cert_file or not key_file): + raise RuntimeError(_("When running server in SSL mode, you must " + "specify both a cert_file and key_file " + "option value in your configuration file")) + + return use_ssl + + +def wrap(sock): + ssl_kwargs = { + 'server_side': True, + 'certfile': CONF.ssl.cert_file, + 'keyfile': CONF.ssl.key_file, + 'cert_reqs': ssl.CERT_NONE, + } + + if CONF.ssl.ca_file: + ssl_kwargs['ca_certs'] = CONF.ssl.ca_file + ssl_kwargs['cert_reqs'] = ssl.CERT_REQUIRED + + return ssl.wrap_socket(sock, **ssl_kwargs) + + +_SSL_PROTOCOLS = { + "tlsv1": ssl.PROTOCOL_TLSv1, + "sslv23": ssl.PROTOCOL_SSLv23, + "sslv3": ssl.PROTOCOL_SSLv3 +} + +try: + _SSL_PROTOCOLS["sslv2"] = ssl.PROTOCOL_SSLv2 +except AttributeError: + pass + + +def validate_ssl_version(version): + key = version.lower() + try: + return _SSL_PROTOCOLS[key] + except KeyError: + raise RuntimeError(_("Invalid SSL version : %s") % version) diff --git a/setup.cfg b/setup.cfg index 33bd002a23..ee2a0fdcb3 100644 --- a/setup.cfg +++ b/setup.cfg @@ -61,6 +61,7 @@ oslo.config.opts = log.config = sahara.openstack.common.log:list_opts periodic.config = sahara.openstack.common.periodic_task:list_opts policy.config = sahara.openstack.common.policy:list_opts + ssl.config = sahara.openstack.common.sslutils:list_opts [build_sphinx] all_files = 1 diff --git a/tools/config/config-generator.sahara.conf b/tools/config/config-generator.sahara.conf index 7b89f3acc3..f227a59cbf 100644 --- a/tools/config/config-generator.sahara.conf +++ b/tools/config/config-generator.sahara.conf @@ -7,3 +7,4 @@ namespace = keystonemiddleware.auth_token namespace = log.config namespace = periodic.config namespace = policy.config +namespace = ssl.config