Merge "Remove eventlet support"

This commit is contained in:
Jenkins 2016-04-19 07:29:41 +00:00 committed by Gerrit Code Review
commit 23bb657369
30 changed files with 82 additions and 1340 deletions

View File

@ -9,7 +9,6 @@ namespace = oslo.messaging
namespace = oslo.policy namespace = oslo.policy
namespace = oslo.db namespace = oslo.db
namespace = oslo.middleware namespace = oslo.middleware
namespace = oslo.service.service
namespace = osprofiler namespace = osprofiler
# We don't use oslo.concurrency config options in # We don't use oslo.concurrency config options in
# keystone now, just in case it slips through unnoticed. # keystone now, just in case it slips through unnoticed.

View File

@ -111,9 +111,7 @@ modindex_common_prefix = ['keystone.']
man_pages = [ man_pages = [
('man/keystone-manage', 'keystone-manage', u'Keystone Management Utility', ('man/keystone-manage', 'keystone-manage', u'Keystone Management Utility',
[u'OpenStack'], 1), [u'OpenStack'], 1)
('man/keystone-all', 'keystone-all', u'Keystone Startup Command',
[u'OpenStack'], 1),
] ]

View File

@ -22,7 +22,6 @@ Configuring Keystone
:maxdepth: 1 :maxdepth: 1
man/keystone-manage man/keystone-manage
man/keystone-all
Once Keystone is installed, it is configured via a primary configuration file Once Keystone is installed, it is configured via a primary configuration file
(``etc/keystone.conf``), a PasteDeploy configuration file (``etc/keystone.conf``), a PasteDeploy configuration file
@ -45,48 +44,6 @@ To make the above change persistent,
``net.ipv4.ip_local_reserved_ports = 35357`` should be added to ``net.ipv4.ip_local_reserved_ports = 35357`` should be added to
``/etc/sysctl.conf`` or to ``/etc/sysctl.d/keystone.conf``. ``/etc/sysctl.conf`` or to ``/etc/sysctl.d/keystone.conf``.
Starting and Stopping Keystone under Eventlet
=============================================
.. WARNING::
Running keystone under eventlet has been deprecated as of the Kilo release.
Support for utilizing eventlet will be removed as of the M-release. The
recommended deployment is to run keystone in a WSGI server such as Apache
httpd with ``mod_wsgi``.
Keystone can be run using either its built-in eventlet server or it can be run
embedded in a web server. While the eventlet server is convenient and easy to
use, it's lacking in security features that have been developed into Internet-
based web servers over the years. As such, running the eventlet server as
described in this section is not recommended.
Start Keystone services using the command:
.. code-block:: bash
$ keystone-all
Invoking this command starts up two ``wsgi.Server`` instances, ``admin`` (the
administration API) and ``main`` (the primary/public API interface). Both
services are configured to run in a single process.
.. NOTE::
The separation into ``admin`` and ``main`` interfaces is a historical
anomaly. The new V3 API provides the same interface on both the admin and
main interfaces (this can be configured in ``keystone-paste.ini``, but the
default is to have both the same). The V2.0 API provides a limited public
API (getting and validating tokens) on ``main``, and an administrative API
(which can include creating users and such) on the ``admin`` interface.
Stop the process using ``Control-C``.
.. NOTE::
If you have not already configured Keystone, it may not start as expected.
Configuration Files Configuration Files
=================== ===================
@ -115,8 +72,6 @@ The primary configuration file is organized into the following sections:
* ``[credential]`` - Credential system driver configuration * ``[credential]`` - Credential system driver configuration
* ``[endpoint_filter]`` - Endpoint filtering configuration * ``[endpoint_filter]`` - Endpoint filtering configuration
* ``[endpoint_policy]`` - Endpoint policy configuration * ``[endpoint_policy]`` - Endpoint policy configuration
* ``[eventlet_server]`` - Eventlet server configuration
* ``[eventlet_server_ssl]`` - Eventlet server SSL configuration
* ``[federation]`` - Federation driver configuration * ``[federation]`` - Federation driver configuration
* ``[identity]`` - Identity system driver configuration * ``[identity]`` - Identity system driver configuration
* ``[identity_mapping]`` - Identity mapping system driver configuration * ``[identity_mapping]`` - Identity mapping system driver configuration
@ -977,32 +932,19 @@ certificates are just provided as an example.
Configuration Configuration
^^^^^^^^^^^^^ ^^^^^^^^^^^^^
To enable SSL modify the ``etc/keystone.conf`` file under the ``[ssl]`` and To enable SSL a deployment should configure a web server (such as Apache) to
``[eventlet_server_ssl]`` sections. The following is an SSL configuration use SSL. Keystone is able to generate SSL certificates by modifying the
example using the included sample certificates: ``[ssl]`` section in the ``etc/keystone.conf`` file. The following is an SSL
configuration example using the included sample certificates:
.. code-block:: ini .. code-block:: ini
[eventlet_server_ssl]
enable = True
certfile = <path to keystone.pem>
keyfile = <path to keystonekey.pem>
ca_certs = <path to ca.pem>
cert_required = False
[ssl] [ssl]
ca_key = <path to cakey.pem> ca_key = <path to cakey.pem>
key_size = 1024 key_size = 1024
valid_days=3650 valid_days=3650
cert_subject=/C=US/ST=Unset/L=Unset/O=Unset/CN=localhost cert_subject=/C=US/ST=Unset/L=Unset/O=Unset/CN=localhost
* ``enable``: True enables SSL. Defaults to False.
* ``certfile``: Path to Keystone public certificate file.
* ``keyfile``: Path to Keystone private certificate file. If the private key is
included in the certfile, the keyfile may be omitted.
* ``ca_certs``: Path to CA trust chain.
* ``cert_required``: Requires client certificate. Defaults to False.
When generating SSL certificates the following values are read When generating SSL certificates the following values are read
* ``key_size``: Key size to create. Defaults to 1024. * ``key_size``: Key size to create. Defaults to 1024.

View File

@ -222,6 +222,5 @@ HTTP/1.1 Chunked Encoding
Running Keystone under HTTPD in the recommended (and tested) configuration does not support Running Keystone under HTTPD in the recommended (and tested) configuration does not support
the use of ``Transfer-Encoding: chunked``. This is due to a limitation with the WSGI spec the use of ``Transfer-Encoding: chunked``. This is due to a limitation with the WSGI spec
and the implementation used by ``mod_wsgi``. Support for chunked encoding under ``eventlet`` and the implementation used by ``mod_wsgi``. It is recommended that all
may or may not continue. It is recommended that all clients assume Keystone will not support clients assume Keystone will not support ``Transfer-Encoding: chunked``.
``Transfer-Encoding: chunked``.

View File

@ -78,7 +78,6 @@ Man Pages
.. toctree:: .. toctree::
:maxdepth: 1 :maxdepth: 1
man/keystone-all
man/keystone-manage man/keystone-manage
Developers Documentation Developers Documentation

View File

@ -1,112 +0,0 @@
============
keystone-all
============
------------------------
Keystone Startup Command
------------------------
:Author: openstack@lists.openstack.org
:Date: 2015-10-15
:Copyright: OpenStack Foundation
:Version: 8.0.0
:Manual section: 1
:Manual group: cloud computing
SYNOPSIS
========
::
keystone-all [-h] [--config-dir DIR] [--config-file PATH] [--debug]
[--log-config-append PATH] [--log-date-format DATE_FORMAT]
[--log-dir LOG_DIR] [--log-file PATH]
[--log-format FORMAT] [--nodebug] [--nostandard-threads]
[--nouse-syslog] [--nouse-syslog-rfc-format] [--noverbose]
[--pydev-debug-host PYDEV_DEBUG_HOST]
[--pydev-debug-port PYDEV_DEBUG_PORT] [--standard-threads]
[--syslog-log-facility SYSLOG_LOG_FACILITY] [--use-syslog]
[--use-syslog-rfc-format] [--verbose] [--version]
DESCRIPTION
===========
keystone-all starts both the service and administrative APIs in a single
process to provide catalog, authorization, and authentication services for
OpenStack.
OPTIONS
=======
-h, --help show this help message and exit
--config-dir DIR Path to a config directory to pull \*.conf files from.
This file set is sorted, so as to provide a
predictable parse order if individual options are
over-ridden. The set is parsed after the file(s)
specified via previous --config-file, arguments hence
over-ridden options in the directory take precedence.
--config-file PATH Path to a config file to use. Multiple config files
can be specified, with values in later files taking
precedence. The default files used are: None.
--debug, -d Print debugging output (set logging level to DEBUG
instead of default WARNING level).
--log-config-append PATH, --log_config PATH
The name of a logging configuration file. This file is
appended to any existing logging configuration files.
For details about logging configuration files, see the
Python logging module documentation.
--log-date-format DATE_FORMAT
Format string for %(asctime)s in log records. Default:
None .
--log-dir LOG_DIR, --logdir LOG_DIR
(Optional) The base directory used for relative --log-
file paths.
--log-file PATH, --logfile PATH
(Optional) Name of log file to output to. If no
default is set, logging will go to stdout.
--log-format FORMAT DEPRECATED. A logging.Formatter log message format
string which may use any of the available
logging.LogRecord attributes. This option is
deprecated. Please use logging_context_format_string
and logging_default_format_string instead.
--nodebug The inverse of --debug
--nostandard-threads The inverse of --standard-threads
--nouse-syslog The inverse of --use-syslog
--nouse-syslog-rfc-format
The inverse of --use-syslog-rfc-format
--noverbose The inverse of --verbose
--pydev-debug-host PYDEV_DEBUG_HOST
Host to connect to for remote debugger.
--pydev-debug-port PYDEV_DEBUG_PORT
Port to connect to for remote debugger.
--standard-threads Do not monkey-patch threading system modules.
--syslog-log-facility SYSLOG_LOG_FACILITY
Syslog facility to receive log lines.
--use-syslog Use syslog for logging. Existing syslog format is
DEPRECATED during I, and will change in J to honor
RFC5424.
--use-syslog-rfc-format
(Optional) Enables or disables syslog rfc5424 format
for logging. If enabled, prefixes the MSG part of the
syslog message with APP-NAME (RFC5424). The format
without the APP-NAME is deprecated in I, and will be
removed in J.
--verbose, -v Print more verbose output (set logging level to INFO
instead of default WARNING level).
--version show program's version number and exit
FILES
=====
None
SEE ALSO
========
* `OpenStack Keystone <http://keystone.openstack.org>`__
SOURCE
======
* Keystone source is managed in Gerrit git `Keystone <https://git.openstack.org/cgit/openstack/keystone>`__
* Keystone bugs are managed at Launchpad `Keystone <https://bugs.launchpad.net/keystone>`__

View File

@ -1,39 +0,0 @@
#!/usr/bin/env python
# Copyright 2013 OpenStack Foundation
#
# 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 os
import sys
# If ../../keystone/__init__.py exists, add ../../ to Python search path, so
# that it will override what happens to be installed in
# /usr/(local/)lib/python...
possible_topdir = os.path.normpath(os.path.join(os.path.abspath(__file__),
os.pardir,
os.pardir,
os.pardir))
if os.path.exists(os.path.join(possible_topdir,
'keystone',
'__init__.py')):
sys.path.insert(0, possible_topdir)
from keystone.server import eventlet as eventlet_server
# entry point.
def main():
eventlet_server.run(possible_topdir)

View File

@ -30,13 +30,10 @@ if os.path.exists(os.path.join(possible_topdir,
sys.path.insert(0, possible_topdir) sys.path.insert(0, possible_topdir)
from keystone.cmd import cli from keystone.cmd import cli
from keystone.common import environment
# entry point. # entry point.
def main(): def main():
environment.use_stdlib()
dev_conf = os.path.join(possible_topdir, dev_conf = os.path.join(possible_topdir,
'etc', 'etc',
'keystone.conf') 'keystone.conf')

View File

@ -49,6 +49,11 @@ _DEPRECATE_DII_MSG = ('The option to set domain_id_immutable to false '
'has been deprecated in the M release and will ' 'has been deprecated in the M release and will '
'be removed in the O release.') 'be removed in the O release.')
_DEPRECATE_EVENTLET_MSG = ('Support for running keystone under eventlet has '
'been removed in the N release. These options '
'remain for backwards compatibility because they '
'are used for URL substitutions.')
FILE_OPTIONS = { FILE_OPTIONS = {
None: [ None: [
cfg.StrOpt('admin_token', secret=True, default=None, cfg.StrOpt('admin_token', secret=True, default=None,
@ -999,20 +1004,6 @@ FILE_OPTIONS = {
'assertions.'), 'assertions.'),
], ],
'eventlet_server': [ 'eventlet_server': [
cfg.IntOpt('public_workers',
deprecated_name='public_workers',
deprecated_group='DEFAULT',
deprecated_for_removal=True,
help='The number of worker processes to serve the public '
'eventlet application. Defaults to number of CPUs '
'(minimum of 2).'),
cfg.IntOpt('admin_workers',
deprecated_name='admin_workers',
deprecated_group='DEFAULT',
deprecated_for_removal=True,
help='The number of worker processes to serve the admin '
'eventlet application. Defaults to number of CPUs '
'(minimum of 2).'),
cfg.StrOpt('public_bind_host', cfg.StrOpt('public_bind_host',
default='0.0.0.0', # nosec : Bind to all interfaces by default='0.0.0.0', # nosec : Bind to all interfaces by
# default for backwards compatibility. # default for backwards compatibility.
@ -1021,12 +1012,14 @@ FILE_OPTIONS = {
cfg.DeprecatedOpt('public_bind_host', cfg.DeprecatedOpt('public_bind_host',
group='DEFAULT'), ], group='DEFAULT'), ],
deprecated_for_removal=True, deprecated_for_removal=True,
deprecated_reason=_DEPRECATE_EVENTLET_MSG,
help='The IP address of the network interface for the ' help='The IP address of the network interface for the '
'public service to listen on.'), 'public service to listen on.'),
cfg.PortOpt('public_port', default=5000, cfg.PortOpt('public_port', default=5000,
deprecated_name='public_port', deprecated_name='public_port',
deprecated_group='DEFAULT', deprecated_group='DEFAULT',
deprecated_for_removal=True, deprecated_for_removal=True,
deprecated_reason=_DEPRECATE_EVENTLET_MSG,
help='The port number which the public service listens ' help='The port number which the public service listens '
'on.'), 'on.'),
cfg.StrOpt('admin_bind_host', cfg.StrOpt('admin_bind_host',
@ -1037,6 +1030,7 @@ FILE_OPTIONS = {
cfg.DeprecatedOpt('admin_bind_host', cfg.DeprecatedOpt('admin_bind_host',
group='DEFAULT')], group='DEFAULT')],
deprecated_for_removal=True, deprecated_for_removal=True,
deprecated_reason=_DEPRECATE_EVENTLET_MSG,
help='The IP address of the network interface for the ' help='The IP address of the network interface for the '
'admin service to listen on.'), 'admin service to listen on.'),
cfg.PortOpt('admin_port', default=35357, cfg.PortOpt('admin_port', default=35357,
@ -1045,60 +1039,6 @@ FILE_OPTIONS = {
deprecated_for_removal=True, deprecated_for_removal=True,
help='The port number which the admin service listens ' help='The port number which the admin service listens '
'on.'), 'on.'),
cfg.BoolOpt('wsgi_keep_alive', default=True,
help='If set to false, disables keepalives on the server; '
'all connections will be closed after serving one '
'request.'),
cfg.IntOpt('client_socket_timeout', default=900,
help='Timeout for socket operations on a client '
'connection. If an incoming connection is idle for '
'this number of seconds it will be closed. A value '
'of "0" means wait forever.'),
cfg.BoolOpt('tcp_keepalive', default=False,
deprecated_name='tcp_keepalive',
deprecated_group='DEFAULT',
deprecated_for_removal=True,
help='Set this to true if you want to enable '
'TCP_KEEPALIVE on server sockets, i.e. sockets used '
'by the Keystone wsgi server for client '
'connections.'),
cfg.IntOpt('tcp_keepidle',
default=600,
deprecated_name='tcp_keepidle',
deprecated_group='DEFAULT',
deprecated_for_removal=True,
help='Sets the value of TCP_KEEPIDLE in seconds for each '
'server socket. Only applies if tcp_keepalive is '
'true. Ignored if system does not support it.'),
],
'eventlet_server_ssl': [
cfg.BoolOpt('enable', default=False, deprecated_name='enable',
deprecated_group='ssl',
deprecated_for_removal=True,
help='Toggle for SSL support on the Keystone '
'eventlet servers.'),
cfg.StrOpt('certfile',
default='/etc/keystone/ssl/certs/keystone.pem',
deprecated_name='certfile', deprecated_group='ssl',
deprecated_for_removal=True,
help='Path of the certfile for SSL. For non-production '
'environments, you may be interested in using '
'`keystone-manage ssl_setup` to generate self-signed '
'certificates.'),
cfg.StrOpt('keyfile',
default='/etc/keystone/ssl/private/keystonekey.pem',
deprecated_name='keyfile', deprecated_group='ssl',
deprecated_for_removal=True,
help='Path of the keyfile for SSL.'),
cfg.StrOpt('ca_certs',
default='/etc/keystone/ssl/certs/ca.pem',
deprecated_name='ca_certs', deprecated_group='ssl',
deprecated_for_removal=True,
help='Path of the CA cert file for SSL.'),
cfg.BoolOpt('cert_required', default=False,
deprecated_name='cert_required', deprecated_group='ssl',
deprecated_for_removal=True,
help='Require client certificate.'),
], ],
} }

View File

@ -1,102 +0,0 @@
# Copyright 2013 OpenStack Foundation
#
# 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 functools
import os
from oslo_log import log
LOG = log.getLogger(__name__)
__all__ = ('Server', 'httplib', 'subprocess')
_configured = False
Server = None
httplib = None
subprocess = None
def configure_once(name):
"""Ensure that environment configuration is only run once.
If environment is reconfigured in the same way then it is ignored.
It is an error to attempt to reconfigure environment in a different way.
"""
def decorator(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
global _configured
if _configured:
if _configured == name:
return
else:
raise SystemError("Environment has already been "
"configured as %s" % _configured)
LOG.debug("Environment configured as: %s", name)
_configured = name
return func(*args, **kwargs)
return wrapper
return decorator
@configure_once('eventlet')
def use_eventlet(monkeypatch_thread=None):
global httplib, subprocess, Server
# This must be set before the initial import of eventlet because if
# dnspython is present in your environment then eventlet monkeypatches
# socket.getaddrinfo() with an implementation which doesn't work for IPv6.
os.environ['EVENTLET_NO_GREENDNS'] = 'yes'
import eventlet
from eventlet.green import httplib as _httplib
from eventlet.green import subprocess as _subprocess
from keystone.common.environment import eventlet_server
if monkeypatch_thread is None:
monkeypatch_thread = not os.getenv('STANDARD_THREADS')
# Raise the default from 8192 to accommodate large tokens
eventlet.wsgi.MAX_HEADER_LINE = 16384
# NOTE(ldbragst): Explicitly declare what should be monkey patched and
# what shouldn't. Doing this allows for more readable code when
# understanding Eventlet in Keystone. The following is a complete list
# of what is monkey patched instead of passing all=False and then passing
# module=True to monkey patch a specific module.
eventlet.patcher.monkey_patch(os=False, select=True, socket=True,
thread=monkeypatch_thread, time=True,
psycopg=False, MySQLdb=False)
Server = eventlet_server.Server
httplib = _httplib
subprocess = _subprocess
@configure_once('stdlib')
def use_stdlib():
global httplib, subprocess
import six.moves.http_client as _httplib
import subprocess as _subprocess # nosec : This is used in .federation.idp
# and .common.openssl. See there.
httplib = _httplib
subprocess = _subprocess

View File

@ -1,212 +0,0 @@
# Copyright 2012 OpenStack Foundation
# Copyright 2010 United States Government as represented by the
# Administrator of the National Aeronautics and Space Administration.
# Copyright 2010 OpenStack Foundation
# All Rights Reserved.
#
# 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 errno
import re
import socket
import ssl
import sys
import eventlet
import eventlet.wsgi
import greenlet
from oslo_config import cfg
from oslo_log import log
from oslo_service import service
from keystone.i18n import _LE, _LI
CONF = cfg.CONF
LOG = log.getLogger(__name__)
# The size of a pool that is used to spawn a single green thread in which
# a wsgi server is then started. The size of one is enough, because in case
# of several workers the parent process forks and each child gets a copy
# of a pool, which does not include any greenthread object as the spawn is
# done after the fork.
POOL_SIZE = 1
class EventletFilteringLogger(object):
# NOTE(morganfainberg): This logger is designed to filter out specific
# Tracebacks to limit the amount of data that eventlet can log. In the
# case of broken sockets (EPIPE and ECONNRESET), we are seeing a huge
# volume of data being written to the logs due to ~14 lines+ per traceback.
# The traceback in these cases are, at best, useful for limited debugging
# cases.
def __init__(self, logger, level=log.INFO):
self.logger = logger
self.level = level
self.regex = re.compile(r'errno (%d|%d)' %
(errno.EPIPE, errno.ECONNRESET), re.IGNORECASE)
def write(self, msg):
m = self.regex.search(msg)
if m:
self.logger.log(log.logging.DEBUG, 'Error(%s) writing to socket.',
m.group(1))
else:
self.logger.log(self.level, msg.rstrip())
class Server(service.ServiceBase):
"""Server class to manage multiple WSGI sockets and applications."""
def __init__(self, application, host=None, port=None, keepalive=False,
keepidle=None):
self.application = application
self.host = host or '0.0.0.0' # nosec : Bind to all interfaces by
# default for backwards compatibility.
self.port = port or 0
# Pool for a green thread in which wsgi server will be running
self.pool = eventlet.GreenPool(POOL_SIZE)
self.socket_info = {}
self.greenthread = None
self.do_ssl = False
self.cert_required = False
self.keepalive = keepalive
self.keepidle = keepidle
self.socket = None
def listen(self, key=None, backlog=128):
"""Create and start listening on socket.
Call before forking worker processes.
Raises Exception if this has already been called.
"""
# TODO(dims): eventlet's green dns/socket module does not actually
# support IPv6 in getaddrinfo(). We need to get around this in the
# future or monitor upstream for a fix.
# Please refer below link
# (https://bitbucket.org/eventlet/eventlet/
# src/e0f578180d7d82d2ed3d8a96d520103503c524ec/eventlet/support/
# greendns.py?at=0.12#cl-163)
info = socket.getaddrinfo(self.host,
self.port,
socket.AF_UNSPEC,
socket.SOCK_STREAM)[0]
try:
self.socket = eventlet.listen(info[-1], family=info[0],
backlog=backlog)
except EnvironmentError:
LOG.error(_LE("Could not bind to %(host)s:%(port)s"),
{'host': self.host, 'port': self.port})
raise
LOG.info(_LI('Starting %(arg0)s on %(host)s:%(port)s'),
{'arg0': sys.argv[0],
'host': self.host,
'port': self.port})
def start(self, key=None, backlog=128):
"""Run a WSGI server with the given application."""
if self.socket is None:
self.listen(key=key, backlog=backlog)
dup_socket = self.socket.dup()
if key:
self.socket_info[key] = self.socket.getsockname()
# SSL is enabled
if self.do_ssl:
if self.cert_required:
cert_reqs = ssl.CERT_REQUIRED
else:
cert_reqs = ssl.CERT_NONE
dup_socket = eventlet.wrap_ssl(dup_socket, certfile=self.certfile,
keyfile=self.keyfile,
server_side=True,
cert_reqs=cert_reqs,
ca_certs=self.ca_certs)
# Optionally enable keepalive on the wsgi socket.
if self.keepalive:
dup_socket.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1)
if self.keepidle is not None:
if hasattr(socket, 'TCP_KEEPIDLE'):
dup_socket.setsockopt(socket.IPPROTO_TCP,
socket.TCP_KEEPIDLE,
self.keepidle)
else:
LOG.warning("System does not support TCP_KEEPIDLE but "
"tcp_keepidle has been set. Ignoring.")
self.greenthread = self.pool.spawn(self._run,
self.application,
dup_socket)
def set_ssl(self, certfile, keyfile=None, ca_certs=None,
cert_required=True):
self.certfile = certfile
self.keyfile = keyfile
self.ca_certs = ca_certs
self.cert_required = cert_required
self.do_ssl = True
def stop(self):
if self.greenthread is not None:
self.greenthread.kill()
def wait(self):
"""Wait until all servers have completed running."""
try:
self.pool.waitall()
except KeyboardInterrupt: # nosec
# If CTRL-C, just break out of the loop.
pass
except greenlet.GreenletExit: # nosec
# If exiting, break out of the loop.
pass
def reset(self):
"""Required by the service interface.
The service interface is used by the launcher when receiving a
SIGHUP. The service interface is defined in
oslo_service.service.Service.
Keystone does not need to do anything here.
"""
pass
def _run(self, application, socket):
"""Start a WSGI server with a new green thread pool."""
logger = log.getLogger('eventlet.wsgi.server')
# NOTE(dolph): [eventlet_server] client_socket_timeout is required to
# be an integer in keystone.conf, but in order to make
# eventlet.wsgi.server() wait forever, we pass None instead of 0.
socket_timeout = CONF.eventlet_server.client_socket_timeout or None
try:
eventlet.wsgi.server(
socket, application, log=EventletFilteringLogger(logger),
debug=False, keepalive=CONF.eventlet_server.wsgi_keep_alive,
socket_timeout=socket_timeout)
except greenlet.GreenletExit: # nosec
# Wait until all servers have completed running
pass
except Exception:
LOG.exception(_LE('Server error'))
raise

View File

@ -14,11 +14,11 @@
# #
import os import os
import subprocess # nosec : see comments in the code below
from oslo_config import cfg from oslo_config import cfg
from oslo_log import log from oslo_log import log
from keystone.common import environment
from keystone.common import utils from keystone.common import utils
from keystone.i18n import _LI, _LE, _LW from keystone.i18n import _LI, _LE, _LW
@ -42,22 +42,22 @@ class BaseCertificateConfigure(object):
""" """
def __init__(self, conf_obj, server_conf_obj, keystone_user, def __init__(self, conf_obj, keystone_user,
keystone_group, rebuild, **kwargs): keystone_group, rebuild, **kwargs):
self.conf_dir = os.path.dirname(server_conf_obj.ca_certs) self.conf_dir = os.path.dirname(conf_obj.ca_certs)
self.use_keystone_user = keystone_user self.use_keystone_user = keystone_user
self.use_keystone_group = keystone_group self.use_keystone_group = keystone_group
self.rebuild = rebuild self.rebuild = rebuild
self.ssl_config_file_name = os.path.join(self.conf_dir, "openssl.conf") self.ssl_config_file_name = os.path.join(self.conf_dir, "openssl.conf")
self.request_file_name = os.path.join(self.conf_dir, "req.pem") self.request_file_name = os.path.join(self.conf_dir, "req.pem")
self.ssl_dictionary = {'conf_dir': self.conf_dir, self.ssl_dictionary = {'conf_dir': self.conf_dir,
'ca_cert': server_conf_obj.ca_certs, 'ca_cert': conf_obj.ca_certs,
'default_md': 'default', 'default_md': 'default',
'ssl_config': self.ssl_config_file_name, 'ssl_config': self.ssl_config_file_name,
'ca_private_key': conf_obj.ca_key, 'ca_private_key': conf_obj.ca_key,
'request_file': self.request_file_name, 'request_file': self.request_file_name,
'signing_key': server_conf_obj.keyfile, 'signing_key': conf_obj.keyfile,
'signing_cert': server_conf_obj.certfile, 'signing_cert': conf_obj.certfile,
'key_size': int(conf_obj.key_size), 'key_size': int(conf_obj.key_size),
'valid_days': int(conf_obj.valid_days), 'valid_days': int(conf_obj.valid_days),
'cert_subject': conf_obj.cert_subject} 'cert_subject': conf_obj.cert_subject}
@ -65,12 +65,12 @@ class BaseCertificateConfigure(object):
try: try:
# OpenSSL 1.0 and newer support default_md = default, # OpenSSL 1.0 and newer support default_md = default,
# older versions do not # older versions do not
openssl_ver = environment.subprocess.check_output( # the arguments openssl_ver = subprocess.check_output( # nosec : the arguments
# are hardcoded and just check the openssl version # are hardcoded and just check the openssl version
['openssl', 'version']) ['openssl', 'version'])
if b'OpenSSL 0.' in openssl_ver: if b'OpenSSL 0.' in openssl_ver:
self.ssl_dictionary['default_md'] = 'sha1' self.ssl_dictionary['default_md'] = 'sha1'
except environment.subprocess.CalledProcessError: except subprocess.CalledProcessError:
LOG.warning(_LW('Failed to invoke ``openssl version``, ' LOG.warning(_LW('Failed to invoke ``openssl version``, '
'assuming is v1.0 or newer')) 'assuming is v1.0 or newer'))
self.ssl_dictionary.update(kwargs) self.ssl_dictionary.update(kwargs)
@ -81,12 +81,12 @@ class BaseCertificateConfigure(object):
try: try:
# NOTE(shaleh): use check_output instead of the simpler # NOTE(shaleh): use check_output instead of the simpler
# `check_call()` in order to log any output from an error. # `check_call()` in order to log any output from an error.
environment.subprocess.check_output( # the arguments being passed subprocess.check_output( # nosec : the arguments being passed
# in are defined in this file and trusted to build CAs, keys # in are defined in this file and trusted to build CAs, keys
# and certs # and certs
to_exec, to_exec,
stderr=environment.subprocess.STDOUT) stderr=subprocess.STDOUT)
except environment.subprocess.CalledProcessError as e: except subprocess.CalledProcessError as e:
LOG.error(_LE('Command %(to_exec)s exited with %(retcode)s ' LOG.error(_LE('Command %(to_exec)s exited with %(retcode)s '
'- %(output)s'), '- %(output)s'),
{'to_exec': to_exec, {'to_exec': to_exec,
@ -249,9 +249,8 @@ class ConfigurePKI(BaseCertificateConfigure):
""" """
def __init__(self, keystone_user, keystone_group, rebuild=False): def __init__(self, keystone_user, keystone_group, rebuild=False):
super(ConfigurePKI, self).__init__(CONF.signing, CONF.signing, super(ConfigurePKI, self).__init__(CONF.signing, keystone_user,
keystone_user, keystone_group, keystone_group, rebuild=rebuild)
rebuild=rebuild)
class ConfigureSSL(BaseCertificateConfigure): class ConfigureSSL(BaseCertificateConfigure):
@ -262,9 +261,8 @@ class ConfigureSSL(BaseCertificateConfigure):
""" """
def __init__(self, keystone_user, keystone_group, rebuild=False): def __init__(self, keystone_user, keystone_group, rebuild=False):
super(ConfigureSSL, self).__init__(CONF.ssl, CONF.eventlet_server_ssl, super(ConfigureSSL, self).__init__(CONF.ssl, keystone_user,
keystone_user, keystone_group, keystone_group, rebuild=rebuild)
rebuild=rebuild)
BaseCertificateConfigure.sslconfig = """ BaseCertificateConfigure.sslconfig = """

View File

@ -12,6 +12,7 @@
import datetime import datetime
import os import os
import subprocess # nosec : see comments in the code below
import uuid import uuid
from oslo_config import cfg from oslo_config import cfg
@ -31,7 +32,6 @@ xmldsig = importutils.try_import("saml2.xmldsig")
if not xmldsig: if not xmldsig:
xmldsig = importutils.try_import("xmldsig") xmldsig = importutils.try_import("xmldsig")
from keystone.common import environment
from keystone.common import utils from keystone.common import utils
from keystone import exception from keystone import exception
from keystone.i18n import _, _LE from keystone.i18n import _, _LE
@ -422,7 +422,6 @@ def _sign_assertion(assertion):
nspair={'saml': saml2.NAMESPACE, nspair={'saml': saml2.NAMESPACE,
'xmldsig': xmldsig.NAMESPACE})) 'xmldsig': xmldsig.NAMESPACE}))
command_list.append(file_path) command_list.append(file_path)
subprocess = environment.subprocess
stdout = subprocess.check_output(command_list, # nosec : The contents stdout = subprocess.check_output(command_list, # nosec : The contents
# of the command list are coming from # of the command list are coming from
# a trusted source because the # a trusted source because the

View File

@ -1,158 +0,0 @@
# Copyright 2013 OpenStack Foundation
#
# 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 logging
import os
import socket
from oslo_concurrency import processutils
from oslo_config import cfg
import oslo_i18n
from oslo_service import service
from oslo_service import systemd
import pbr.version
# NOTE(dstanek): i18n.enable_lazy() must be called before
# keystone.i18n._() is called to ensure it has the desired lazy lookup
# behavior. This includes cases, like keystone.exceptions, where
# keystone.i18n._() is called at import time.
oslo_i18n.enable_lazy()
from keystone.common import config
from keystone.common import environment
from keystone.common import profiler
from keystone.common import utils
from keystone.i18n import _
from keystone.server import common
from keystone.version import service as keystone_service
CONF = cfg.CONF
class ServerWrapper(object):
"""Wrap a Server with some launching info & capabilities."""
def __init__(self, server, workers):
self.server = server
self.workers = workers
def launch_with(self, launcher):
self.server.listen()
if self.workers > 1:
# Use multi-process launcher
launcher.launch_service(self.server, self.workers)
else:
# Use single process launcher
launcher.launch_service(self.server)
def create_server(conf, name, host, port, workers):
app = keystone_service.loadapp('config:%s' % conf, name)
server = environment.Server(app, host=host, port=port,
keepalive=CONF.eventlet_server.tcp_keepalive,
keepidle=CONF.eventlet_server.tcp_keepidle)
profiler.setup(name, host)
if CONF.eventlet_server_ssl.enable:
server.set_ssl(CONF.eventlet_server_ssl.certfile,
CONF.eventlet_server_ssl.keyfile,
CONF.eventlet_server_ssl.ca_certs,
CONF.eventlet_server_ssl.cert_required)
return name, ServerWrapper(server, workers)
def serve(*servers):
logging.warning(_('Running keystone via eventlet is deprecated as of Kilo '
'in favor of running in a WSGI server (e.g. mod_wsgi). '
'Support for keystone under eventlet will be removed in '
'the "M"-Release.'))
if max([server[1].workers for server in servers]) > 1:
launcher = service.ProcessLauncher(CONF)
else:
launcher = service.ServiceLauncher(CONF)
for name, server in servers:
try:
server.launch_with(launcher)
except socket.error:
logging.exception(_('Failed to start the %(name)s server') % {
'name': name})
raise
# notify calling process we are ready to serve
systemd.notify_once()
for name, server in servers:
launcher.wait()
def _get_workers(worker_type_config_opt):
# Get the value from config, if the config value is None (not set), return
# the number of cpus with a minimum of 2.
worker_count = CONF.eventlet_server.get(worker_type_config_opt)
if not worker_count:
worker_count = max(2, processutils.get_worker_count())
return worker_count
def configure_threading():
monkeypatch_thread = not CONF.standard_threads
pydev_debug_url = utils.setup_remote_pydev_debug()
if pydev_debug_url:
# in order to work around errors caused by monkey patching we have to
# set the thread to False. An explanation is here:
# http://lists.openstack.org/pipermail/openstack-dev/2012-August/
# 000794.html
monkeypatch_thread = False
environment.use_eventlet(monkeypatch_thread)
def run(possible_topdir):
dev_conf = os.path.join(possible_topdir,
'etc',
'keystone.conf')
config_files = None
if os.path.exists(dev_conf):
config_files = [dev_conf]
common.configure(
version=pbr.version.VersionInfo('keystone').version_string(),
config_files=config_files,
pre_setup_logging_fn=configure_threading)
paste_config = config.find_paste_config()
def create_servers():
admin_worker_count = _get_workers('admin_workers')
public_worker_count = _get_workers('public_workers')
servers = []
servers.append(create_server(paste_config,
'admin',
CONF.eventlet_server.admin_bind_host,
CONF.eventlet_server.admin_port,
admin_worker_count))
servers.append(create_server(paste_config,
'main',
CONF.eventlet_server.public_bind_host,
CONF.eventlet_server.public_port,
public_worker_count))
return servers
_unused, servers = common.setup_backends(
startup_application_fn=create_servers)
serve(*servers)

View File

@ -28,7 +28,6 @@ oslo_i18n.enable_lazy()
from keystone.common import config from keystone.common import config
from keystone.common import environment
from keystone.server import common from keystone.server import common
from keystone.version import service as keystone_service from keystone.version import service as keystone_service
@ -43,8 +42,6 @@ def initialize_application(name, post_log_configured_function=lambda: None):
if CONF.debug: if CONF.debug:
CONF.log_opt_values(logging.getLogger(CONF.prog), logging.DEBUG) CONF.log_opt_values(logging.getLogger(CONF.prog), logging.DEBUG)
environment.use_stdlib()
post_log_configured_function() post_log_configured_function()
def loadapp(): def loadapp():

View File

@ -42,12 +42,6 @@ from sqlalchemy import exc
import testtools import testtools
from testtools import testcase from testtools import testcase
# NOTE(ayoung)
# environment.use_eventlet must run before any of the code that will
# call the eventlet monkeypatching.
from keystone.common import environment # noqa
environment.use_eventlet()
from keystone import auth from keystone import auth
from keystone.common import config from keystone.common import config
from keystone.common import dependency from keystone.common import dependency
@ -648,7 +642,7 @@ class TestCase(BaseTestCase):
# log module. This is not in a function or otherwise available to use # log module. This is not in a function or otherwise available to use
# without having a CONF object to setup logging. This should help to # without having a CONF object to setup logging. This should help to
# reduce the log size by limiting what we log (similar to how Keystone # reduce the log size by limiting what we log (similar to how Keystone
# would run under mod_wsgi or eventlet). # would run under mod_wsgi).
for pair in CONF.default_log_levels: for pair in CONF.default_log_levels:
mod, _sep, level_name = pair.partition('=') mod, _sep, level_name = pair.partition('=')
logger = logging.getLogger(mod) logger = logging.getLogger(mod)

View File

@ -1,79 +0,0 @@
# Copyright 2013 OpenStack Foundation
#
# 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.
from __future__ import absolute_import
import fixtures
from oslo_config import cfg
from paste import deploy
from keystone.common import environment
CONF = cfg.CONF
MAIN = 'main'
ADMIN = 'admin'
class AppServer(fixtures.Fixture):
"""A fixture for managing an application server instance."""
def __init__(self, config, name, cert=None, key=None, ca=None,
cert_required=False, host='127.0.0.1', port=0):
super(AppServer, self).__init__()
self.config = config
self.name = name
self.cert = cert
self.key = key
self.ca = ca
self.cert_required = cert_required
self.host = host
self.port = port
def setUp(self):
super(AppServer, self).setUp()
app = deploy.loadapp(self.config, name=self.name)
self.server = environment.Server(app, self.host, self.port)
self._setup_SSL_if_requested()
self.server.start(key='socket')
# some tests need to know the port we ran on.
self.port = self.server.socket_info['socket'][1]
self._update_config_opt()
self.addCleanup(self.server.stop)
def _setup_SSL_if_requested(self):
# TODO(dstanek): fix environment.Server to take a SSLOpts instance
# so that the params are either always set or not
if (self.cert is not None and
self.ca is not None and
self.key is not None):
self.server.set_ssl(certfile=self.cert,
keyfile=self.key,
ca_certs=self.ca,
cert_required=self.cert_required)
def _update_config_opt(self):
"""Update the config with the actual port used."""
opt_name = self._get_config_option_for_section_name()
CONF.set_override(opt_name, self.port, group='eventlet_server',
enforce_type=True)
def _get_config_option_for_section_name(self):
"""Map Paster config section names to port option names."""
return {'admin': 'admin_port', 'main': 'public_port'}[self.name]

View File

@ -15,12 +15,12 @@
import os import os
import shutil import shutil
import subprocess
import mock import mock
from six.moves import http_client from six.moves import http_client
from testtools import matchers from testtools import matchers
from keystone.common import environment
from keystone.common import openssl from keystone.common import openssl
from keystone import exception from keystone import exception
from keystone.tests import unit from keystone.tests import unit
@ -60,14 +60,6 @@ class CertSetupTestCase(rest.RestfulTestCase):
ca_certs=ca_certs, ca_certs=ca_certs,
ca_key=ca_key, ca_key=ca_key,
keyfile=os.path.join(KEYDIR, 'signing_key.pem')) keyfile=os.path.join(KEYDIR, 'signing_key.pem'))
self.config_fixture.config(
group='ssl',
ca_key=ca_key)
self.config_fixture.config(
group='eventlet_server_ssl',
ca_certs=ca_certs,
certfile=os.path.join(CERTDIR, 'keystone.pem'),
keyfile=os.path.join(KEYDIR, 'keystonekey.pem'))
self.config_fixture.config(group='token', provider='pkiz') self.config_fixture.config(group='token', provider='pkiz')
def test_can_handle_missing_certs(self): def test_can_handle_missing_certs(self):
@ -93,13 +85,6 @@ class CertSetupTestCase(rest.RestfulTestCase):
self.assertTrue(os.path.exists(CONF.signing.ca_certs)) self.assertTrue(os.path.exists(CONF.signing.ca_certs))
self.assertTrue(os.path.exists(CONF.signing.keyfile)) self.assertTrue(os.path.exists(CONF.signing.keyfile))
def test_create_ssl_certs(self, rebuild=False):
ssl = openssl.ConfigureSSL(None, None, rebuild=rebuild)
ssl.run()
self.assertTrue(os.path.exists(CONF.eventlet_server_ssl.ca_certs))
self.assertTrue(os.path.exists(CONF.eventlet_server_ssl.certfile))
self.assertTrue(os.path.exists(CONF.eventlet_server_ssl.keyfile))
def test_fetch_signing_cert(self, rebuild=False): def test_fetch_signing_cert(self, rebuild=False):
pki = openssl.ConfigurePKI(None, None, rebuild=rebuild) pki = openssl.ConfigurePKI(None, None, rebuild=rebuild)
pki.run() pki.run()
@ -156,17 +141,6 @@ class CertSetupTestCase(rest.RestfulTestCase):
self.assertNotEqual(cert_file1, cert_file2) self.assertNotEqual(cert_file1, cert_file2)
def test_ssl_certs_rebuild(self):
self.test_create_ssl_certs()
with open(CONF.eventlet_server_ssl.certfile) as f:
cert_file1 = f.read()
self.test_create_ssl_certs(rebuild=True)
with open(CONF.eventlet_server_ssl.certfile) as f:
cert_file2 = f.read()
self.assertNotEqual(cert_file1, cert_file2)
@mock.patch.object(os, 'remove') @mock.patch.object(os, 'remove')
def test_rebuild_pki_certs_remove_error(self, mock_remove): def test_rebuild_pki_certs_remove_error(self, mock_remove):
self.test_create_pki_certs() self.test_create_pki_certs()
@ -180,19 +154,6 @@ class CertSetupTestCase(rest.RestfulTestCase):
self.assertEqual(cert_file1, cert_file2) self.assertEqual(cert_file1, cert_file2)
@mock.patch.object(os, 'remove')
def test_rebuild_ssl_certs_remove_error(self, mock_remove):
self.test_create_ssl_certs()
with open(CONF.eventlet_server_ssl.certfile) as f:
cert_file1 = f.read()
mock_remove.side_effect = OSError()
self.test_create_ssl_certs(rebuild=True)
with open(CONF.eventlet_server_ssl.certfile) as f:
cert_file2 = f.read()
self.assertEqual(cert_file1, cert_file2)
def test_create_pki_certs_twice_without_rebuild(self): def test_create_pki_certs_twice_without_rebuild(self):
self.test_create_pki_certs() self.test_create_pki_certs()
with open(CONF.signing.certfile) as f: with open(CONF.signing.certfile) as f:
@ -204,40 +165,29 @@ class CertSetupTestCase(rest.RestfulTestCase):
self.assertEqual(cert_file1, cert_file2) self.assertEqual(cert_file1, cert_file2)
def test_create_ssl_certs_twice_without_rebuild(self):
self.test_create_ssl_certs()
with open(CONF.eventlet_server_ssl.certfile) as f:
cert_file1 = f.read()
self.test_create_ssl_certs()
with open(CONF.eventlet_server_ssl.certfile) as f:
cert_file2 = f.read()
self.assertEqual(cert_file1, cert_file2)
class TestExecCommand(unit.TestCase): class TestExecCommand(unit.TestCase):
@mock.patch.object(environment.subprocess.Popen, 'poll') @mock.patch.object(subprocess.Popen, 'poll')
def test_running_a_successful_command(self, mock_poll): def test_running_a_successful_command(self, mock_poll):
mock_poll.return_value = 0 mock_poll.return_value = 0
ssl = openssl.ConfigureSSL('keystone_user', 'keystone_group') ssl = openssl.ConfigurePKI('keystone_user', 'keystone_group')
ssl.exec_command(['ls']) ssl.exec_command(['ls'])
@mock.patch.object(environment.subprocess, 'check_output') @mock.patch.object(subprocess, 'check_output')
def test_running_an_invalid_command(self, mock_check_output): def test_running_an_invalid_command(self, mock_check_output):
cmd = ['ls'] cmd = ['ls']
output = 'this is the output string' output = 'this is the output string'
error = environment.subprocess.CalledProcessError(returncode=1, error = subprocess.CalledProcessError(returncode=1,
cmd=cmd, cmd=cmd,
output=output) output=output)
mock_check_output.side_effect = error mock_check_output.side_effect = error
ssl = openssl.ConfigureSSL('keystone_user', 'keystone_group') ssl = openssl.ConfigurePKI('keystone_user', 'keystone_group')
e = self.assertRaises(environment.subprocess.CalledProcessError, e = self.assertRaises(subprocess.CalledProcessError,
ssl.exec_command, ssl.exec_command,
cmd) cmd)
self.assertThat(e.output, matchers.Equals(output)) self.assertThat(e.output, matchers.Equals(output))

View File

@ -1,51 +0,0 @@
# Copyright 2012 OpenStack Foundation
#
# 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.
from oslo_config import cfg
from keystone.common import environment
from keystone.tests import unit
from keystone.tests.unit.ksfixtures import appserver
CONF = cfg.CONF
class IPv6TestCase(unit.TestCase):
def setUp(self):
self.skip_if_no_ipv6()
super(IPv6TestCase, self).setUp()
self.load_backends()
def test_ipv6_ok(self):
"""Make sure both public and admin API work with ipv6."""
paste_conf = self._paste_config('keystone')
# Verify Admin
with appserver.AppServer(paste_conf, appserver.ADMIN, host="::1"):
conn = environment.httplib.HTTPConnection(
'::1', CONF.eventlet_server.admin_port)
conn.request('GET', '/')
resp = conn.getresponse()
self.assertEqual(300, resp.status)
# Verify Public
with appserver.AppServer(paste_conf, appserver.MAIN, host="::1"):
conn = environment.httplib.HTTPConnection(
'::1', CONF.eventlet_server.public_port)
conn.request('GET', '/')
resp = conn.getresponse()
self.assertEqual(300, resp.status)

View File

@ -1,186 +0,0 @@
# Copyright 2012 OpenStack Foundation
#
# 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 os
import ssl
from oslo_config import cfg
from keystone.common import environment
from keystone.tests import unit
from keystone.tests.unit.ksfixtures import appserver
CONF = cfg.CONF
CERTDIR = unit.dirs.root('examples', 'pki', 'certs')
KEYDIR = unit.dirs.root('examples', 'pki', 'private')
CERT = os.path.join(CERTDIR, 'ssl_cert.pem')
KEY = os.path.join(KEYDIR, 'ssl_key.pem')
CA = os.path.join(CERTDIR, 'cacert.pem')
CLIENT = os.path.join(CERTDIR, 'middleware.pem')
class SSLTestCase(unit.TestCase):
def setUp(self):
super(SSLTestCase, self).setUp()
raise self.skipTest('SSL Version and Ciphers cannot be configured '
'with eventlet, some platforms have disabled '
'SSLv3. See bug 1381365.')
# NOTE(morganfainberg): It has been determined that this
# will not be fixed. These tests should be re-enabled for the full
# functional test suite when run against an SSL terminated
# endpoint. Some distributions/environments have patched OpenSSL to
# not have SSLv3 at all due to POODLE and this causes differing
# behavior depending on platform. See bug 1381365 for more information.
# NOTE(jamespage):
# Deal with more secure certificate chain verification
# introduced in python 2.7.9 under PEP-0476
# https://github.com/python/peps/blob/master/pep-0476.txt
self.context = None
if hasattr(ssl, '_create_unverified_context'):
self.context = ssl._create_unverified_context()
self.load_backends()
def get_HTTPSConnection(self, *args):
"""Simple helper to configure HTTPSConnection objects."""
if self.context:
return environment.httplib.HTTPSConnection(
*args,
context=self.context
)
else:
return environment.httplib.HTTPSConnection(*args)
def test_1way_ssl_ok(self):
"""Make sure both public and admin API work with 1-way SSL."""
paste_conf = self._paste_config('keystone')
ssl_kwargs = dict(cert=CERT, key=KEY, ca=CA)
# Verify Admin
with appserver.AppServer(paste_conf, appserver.ADMIN, **ssl_kwargs):
conn = self.get_HTTPSConnection(
'127.0.0.1', CONF.eventlet_server.admin_port)
conn.request('GET', '/')
resp = conn.getresponse()
self.assertEqual(300, resp.status)
# Verify Public
with appserver.AppServer(paste_conf, appserver.MAIN, **ssl_kwargs):
conn = self.get_HTTPSConnection(
'127.0.0.1', CONF.eventlet_server.public_port)
conn.request('GET', '/')
resp = conn.getresponse()
self.assertEqual(300, resp.status)
def test_2way_ssl_ok(self):
"""Make sure both public and admin API work with 2-way SSL.
Requires client certificate.
"""
paste_conf = self._paste_config('keystone')
ssl_kwargs = dict(cert=CERT, key=KEY, ca=CA, cert_required=True)
# Verify Admin
with appserver.AppServer(paste_conf, appserver.ADMIN, **ssl_kwargs):
conn = self.get_HTTPSConnection(
'127.0.0.1', CONF.eventlet_server.admin_port, CLIENT, CLIENT)
conn.request('GET', '/')
resp = conn.getresponse()
self.assertEqual(300, resp.status)
# Verify Public
with appserver.AppServer(paste_conf, appserver.MAIN, **ssl_kwargs):
conn = self.get_HTTPSConnection(
'127.0.0.1', CONF.eventlet_server.public_port, CLIENT, CLIENT)
conn.request('GET', '/')
resp = conn.getresponse()
self.assertEqual(300, resp.status)
def test_1way_ssl_with_ipv6_ok(self):
"""Make sure both public and admin API work with 1-way ipv6 & SSL."""
self.skip_if_no_ipv6()
paste_conf = self._paste_config('keystone')
ssl_kwargs = dict(cert=CERT, key=KEY, ca=CA, host="::1")
# Verify Admin
with appserver.AppServer(paste_conf, appserver.ADMIN, **ssl_kwargs):
conn = self.get_HTTPSConnection(
'::1', CONF.eventlet_server.admin_port)
conn.request('GET', '/')
resp = conn.getresponse()
self.assertEqual(300, resp.status)
# Verify Public
with appserver.AppServer(paste_conf, appserver.MAIN, **ssl_kwargs):
conn = self.get_HTTPSConnection(
'::1', CONF.eventlet_server.public_port)
conn.request('GET', '/')
resp = conn.getresponse()
self.assertEqual(300, resp.status)
def test_2way_ssl_with_ipv6_ok(self):
"""Make sure both public and admin API work with 2-way ipv6 & SSL.
Requires client certificate.
"""
self.skip_if_no_ipv6()
paste_conf = self._paste_config('keystone')
ssl_kwargs = dict(cert=CERT, key=KEY, ca=CA,
cert_required=True, host="::1")
# Verify Admin
with appserver.AppServer(paste_conf, appserver.ADMIN, **ssl_kwargs):
conn = self.get_HTTPSConnection(
'::1', CONF.eventlet_server.admin_port, CLIENT, CLIENT)
conn.request('GET', '/')
resp = conn.getresponse()
self.assertEqual(300, resp.status)
# Verify Public
with appserver.AppServer(paste_conf, appserver.MAIN, **ssl_kwargs):
conn = self.get_HTTPSConnection(
'::1', CONF.eventlet_server.public_port, CLIENT, CLIENT)
conn.request('GET', '/')
resp = conn.getresponse()
self.assertEqual(300, resp.status)
def test_2way_ssl_fail(self):
"""Expect to fail when client does not present proper certificate."""
paste_conf = self._paste_config('keystone')
ssl_kwargs = dict(cert=CERT, key=KEY, ca=CA, cert_required=True)
# Verify Admin
with appserver.AppServer(paste_conf, appserver.ADMIN, **ssl_kwargs):
conn = self.get_HTTPSConnection(
'127.0.0.1', CONF.eventlet_server.admin_port)
try:
conn.request('GET', '/')
self.fail('Admin API shoulda failed with SSL handshake!')
except ssl.SSLError:
pass
# Verify Public
with appserver.AppServer(paste_conf, appserver.MAIN, **ssl_kwargs):
conn = self.get_HTTPSConnection(
'127.0.0.1', CONF.eventlet_server.public_port)
try:
conn.request('GET', '/')
self.fail('Public API shoulda failed with SSL handshake!')
except ssl.SSLError:
pass

View File

@ -798,17 +798,10 @@ class PKIProviderTests(object):
from keystoneclient.common import cms from keystoneclient.common import cms
self.cms = cms self.cms = cms
from keystone.common import environment
self.environment = environment
old_cms_subprocess = cms.subprocess old_cms_subprocess = cms.subprocess
self.addCleanup(setattr, cms, 'subprocess', old_cms_subprocess) self.addCleanup(setattr, cms, 'subprocess', old_cms_subprocess)
old_env_subprocess = environment.subprocess
self.addCleanup(setattr, environment, 'subprocess', old_env_subprocess)
self.cms.subprocess = self.target_subprocess self.cms.subprocess = self.target_subprocess
self.environment.subprocess = self.target_subprocess
# force module reload so the imports get re-evaluated # force module reload so the imports get re-evaluated
reload_module(pki) reload_module(pki)
@ -825,16 +818,6 @@ class PKIProviderTests(object):
token_data) token_data)
class TestPKIProviderWithEventlet(PKIProviderTests, unit.TestCase):
def setUp(self):
# force keystoneclient.common.cms to use eventlet's subprocess
from eventlet.green import subprocess
self.target_subprocess = subprocess
super(TestPKIProviderWithEventlet, self).setUp()
class TestPKIProviderWithStdlib(PKIProviderTests, unit.TestCase): class TestPKIProviderWithStdlib(PKIProviderTests, unit.TestCase):
def setUp(self): def setUp(self):

View File

@ -13,6 +13,7 @@
import copy import copy
import os import os
import random import random
import subprocess
from testtools import matchers from testtools import matchers
import uuid import uuid
@ -33,7 +34,6 @@ if not xmldsig:
xmldsig = importutils.try_import("xmldsig") xmldsig = importutils.try_import("xmldsig")
from keystone.auth import controllers as auth_controllers from keystone.auth import controllers as auth_controllers
from keystone.common import environment
from keystone.contrib.federation import routers from keystone.contrib.federation import routers
from keystone import exception from keystone import exception
from keystone.federation import controllers as federation_controllers from keystone.federation import controllers as federation_controllers
@ -49,8 +49,6 @@ from keystone.tests.unit import utils
from keystone.token.providers import common as token_common from keystone.token.providers import common as token_common
subprocess = environment.subprocess
CONF = cfg.CONF CONF = cfg.CONF
ROOTDIR = os.path.dirname(os.path.abspath(__file__)) ROOTDIR = os.path.dirname(os.path.abspath(__file__))
XMLDIR = os.path.join(ROOTDIR, 'saml2/') XMLDIR = os.path.join(ROOTDIR, 'saml2/')

View File

@ -672,17 +672,15 @@ class VersionTestCase(unit.TestCase):
self.public_app = self.loadapp('keystone', 'main') self.public_app = self.loadapp('keystone', 'main')
self.admin_app = self.loadapp('keystone', 'admin') self.admin_app = self.loadapp('keystone', 'admin')
self.admin_port = random.randint(10000, 30000)
self.public_port = random.randint(40000, 60000)
self.config_fixture.config( self.config_fixture.config(
public_endpoint='http://localhost:%(public_port)d', public_endpoint='http://localhost:%d' % self.public_port,
admin_endpoint='http://localhost:%(admin_port)d') admin_endpoint='http://localhost:%d' % self.admin_port)
def config_overrides(self): def config_overrides(self):
super(VersionTestCase, self).config_overrides() super(VersionTestCase, self).config_overrides()
admin_port = random.randint(10000, 30000)
public_port = random.randint(40000, 60000)
self.config_fixture.config(group='eventlet_server',
public_port=public_port,
admin_port=admin_port)
def _paste_in_port(self, response, port): def _paste_in_port(self, response, port):
for link in response['links']: for link in response['links']:
@ -698,12 +696,10 @@ class VersionTestCase(unit.TestCase):
for version in expected['versions']['values']: for version in expected['versions']['values']:
if version['id'].startswith('v3'): if version['id'].startswith('v3'):
self._paste_in_port( self._paste_in_port(
version, 'http://localhost:%s/v3/' % version, 'http://localhost:%s/v3/' % self.public_port)
CONF.eventlet_server.public_port)
elif version['id'] == 'v2.0': elif version['id'] == 'v2.0':
self._paste_in_port( self._paste_in_port(
version, 'http://localhost:%s/v2.0/' % version, 'http://localhost:%s/v2.0/' % self.public_port)
CONF.eventlet_server.public_port)
self.assertThat(data, _VersionsEqual(expected)) self.assertThat(data, _VersionsEqual(expected))
def test_admin_versions(self): def test_admin_versions(self):
@ -715,12 +711,10 @@ class VersionTestCase(unit.TestCase):
for version in expected['versions']['values']: for version in expected['versions']['values']:
if version['id'].startswith('v3'): if version['id'].startswith('v3'):
self._paste_in_port( self._paste_in_port(
version, 'http://localhost:%s/v3/' % version, 'http://localhost:%s/v3/' % self.admin_port)
CONF.eventlet_server.admin_port)
elif version['id'] == 'v2.0': elif version['id'] == 'v2.0':
self._paste_in_port( self._paste_in_port(
version, 'http://localhost:%s/v2.0/' % version, 'http://localhost:%s/v2.0/' % self.admin_port)
CONF.eventlet_server.admin_port)
self.assertThat(data, _VersionsEqual(expected)) self.assertThat(data, _VersionsEqual(expected))
def test_use_site_url_if_endpoint_unset(self): def test_use_site_url_if_endpoint_unset(self):
@ -749,8 +743,7 @@ class VersionTestCase(unit.TestCase):
data = jsonutils.loads(resp.body) data = jsonutils.loads(resp.body)
expected = v2_VERSION_RESPONSE expected = v2_VERSION_RESPONSE
self._paste_in_port(expected['version'], self._paste_in_port(expected['version'],
'http://localhost:%s/v2.0/' % 'http://localhost:%s/v2.0/' % self.public_port)
CONF.eventlet_server.public_port)
self.assertEqual(expected, data) self.assertEqual(expected, data)
def test_admin_version_v2(self): def test_admin_version_v2(self):
@ -760,8 +753,7 @@ class VersionTestCase(unit.TestCase):
data = jsonutils.loads(resp.body) data = jsonutils.loads(resp.body)
expected = v2_VERSION_RESPONSE expected = v2_VERSION_RESPONSE
self._paste_in_port(expected['version'], self._paste_in_port(expected['version'],
'http://localhost:%s/v2.0/' % 'http://localhost:%s/v2.0/' % self.admin_port)
CONF.eventlet_server.admin_port)
self.assertEqual(expected, data) self.assertEqual(expected, data)
def test_use_site_url_if_endpoint_unset_v2(self): def test_use_site_url_if_endpoint_unset_v2(self):
@ -782,8 +774,7 @@ class VersionTestCase(unit.TestCase):
data = jsonutils.loads(resp.body) data = jsonutils.loads(resp.body)
expected = v3_VERSION_RESPONSE expected = v3_VERSION_RESPONSE
self._paste_in_port(expected['version'], self._paste_in_port(expected['version'],
'http://localhost:%s/v3/' % 'http://localhost:%s/v3/' % self.public_port)
CONF.eventlet_server.public_port)
self.assertEqual(expected, data) self.assertEqual(expected, data)
@utils.wip('waiting on bug #1381961') @utils.wip('waiting on bug #1381961')
@ -794,8 +785,7 @@ class VersionTestCase(unit.TestCase):
data = jsonutils.loads(resp.body) data = jsonutils.loads(resp.body)
expected = v3_VERSION_RESPONSE expected = v3_VERSION_RESPONSE
self._paste_in_port(expected['version'], self._paste_in_port(expected['version'],
'http://localhost:%s/v3/' % 'http://localhost:%s/v3/' % self.admin_port)
CONF.eventlet_server.admin_port)
self.assertEqual(expected, data) self.assertEqual(expected, data)
def test_use_site_url_if_endpoint_unset_v3(self): def test_use_site_url_if_endpoint_unset_v3(self):
@ -822,8 +812,7 @@ class VersionTestCase(unit.TestCase):
data = jsonutils.loads(resp.body) data = jsonutils.loads(resp.body)
expected = v3_VERSION_RESPONSE expected = v3_VERSION_RESPONSE
self._paste_in_port(expected['version'], self._paste_in_port(expected['version'],
'http://localhost:%s/v3/' % 'http://localhost:%s/v3/' % self.public_port)
CONF.eventlet_server.public_port)
self.assertEqual(expected, data) self.assertEqual(expected, data)
# only v3 information should be displayed by requests to / # only v3 information should be displayed by requests to /
@ -835,8 +824,7 @@ class VersionTestCase(unit.TestCase):
} }
} }
self._paste_in_port(v3_only_response['versions']['values'][0], self._paste_in_port(v3_only_response['versions']['values'][0],
'http://localhost:%s/v3/' % 'http://localhost:%s/v3/' % self.public_port)
CONF.eventlet_server.public_port)
resp = client.get('/') resp = client.get('/')
self.assertEqual(300, resp.status_int) self.assertEqual(300, resp.status_int)
data = jsonutils.loads(resp.body) data = jsonutils.loads(resp.body)
@ -855,8 +843,7 @@ class VersionTestCase(unit.TestCase):
data = jsonutils.loads(resp.body) data = jsonutils.loads(resp.body)
expected = v2_VERSION_RESPONSE expected = v2_VERSION_RESPONSE
self._paste_in_port(expected['version'], self._paste_in_port(expected['version'],
'http://localhost:%s/v2.0/' % 'http://localhost:%s/v2.0/' % self.public_port)
CONF.eventlet_server.public_port)
self.assertEqual(expected, data) self.assertEqual(expected, data)
# only v2 information should be displayed by requests to / # only v2 information should be displayed by requests to /
@ -868,8 +855,7 @@ class VersionTestCase(unit.TestCase):
} }
} }
self._paste_in_port(v2_only_response['versions']['values'][0], self._paste_in_port(v2_only_response['versions']['values'][0],
'http://localhost:%s/v2.0/' % 'http://localhost:%s/v2.0/' % self.public_port)
CONF.eventlet_server.public_port)
resp = client.get('/') resp = client.get('/')
self.assertEqual(300, resp.status_int) self.assertEqual(300, resp.status_int)
data = jsonutils.loads(resp.body) data = jsonutils.loads(resp.body)
@ -971,17 +957,15 @@ class VersionSingleAppTestCase(unit.TestCase):
super(VersionSingleAppTestCase, self).setUp() super(VersionSingleAppTestCase, self).setUp()
self.load_backends() self.load_backends()
self.admin_port = random.randint(10000, 30000)
self.public_port = random.randint(40000, 60000)
self.config_fixture.config( self.config_fixture.config(
public_endpoint='http://localhost:%(public_port)d', public_endpoint='http://localhost:%d' % self.public_port,
admin_endpoint='http://localhost:%(admin_port)d') admin_endpoint='http://localhost:%d' % self.admin_port)
def config_overrides(self): def config_overrides(self):
super(VersionSingleAppTestCase, self).config_overrides() super(VersionSingleAppTestCase, self).config_overrides()
admin_port = random.randint(10000, 30000)
public_port = random.randint(40000, 60000)
self.config_fixture.config(group='eventlet_server',
public_port=public_port,
admin_port=admin_port)
def _paste_in_port(self, response, port): def _paste_in_port(self, response, port):
for link in response['links']: for link in response['links']:
@ -991,9 +975,9 @@ class VersionSingleAppTestCase(unit.TestCase):
def _test_version(self, app_name): def _test_version(self, app_name):
def app_port(): def app_port():
if app_name == 'admin': if app_name == 'admin':
return CONF.eventlet_server.admin_port return self.admin_port
else: else:
return CONF.eventlet_server.public_port return self.public_port
app = self.loadapp('keystone', app_name) app = self.loadapp('keystone', app_name)
client = TestClient(app) client = TestClient(app)
resp = client.get('/') resp = client.get('/')

View File

@ -15,10 +15,8 @@
# under the License. # under the License.
import gettext import gettext
import socket
import uuid import uuid
import eventlet
import mock import mock
import oslo_i18n import oslo_i18n
from oslo_serialization import jsonutils from oslo_serialization import jsonutils
@ -27,7 +25,6 @@ from six.moves import http_client
from testtools import matchers from testtools import matchers
import webob import webob
from keystone.common import environment
from keystone.common import wsgi from keystone.common import wsgi
from keystone import exception from keystone import exception
from keystone.tests import unit from keystone.tests import unit
@ -485,102 +482,3 @@ class LocalizedResponseTest(unit.TestCase):
self.assertThat(resp.json['error']['message'], self.assertThat(resp.json['error']['message'],
matchers.Equals(exp_msg)) matchers.Equals(exp_msg))
self.assertThat(xlation_mock.called, matchers.Equals(True)) self.assertThat(xlation_mock.called, matchers.Equals(True))
class ServerTest(unit.TestCase):
def setUp(self):
super(ServerTest, self).setUp()
self.host = '127.0.0.1'
self.port = '1234'
@mock.patch('eventlet.listen')
@mock.patch('socket.getaddrinfo')
def test_keepalive_unset(self, mock_getaddrinfo, mock_listen):
mock_getaddrinfo.return_value = [(1, 2, 3, 4, 5)]
mock_sock_dup = mock_listen.return_value.dup.return_value
server = environment.Server(mock.MagicMock(), host=self.host,
port=self.port)
server.start()
self.addCleanup(server.stop)
self.assertTrue(mock_listen.called)
self.assertFalse(mock_sock_dup.setsockopt.called)
@mock.patch('eventlet.listen')
@mock.patch('socket.getaddrinfo')
def test_keepalive_set(self, mock_getaddrinfo, mock_listen):
mock_getaddrinfo.return_value = [(1, 2, 3, 4, 5)]
mock_sock_dup = mock_listen.return_value.dup.return_value
server = environment.Server(mock.MagicMock(), host=self.host,
port=self.port, keepalive=True)
server.start()
self.addCleanup(server.stop)
mock_sock_dup.setsockopt.assert_called_once_with(socket.SOL_SOCKET,
socket.SO_KEEPALIVE,
1)
self.assertTrue(mock_listen.called)
@mock.patch('eventlet.listen')
@mock.patch('socket.getaddrinfo')
def test_keepalive_and_keepidle_set(self, mock_getaddrinfo, mock_listen):
mock_getaddrinfo.return_value = [(1, 2, 3, 4, 5)]
mock_sock_dup = mock_listen.return_value.dup.return_value
server = environment.Server(mock.MagicMock(), host=self.host,
port=self.port, keepalive=True,
keepidle=1)
server.start()
self.addCleanup(server.stop)
if hasattr(socket, 'TCP_KEEPIDLE'):
self.assertEqual(2, mock_sock_dup.setsockopt.call_count)
# Test the last set of call args i.e. for the keepidle
mock_sock_dup.setsockopt.assert_called_with(socket.IPPROTO_TCP,
socket.TCP_KEEPIDLE,
1)
else:
self.assertEqual(1, mock_sock_dup.setsockopt.call_count)
self.assertTrue(mock_listen.called)
def test_client_socket_timeout(self):
# mocking server method of eventlet.wsgi to check it is called with
# configured 'client_socket_timeout' value.
for socket_timeout in range(1, 10):
self.config_fixture.config(group='eventlet_server',
client_socket_timeout=socket_timeout)
server = environment.Server(mock.MagicMock(), host=self.host,
port=self.port)
with mock.patch.object(eventlet.wsgi, 'server') as mock_server:
fake_application = uuid.uuid4().hex
fake_socket = uuid.uuid4().hex
server._run(fake_application, fake_socket)
mock_server.assert_called_once_with(
fake_socket,
fake_application,
debug=mock.ANY,
socket_timeout=socket_timeout,
log=mock.ANY,
keepalive=mock.ANY)
def test_wsgi_keep_alive(self):
# mocking server method of eventlet.wsgi to check it is called with
# configured 'wsgi_keep_alive' value.
wsgi_keepalive = False
self.config_fixture.config(group='eventlet_server',
wsgi_keep_alive=wsgi_keepalive)
server = environment.Server(mock.MagicMock(), host=self.host,
port=self.port)
with mock.patch.object(eventlet.wsgi, 'server') as mock_server:
fake_application = uuid.uuid4().hex
fake_socket = uuid.uuid4().hex
server._run(fake_application, fake_socket)
mock_server.assert_called_once_with(fake_socket,
fake_application,
debug=mock.ANY,
socket_timeout=mock.ANY,
log=mock.ANY,
keepalive=wsgi_keepalive)

View File

@ -14,13 +14,14 @@
"""Keystone PKI Token Provider""" """Keystone PKI Token Provider"""
import subprocess # nosec : used to catch subprocess exceptions
from keystoneclient.common import cms from keystoneclient.common import cms
from oslo_config import cfg from oslo_config import cfg
from oslo_log import log from oslo_log import log
from oslo_log import versionutils from oslo_log import versionutils
from oslo_serialization import jsonutils from oslo_serialization import jsonutils
from keystone.common import environment
from keystone.common import utils from keystone.common import utils
from keystone import exception from keystone import exception
from keystone.i18n import _, _LE from keystone.i18n import _, _LE
@ -48,7 +49,7 @@ class Provider(common.BaseProvider):
CONF.signing.certfile, CONF.signing.certfile,
CONF.signing.keyfile)) CONF.signing.keyfile))
return token_id return token_id
except environment.subprocess.CalledProcessError: except subprocess.CalledProcessError:
LOG.exception(_LE('Unable to sign token')) LOG.exception(_LE('Unable to sign token'))
raise exception.UnexpectedError(_( raise exception.UnexpectedError(_(
'Unable to sign token.')) 'Unable to sign token.'))

View File

@ -12,13 +12,14 @@
"""Keystone Compressed PKI Token Provider""" """Keystone Compressed PKI Token Provider"""
import subprocess # nosec : used to catch subprocess exceptions
from keystoneclient.common import cms from keystoneclient.common import cms
from oslo_config import cfg from oslo_config import cfg
from oslo_log import log from oslo_log import log
from oslo_log import versionutils from oslo_log import versionutils
from oslo_serialization import jsonutils from oslo_serialization import jsonutils
from keystone.common import environment
from keystone.common import utils from keystone.common import utils
from keystone import exception from keystone import exception
from keystone.i18n import _ from keystone.i18n import _
@ -47,7 +48,7 @@ class Provider(common.BaseProvider):
CONF.signing.certfile, CONF.signing.certfile,
CONF.signing.keyfile)) CONF.signing.keyfile))
return token_id return token_id
except environment.subprocess.CalledProcessError: except subprocess.CalledProcessError:
LOG.exception(ERROR_MESSAGE) LOG.exception(ERROR_MESSAGE)
raise exception.UnexpectedError(ERROR_MESSAGE) raise exception.UnexpectedError(ERROR_MESSAGE)

View File

@ -4,4 +4,12 @@ other:
[`blueprint removed-as-of-newton <https://blueprints.launchpad.net/keystone/+spec/removed-as-of-newton>`_] [`blueprint removed-as-of-newton <https://blueprints.launchpad.net/keystone/+spec/removed-as-of-newton>`_]
Removed the backend and route from ``keystone.contrib.endpoint_policy``. Removed the backend and route from ``keystone.contrib.endpoint_policy``.
The package has been moved to ``keystone.endpoint_policy``. This was The package has been moved to ``keystone.endpoint_policy``. This was
deprecated in the Liberty release. deprecated in the Liberty release.
- >
[`blueprint removed-as-of-newton <https://blueprints.launchpad.net/keystone/+spec/removed-as-of-newton>`_]
Removed ``[eventlet_server]`` and ``[eventlet_server_ssl]`` sections from
the `keystone.conf`.
- >
[`blueprint removed-as-of-newton <https://blueprints.launchpad.net/keystone/+spec/removed-as-of-newton>`_]
Removed support for running keystone under eventlet. It is recommended to
run keystone in an HTTP server.

View File

@ -8,8 +8,6 @@ Babel>=1.3,!=2.3.0,!=2.3.1,!=2.3.2,!=2.3.3 # BSD
pbr>=1.6 # Apache-2.0 pbr>=1.6 # Apache-2.0
WebOb>=1.2.3 # MIT WebOb>=1.2.3 # MIT
eventlet!=0.18.3,>=0.18.2 # MIT
greenlet>=0.3.2 # MIT
PasteDeploy>=1.5.0 # MIT PasteDeploy>=1.5.0 # MIT
Paste # MIT Paste # MIT
Routes!=2.0,!=2.1,!=2.3.0,>=1.12.3;python_version=='2.7' # MIT Routes!=2.0,!=2.1,!=2.3.0,>=1.12.3;python_version=='2.7' # MIT
@ -33,7 +31,6 @@ oslo.log>=1.14.0 # Apache-2.0
oslo.middleware>=3.0.0 # Apache-2.0 oslo.middleware>=3.0.0 # Apache-2.0
oslo.policy>=0.5.0 # Apache-2.0 oslo.policy>=0.5.0 # Apache-2.0
oslo.serialization>=1.10.0 # Apache-2.0 oslo.serialization>=1.10.0 # Apache-2.0
oslo.service>=1.0.0 # Apache-2.0
oslo.utils>=3.5.0 # Apache-2.0 oslo.utils>=3.5.0 # Apache-2.0
oauthlib>=0.6 # BSD oauthlib>=0.6 # BSD
pysaml2<4.0.3,>=2.4.0 # Apache-2.0 pysaml2<4.0.3,>=2.4.0 # Apache-2.0

View File

@ -69,7 +69,6 @@ autodoc_tree_index_modules = True
[entry_points] [entry_points]
console_scripts = console_scripts =
keystone-all = keystone.cmd.all:main
keystone-manage = keystone.cmd.manage:main keystone-manage = keystone.cmd.manage:main
wsgi_scripts = wsgi_scripts =

View File

@ -122,7 +122,7 @@ passenv =
KSTEST_PROJECT_ID KSTEST_PROJECT_ID
[flake8] [flake8]
filename= *.py,keystone-all,keystone-manage filename= *.py,keystone-manage
show-source = true show-source = true
# D100: Missing docstring in public module # D100: Missing docstring in public module