drop key distribution from icehouse

key distribution is being continued in feature branch here:

  https://github.com/openstack/keystone/tree/feature/key-dist

Change-Id: I47504bec73dd7e1a6419a5509093a9d494d90108
This commit is contained in:
Dolph Mathews 2014-03-03 15:19:35 -06:00 committed by Morgan Fainberg
parent 7d919df6c6
commit dd18e86ff6
55 changed files with 43 additions and 2005 deletions

View File

@ -1,238 +0,0 @@
[DEFAULT]
#
# Options defined in keystone.contrib.kds.common.service
#
# IP for the server to bind to (string value)
#bind_ip=0.0.0.0
# The port for the server (integer value)
#port=9109
#
# Options defined in keystone.openstack.common.db.sqlalchemy.session
#
# the filename to use with sqlite (string value)
#sqlite_db=keystone.sqlite
# If true, use synchronous mode for sqlite (boolean value)
#sqlite_synchronous=true
#
# Options defined in keystone.openstack.common.eventlet_backdoor
#
# Enable eventlet backdoor. Acceptable values are 0, <port>,
# and <start>:<end>, where 0 results in listening on a random
# tcp port number; <port> results in listening on the
# specified port number (and not enabling backdoor if that
# port is in use); and <start>:<end> results in listening on
# the smallest unused port number within the specified range
# of port numbers. The chosen port is displayed in the
# service's log file. (string value)
#backdoor_port=<None>
#
# Options defined in keystone.openstack.common.lockutils
#
# Whether to disable inter-process locks (boolean value)
#disable_process_locking=false
# Directory to use for lock files. (string value)
#lock_path=<None>
#
# Options defined in keystone.openstack.common.log
#
# Print debugging output (set logging level to DEBUG instead
# of default WARNING level). (boolean value)
#debug=false
# Print more verbose output (set logging level to INFO instead
# of default WARNING level). (boolean value)
#verbose=false
# Log output to standard error (boolean value)
#use_stderr=true
# format string to use for log messages with context (string
# value)
#logging_context_format_string=%(asctime)s.%(msecs)03d %(process)d %(levelname)s %(name)s [%(request_id)s %(user)s %(tenant)s] %(instance)s%(message)s
# format string to use for log messages without context
# (string value)
#logging_default_format_string=%(asctime)s.%(msecs)03d %(process)d %(levelname)s %(name)s [-] %(instance)s%(message)s
# data to append to log format when level is DEBUG (string
# value)
#logging_debug_format_suffix=%(funcName)s %(pathname)s:%(lineno)d
# prefix each line of exception output with this format
# (string value)
#logging_exception_prefix=%(asctime)s.%(msecs)03d %(process)d TRACE %(name)s %(instance)s
# list of logger=LEVEL pairs (list value)
#default_log_levels=amqp=WARN,amqplib=WARN,boto=WARN,keystone=INFO,qpid=WARN,sqlalchemy=WARN,suds=INFO,iso8601=WARN
# publish error events (boolean value)
#publish_errors=false
# make deprecations fatal (boolean value)
#fatal_deprecations=false
# If an instance is passed with the log message, format it
# like this (string value)
#instance_format="[instance: %(uuid)s] "
# If an instance UUID is passed with the log message, format
# it like this (string value)
#instance_uuid_format="[instance: %(uuid)s] "
# The name of logging configuration file. It does not disable
# existing loggers, but just appends specified logging
# configuration to any other existing logging options. Please
# see the Python logging module documentation for details on
# logging configuration files. (string value)
# Deprecated group/name - [DEFAULT]/log_config
#log_config_append=<None>
# 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. (string value)
#log_format=<None>
# Format string for %%(asctime)s in log records. Default:
# %(default)s (string value)
#log_date_format=%Y-%m-%d %H:%M:%S
# (Optional) Name of log file to output to. If no default is
# set, logging will go to stdout. (string value)
# Deprecated group/name - [DEFAULT]/logfile
#log_file=<None>
# (Optional) The base directory used for relative --log-file
# paths (string value)
# Deprecated group/name - [DEFAULT]/logdir
#log_dir=<None>
# Use syslog for logging. (boolean value)
#use_syslog=false
# syslog facility to receive log lines (string value)
#syslog_log_facility=LOG_USER
#
# Options defined in keystone.openstack.common.policy
#
# JSON file containing policy (string value)
#policy_file=policy.json
# Rule enforced when requested rule is not found (string
# value)
#policy_default_rule=default
[ssl]
#
# Options defined in keystone.openstack.common.sslutils
#
# CA certificate file to use to verify connecting clients
# (string value)
#ca_file=<None>
# Certificate file to use when starting the server securely
# (string value)
#cert_file=<None>
# Private key file to use when starting the server securely
# (string value)
#key_file=<None>
[database]
#
# Options defined in keystone.openstack.common.db.api
#
# The backend to use for db (string value)
# Deprecated group/name - [DEFAULT]/db_backend
#backend=sqlalchemy
# Enable the experimental use of thread pooling for all DB API
# calls (boolean value)
# Deprecated group/name - [DEFAULT]/dbapi_use_tpool
#use_tpool=false
#
# Options defined in keystone.openstack.common.db.sqlalchemy.session
#
# The SQLAlchemy connection string used to connect to the
# database (string value)
# Deprecated group/name - [DEFAULT]/sql_connection
# Deprecated group/name - [DATABASE]/sql_connection
# Deprecated group/name - [sql]/connection
#connection=sqlite:////keystone/openstack/common/db/$sqlite_db
# The SQLAlchemy connection string used to connect to the
# slave database (string value)
#slave_connection=
# timeout before idle sql connections are reaped (integer
# value)
# Deprecated group/name - [DEFAULT]/sql_idle_timeout
# Deprecated group/name - [DATABASE]/sql_idle_timeout
#idle_timeout=3600
# Minimum number of SQL connections to keep open in a pool
# (integer value)
# Deprecated group/name - [DEFAULT]/sql_min_pool_size
# Deprecated group/name - [DATABASE]/sql_min_pool_size
#min_pool_size=1
# Maximum number of SQL connections to keep open in a pool
# (integer value)
# Deprecated group/name - [DEFAULT]/sql_max_pool_size
# Deprecated group/name - [DATABASE]/sql_max_pool_size
#max_pool_size=<None>
# maximum db connection retries during startup. (setting -1
# implies an infinite retry count) (integer value)
# Deprecated group/name - [DEFAULT]/sql_max_retries
# Deprecated group/name - [DATABASE]/sql_max_retries
#max_retries=10
# interval between retries of opening a sql connection
# (integer value)
# Deprecated group/name - [DEFAULT]/sql_retry_interval
# Deprecated group/name - [DATABASE]/reconnect_interval
#retry_interval=10
# If set, use this value for max_overflow with sqlalchemy
# (integer value)
# Deprecated group/name - [DEFAULT]/sql_max_overflow
# Deprecated group/name - [DATABASE]/sqlalchemy_max_overflow
#max_overflow=<None>
# Verbosity of SQL debugging information. 0=None,
# 100=Everything (integer value)
# Deprecated group/name - [DEFAULT]/sql_connection_debug
#connection_debug=0
# Add python stack traces to SQL as comment strings (boolean
# value)
# Deprecated group/name - [DEFAULT]/sql_connection_trace
#connection_trace=false
# If set, use this value for pool_timeout with sqlalchemy
# (integer value)
# Deprecated group/name - [DATABASE]/sqlalchemy_pool_timeout
#pool_timeout=<None>

View File

@ -109,40 +109,40 @@
# Auto-delete queues in amqp. (boolean value)
#amqp_auto_delete=false
# Size of RPC connection pool (integer value)
# Size of RPC connection pool. (integer value)
#rpc_conn_pool_size=30
# Modules of exceptions that are permitted to be recreatedupon
# receiving exception data from an rpc call. (list value)
# Modules of exceptions that are permitted to be recreated
# upon receiving exception data from an rpc call. (list value)
#allowed_rpc_exception_modules=oslo.messaging.exceptions,nova.exception,cinder.exception,exceptions
# Qpid broker hostname (string value)
# Qpid broker hostname. (string value)
#qpid_hostname=localhost
# Qpid broker port (integer value)
# Qpid broker port. (integer value)
#qpid_port=5672
# Qpid HA cluster host:port pairs (list value)
# Qpid HA cluster host:port pairs. (list value)
#qpid_hosts=$qpid_hostname:$qpid_port
# Username for Qpid connection (string value)
# Username for Qpid connection. (string value)
#qpid_username=
# Password for Qpid connection (string value)
# Password for Qpid connection. (string value)
#qpid_password=
# Space separated list of SASL mechanisms to use for auth
# Space separated list of SASL mechanisms to use for auth.
# (string value)
#qpid_sasl_mechanisms=
# Seconds between connection keepalive heartbeats (integer
# Seconds between connection keepalive heartbeats. (integer
# value)
#qpid_heartbeat=60
# Transport to use, either 'tcp' or 'ssl' (string value)
# Transport to use, either 'tcp' or 'ssl'. (string value)
#qpid_protocol=tcp
# Disable Nagle algorithm (boolean value)
# Whether to disable the Nagle algorithm. (boolean value)
#qpid_tcp_nodelay=true
# The qpid topology version to use. Version 1 is what was
@ -155,52 +155,55 @@
# SSL version to use (valid only if SSL enabled). valid values
# are TLSv1, SSLv23 and SSLv3. SSLv2 may be available on some
# distributions (string value)
# distributions. (string value)
#kombu_ssl_version=
# SSL key file (valid only if SSL enabled) (string value)
# SSL key file (valid only if SSL enabled). (string value)
#kombu_ssl_keyfile=
# SSL cert file (valid only if SSL enabled) (string value)
# SSL cert file (valid only if SSL enabled). (string value)
#kombu_ssl_certfile=
# SSL certification authority file (valid only if SSL enabled)
# (string value)
# SSL certification authority file (valid only if SSL
# enabled). (string value)
#kombu_ssl_ca_certs=
# The RabbitMQ broker address where a single node is used
# The RabbitMQ broker address where a single node is used.
# (string value)
#rabbit_host=localhost
# The RabbitMQ broker port where a single node is used
# The RabbitMQ broker port where a single node is used.
# (integer value)
#rabbit_port=5672
# RabbitMQ HA cluster host:port pairs (list value)
# RabbitMQ HA cluster host:port pairs. (list value)
#rabbit_hosts=$rabbit_host:$rabbit_port
# Connect over SSL for RabbitMQ (boolean value)
# Connect over SSL for RabbitMQ. (boolean value)
#rabbit_use_ssl=false
# The RabbitMQ userid (string value)
# The RabbitMQ userid. (string value)
#rabbit_userid=guest
# The RabbitMQ password (string value)
# The RabbitMQ password. (string value)
#rabbit_password=guest
# The RabbitMQ virtual host (string value)
# the RabbitMQ login method (string value)
#rabbit_login_method=AMQPLAIN
# The RabbitMQ virtual host. (string value)
#rabbit_virtual_host=/
# How frequently to retry connecting with RabbitMQ (integer
# How frequently to retry connecting with RabbitMQ. (integer
# value)
#rabbit_retry_interval=1
# How long to backoff for between retries when connecting to
# RabbitMQ (integer value)
# RabbitMQ. (integer value)
#rabbit_retry_backoff=2
# Maximum number of RabbitMQ connection retries. Default is 0
# (infinite retry count) (integer value)
# (infinite retry count). (integer value)
#rabbit_max_retries=0
# Use HA queues in RabbitMQ (x-ha-policy: all). If you change
@ -208,7 +211,7 @@
# value)
#rabbit_ha_queues=false
# If passed, use a fake RabbitMQ provider (boolean value)
# If passed, use a fake RabbitMQ provider. (boolean value)
#fake_rabbit=false
# ZeroMQ bind address. Should be a wildcard (*), an ethernet
@ -216,20 +219,20 @@
# to this address. (string value)
#rpc_zmq_bind_address=*
# MatchMaker driver (string value)
# MatchMaker driver. (string value)
#rpc_zmq_matchmaker=oslo.messaging._drivers.matchmaker.MatchMakerLocalhost
# ZeroMQ receiver listening port (integer value)
# ZeroMQ receiver listening port. (integer value)
#rpc_zmq_port=9501
# Number of ZeroMQ contexts, defaults to 1 (integer value)
# Number of ZeroMQ contexts, defaults to 1. (integer value)
#rpc_zmq_contexts=1
# Maximum number of ingress messages to locally buffer per
# topic. Default is unlimited. (integer value)
#rpc_zmq_topic_backlog=<None>
# Directory for holding IPC sockets (string value)
# Directory for holding IPC sockets. (string value)
#rpc_zmq_ipc_dir=/var/run/openstack
# Name of this node. Must be a valid hostname, FQDN, or IP
@ -241,33 +244,33 @@
# by impl_zmq. (integer value)
#rpc_cast_timeout=30
# Heartbeat frequency (integer value)
# Heartbeat frequency. (integer value)
#matchmaker_heartbeat_freq=300
# Heartbeat time-to-live. (integer value)
#matchmaker_heartbeat_ttl=600
# Host to locate redis (string value)
# Host to locate redis. (string value)
#host=127.0.0.1
# Use this port to connect to redis host. (integer value)
#port=6379
# Password for Redis server. (optional) (string value)
# Password for Redis server (optional). (string value)
#password=<None>
# Size of RPC greenthread pool (integer value)
# Size of RPC greenthread pool. (integer value)
#rpc_thread_pool_size=64
# Driver or drivers to handle sending notifications (multi
# Driver or drivers to handle sending notifications. (multi
# valued)
#notification_driver=
# AMQP topic used for OpenStack notifications (list value)
# AMQP topic used for OpenStack notifications. (list value)
# Deprecated group/name - [rpc_notifier2]/topics
#notification_topics=notifications
# Seconds to wait for a response from a call (integer value)
# Seconds to wait for a response from a call. (integer value)
#rpc_response_timeout=60
# A URL representing the messaging driver to use and its full
@ -1006,7 +1009,7 @@
# Options defined in oslo.messaging
#
# Matchmaker ring file (JSON) (string value)
# Matchmaker ring file (JSON). (string value)
# Deprecated group/name - [DEFAULT]/matchmaker_ringfile
#ringfile=/etc/oslo/matchmaker_ring.json
@ -1153,23 +1156,6 @@
#cert_subject=/C=US/ST=Unset/L=Unset/O=Unset/CN=localhost
#
# Options defined in keystone.openstack.common.sslutils
#
# CA certificate file to use to verify connecting clients
# (string value)
#ca_file=<None>
# Certificate file to use when starting the server securely
# (string value)
#cert_file=<None>
# Private key file to use when starting the server securely
# (string value)
#key_file=<None>
[stats]
#

View File

@ -1,43 +0,0 @@
# 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
import pecan
from keystone.contrib.kds.api import config as pecan_config
from keystone.contrib.kds.api import hooks
CONF = cfg.CONF
def get_pecan_config():
# Set up the pecan configuration
filename = pecan_config.__file__.replace('.pyc', '.py')
return pecan.configuration.conf_from_file(filename)
def setup_app(config=None, extra_hooks=None):
app_hooks = [hooks.ConfigHook()]
if extra_hooks:
app_hooks.extend(extra_hooks)
if not config:
config = get_pecan_config()
pecan.configuration.set_config(dict(config), overwrite=True)
app = pecan.make_app('keystone.contrib.kds.api.root.RootController',
debug=CONF.debug,
hooks=app_hooks)
return app

View File

@ -1,30 +0,0 @@
# 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.
# Server Specific Configurations
server = {
'port': 9109,
'host': '0.0.0.0'
}
# Pecan Application Configurations
app = {
'root': 'keystone.contrib.kds.api.root.RootController',
'modules': ['keystone.contrib.kds.api'],
'static_root': '%(confdir)s/public',
'template_path': '%(confdir)s/templates',
'debug': False,
}
# Custom Configurations must be in Python dictionary format::
#
# foo = {'bar': 'baz'}

View File

@ -1,19 +0,0 @@
# 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 pecan import hooks
class ConfigHook(hooks.PecanHook):
def before(self, state):
state.request.cfg = cfg.CONF

View File

@ -1,29 +0,0 @@
# 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 pecan
from keystone.contrib.kds.api.v1 import controllers
class RootController(object):
v1 = controllers.Controller()
@pecan.expose('json')
def index(self):
pecan.response.status = 300
return {
'versions': [
self.v1.version_info(),
]
}

View File

@ -1,19 +0,0 @@
# 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 keystone.contrib.kds.api.v1.controllers import controller
Controller = controller.Controller
__all__ = ['Controller']

View File

@ -1,29 +0,0 @@
# 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 pecan
class Controller(object):
"""Version 1 API controller root."""
@staticmethod
def version_info():
return {'status': 'stable',
'id': 'v1.0',
'links': [{
'href': '%s/v1/' % pecan.request.host_url,
'rel': 'self'}]}
@pecan.expose('json')
def index(self):
return {'version': self.version_info()}

View File

@ -1,55 +0,0 @@
# 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 sys
from oslo.config import cfg
from wsgiref import simple_server
from keystone.openstack.common import gettextutils
PROJECT = 'kds'
gettextutils.install(PROJECT, lazy=True)
from keystone.contrib.kds.api import app
from keystone.contrib.kds.common import service
from keystone.openstack.common import log
CONF = cfg.CONF
class Application(object):
def __init__(self):
self.app = app.setup_app()
def __call__(self, environ, start_response):
return self.app(environ, start_response)
def main():
service.prepare_service(sys.argv)
# Build and start the WSGI app
host = CONF.bind_ip
port = CONF.port
wsgi = simple_server.make_server(host, port, Application())
LOG = log.getLogger(__name__)
LOG.info(_("Serving on http://%(host)s:%(port)d"), {'host': host,
'port': port})
CONF.log_opt_values(LOG, logging.INFO)
try:
wsgi.serve_forever()
except KeyboardInterrupt:
pass

View File

@ -1,63 +0,0 @@
# 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 sys
from keystone.openstack.common import gettextutils
# gettextutils.install() must run to set _ before importing any modules that
# contain static translated strings.
gettextutils.install('keystone')
from oslo.config import cfg
from keystone.contrib.kds.common import service
from keystone.contrib.kds.db import migration
CONF = cfg.CONF
def do_db_version():
"""Print database's current migration level."""
print(migration.db_version())
def do_db_sync():
"""Place a database under migration control and upgrade,
creating first if necessary.
"""
return migration.db_sync(CONF.command.version)
def add_command_parsers(subparsers):
parser = subparsers.add_parser('db_version')
parser.set_defaults(func=do_db_version)
parser = subparsers.add_parser('db_sync')
parser.set_defaults(func=do_db_sync)
parser.add_argument('version', nargs='?')
command_opt = cfg.SubCommandOpt('command',
title='Commands',
help='Available commands',
handler=add_command_parsers)
def main():
CONF.register_cli_opt(command_opt)
service.prepare_service(sys.argv)
try:
CONF.command.func()
except Exception as e:
sys.exit("ERROR: %s" % e)

View File

@ -1,54 +0,0 @@
# 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.
_FATAL_EXCEPTION_FORMAT_ERRORS = False
class KdsException(Exception):
"""Base Exception class.
To correctly use this class, inherit from it and define
a 'msg_fmt' property. That message will get printf'd
with the keyword arguments provided to the constructor.
"""
msg_fmt = _('An unknown exception occurred')
def __init__(self, **kwargs):
try:
self._error_string = self.msg_fmt % kwargs
except Exception:
if _FATAL_EXCEPTION_FORMAT_ERRORS:
raise
else:
# at least get the core message out if something happened
self._error_string = self.msg_fmt
def __str__(self):
return self._error_string
class BackendException(KdsException):
msg_fmt = _("Failed to load the '%(backend)s' backend because it is not "
"allowed. Allowed backends are: %(allowed)s")
class IntegrityError(KdsException):
msg_fmt = _('Cannot set key data for %(name)s: %(reason)s')
class GroupStatusChanged(IntegrityError):
def __init__(self, **kwargs):
kwargs.setdefault('reason', "Can't change group status of a host")
super(GroupStatusChanged, self).__init__(**kwargs)

View File

@ -1,52 +0,0 @@
# 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.openstack.common import log
CONF = cfg.CONF
FILE_OPTIONS = {
None: [
cfg.StrOpt('bind_ip',
default='0.0.0.0',
help='IP for the server to bind to'),
cfg.IntOpt('port',
default=9109,
help='The port for the server')]}
def configure(conf=None):
if conf is None:
conf = CONF
for group in FILE_OPTIONS:
conf.register_opts(FILE_OPTIONS[group], group=group)
def parse_args(args, default_config_files=None):
CONF(args=args[1:],
project='kds',
default_config_files=default_config_files)
def prepare_service(argv=[]):
cfg.set_defaults(log.log_opts,
default_log_levels=['sqlalchemy=WARN',
'eventlet.wsgi.server=WARN'
])
parse_args(argv)
log.setup('kds')
configure()

View File

@ -1,59 +0,0 @@
# 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.contrib.kds.common import exception
CONF = cfg.CONF
# NOTE(jamielennox): This class is a direct copy from nova, glance, heat and
# a bunch of other projects. It has been submitted to OSLO
# https://review.openstack.org/#/c/67002/ and should be synced when available.
class LazyPluggable(object):
"""A pluggable backend loaded lazily based on some value."""
def __init__(self, pivot, config_group=None, **backends):
self.__backends = backends
self.__pivot = pivot
self.__backend = None
self.__config_group = config_group
def __get_backend(self):
if not self.__backend:
if self.__config_group is None:
backend_name = CONF[self.__pivot]
else:
backend_name = CONF[self.__config_group][self.__pivot]
if backend_name not in self.__backends:
allowed = ', '.join(self.__backends.iterkeys())
raise exception.BackendException(backend=backend_name,
allowed=allowed)
backend = self.__backends[backend_name]
if isinstance(backend, tuple):
name = backend[0]
fromlist = backend[1]
else:
name = backend
fromlist = backend
self.__backend = __import__(name=name, globals=None,
locals=None, fromlist=fromlist)
return self.__backend
def __getattr__(self, key):
backend = self.__get_backend()
return getattr(backend, key)

View File

@ -1,32 +0,0 @@
# 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.openstack.common.db import api as db_api
CONF = cfg.CONF
_BACKEND_MAPPING = {'sqlalchemy': 'keystone.contrib.kds.db.sqlalchemy.api',
'kvs': 'keystone.contrib.kds.db.kvs.api'}
IMPL = db_api.DBAPI(backend_mapping=_BACKEND_MAPPING)
def reset():
global IMPL
IMPL = db_api.DBAPI(backend_mapping=_BACKEND_MAPPING)
def get_instance():
"""Return a DB API instance."""
return IMPL

View File

@ -1,66 +0,0 @@
# 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 abc
import six
@six.add_metaclass(abc.ABCMeta)
class Connection(object):
@abc.abstractmethod
def set_key(self, name, key, signature, group, expiration=None):
"""Set a key for a name in the database.
If a key is set for an existing key name then a new key entry with a
new generation value is created.
:param string name: The unique name of the key to set.
:param string key: The key data to save.
:param string signature: The signature of the key data to save.
:param bool group: Whether this is a group key or not.
:param DateTime expiration: When the key should expire
(None is never expire).
:raises GroupStatusChanged: If a key exists then new keys assigned to
the name must have the same 'group' setting. If the value of group
is changed a
:class:`keystone.contrib.kds.common.exception.GroupStatusChanged`
is raised.
:returns int: The generation number of this key.
"""
@abc.abstractmethod
def get_key(self, name, generation=None, group=None):
"""Get key related to kds_id.
:param string name: The unique name of the key to fetch.
:param int generation: A specific generation of the key to retrieve. If
not specified the most recent generation is
retrieved.
:param bool group: If provided only retrieve this key if its group
value is the same.
:returns dict: A dictionary of the key information or None if not
found. Keys will contain:
- name: Unique name of the key.
- group: If this key is a group key or not.
- key: The key data.
- signature: The signature of the key data.
- generation: The generation of this key.
- expiration: When the key expires (or None).
Expired keys can be returned.
"""

View File

@ -1,66 +0,0 @@
# 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 keystone.contrib.kds.common import exception
from keystone.contrib.kds.db import connection
def get_backend():
return KvsDbImpl()
class KvsDbImpl(connection.Connection):
"""A simple in-memory Key Value backend.
KVS backends are designed for use in testing and for simple debugging.
This backend should not be deployed in any production systems.
"""
def __init__(self):
super(KvsDbImpl, self).__init__()
self.clear()
def clear(self):
self._data = dict()
def set_key(self, name, key, signature, group, expiration=None):
host = self._data.setdefault(name, {'latest_generation': 0,
'keys': dict(), 'group': group})
if host['group'] != group:
raise exception.GroupStatusChanged(name=name)
host['latest_generation'] += 1
host['keys'][host['latest_generation']] = {'key': key,
'signature': signature,
'expiration': expiration}
return host['latest_generation']
def get_key(self, name, generation=None, group=None):
response = {'name': name}
try:
host = self._data[name]
if generation is None:
generation = host['latest_generation']
key_data = host['keys'][generation]
except KeyError:
return None
response['generation'] = generation
response['group'] = host['group']
if group is not None and host['group'] != group:
return None
response.update(key_data)
return response

View File

@ -1,39 +0,0 @@
# 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.
"""Database setup and migration commands."""
from oslo.config import cfg
from keystone.contrib.kds.common import utils
CONF = cfg.CONF
CONF.import_opt('backend',
'keystone.openstack.common.db.api',
group='database')
_sqlalchemy_repo = 'keystone.contrib.kds.db.sqlalchemy.migration'
IMPL = utils.LazyPluggable(pivot='backend',
config_group='database',
sqlalchemy=_sqlalchemy_repo)
INIT_VERSION = 0
def db_sync(version=None):
"""Migrate the database to `version` or the most recent version."""
return IMPL.db_sync(version=version)
def db_version():
"""Display the current database version."""
return IMPL.db_version()

View File

@ -1,80 +0,0 @@
# 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 sqlalchemy.orm import exc
from keystone.contrib.kds.common import exception
from keystone.contrib.kds.db import connection
from keystone.contrib.kds.db.sqlalchemy import models
from keystone.openstack.common.db.sqlalchemy import session as db_session
def get_backend():
return SqlalchemyDbImpl()
class SqlalchemyDbImpl(connection.Connection):
def set_key(self, name, key, signature, group, expiration=None):
session = db_session.get_session()
with session.begin():
q = session.query(models.Host)
q = q.filter(models.Host.name == name)
try:
host = q.one()
except exc.NoResultFound:
host = models.Host(name=name,
latest_generation=0,
group=group)
else:
if host.group != group:
raise exception.GroupStatusChanged(name=name)
host.latest_generation += 1
host.keys.append(models.Key(signature=signature,
enc_key=key,
generation=host.latest_generation,
expiration=expiration))
session.add(host)
return host.latest_generation
def get_key(self, name, generation=None, group=None):
session = db_session.get_session()
query = session.query(models.Host, models.Key)
query = query.filter(models.Host.id == models.Key.host_id)
query = query.filter(models.Host.name == name)
if group is not None:
query = query.filter(models.Host.group == group)
if generation is not None:
query = query.filter(models.Key.generation == generation)
else:
query = query.filter(models.Host.latest_generation ==
models.Key.generation)
try:
result = query.one()
except exc.NoResultFound:
return None
return {'name': result.Host.name,
'group': result.Host.group,
'key': result.Key.enc_key,
'signature': result.Key.signature,
'generation': result.Key.generation,
'expiration': result.Key.expiration}

View File

@ -1,17 +0,0 @@
# 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 migrate.versioning.shell import main
if __name__ == '__main__':
main(debug=False, repository='.')

View File

@ -1,20 +0,0 @@
[db_settings]
# Used to identify which repository this database is versioned under.
# You can use the name of your project.
repository_id=kds
# The name of the database table used to track the schema version.
# This name shouldn't already be used by your project.
# If this is changed once a database is under version control, you'll need to
# change the table name in each database too.
version_table=migrate_version
# When committing a change script, Migrate will attempt to generate the
# sql for all supported databases; normally, if one of them fails - probably
# because you don't have that database installed - it is ignored and the
# commit continues, perhaps ending successfully.
# Databases in this list MUST compile successfully during a commit, or the
# entire commit will fail. List the databases your application will actually
# be using to ensure your updates to that database work properly.
# This must be a list; example: ['postgres','sqlite']
required_dbs=[]

View File

@ -1,76 +0,0 @@
# 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 sqlalchemy as sql
def upgrade(migrate_engine):
meta = sql.MetaData()
meta.bind = migrate_engine
host_table = sql.Table('kds_hosts', meta,
sql.Column('id',
sql.Integer(),
primary_key=True,
autoincrement=True),
sql.Column('name',
sql.Text(),
nullable=False),
sql.Column('group',
sql.Boolean(),
nullable=False,
index=True),
sql.Column('latest_generation',
sql.Integer(),
nullable=False),
mysql_engine='InnoDB',
mysql_charset='utf8')
# MySQL can't put an index on an unbound TEXT type so if we do it this way
# it will make the index on the first 20 characters which will be fine.
sql.Index('name_idx', host_table.c.name, unique=True, mysql_length=20)
host_table.create(migrate_engine, checkfirst=True)
key_table = sql.Table('kds_keys', meta,
sql.Column('host_id',
sql.Integer(),
sql.ForeignKey('kds_hosts.id'),
primary_key=True,
autoincrement=False),
sql.Column('generation',
sql.Integer(),
primary_key=True,
autoincrement=False),
sql.Column('signature',
sql.LargeBinary(),
nullable=False),
sql.Column('enc_key',
sql.LargeBinary(),
nullable=False),
sql.Column('expiration',
sql.DateTime(),
nullable=True,
index=True),
mysql_engine='InnoDB',
mysql_charset='utf8')
key_table.create(migrate_engine, checkfirst=True)
def downgrade(migrate_engine):
meta = sql.MetaData()
meta.bind = migrate_engine
for name in ['kds_keys', 'kds_hosts']:
table = sql.Table(name, meta, autoload=True)
table.drop(migrate_engine, checkfirst=True)

View File

@ -1,32 +0,0 @@
# 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
from keystone.openstack.common.db.sqlalchemy import migration
def _repo_path():
return os.path.join(os.path.abspath(os.path.dirname(__file__)),
'migrate_repo')
def db_version_control(version=None):
return migration.db_version_control(_repo_path(), version=version)
def db_sync(version=None):
return migration.db_sync(_repo_path(), version=version)
def db_version(version=None):
return migration.db_version(_repo_path(), version)

View File

@ -1,60 +0,0 @@
# 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 sqlalchemy as sql
from sqlalchemy.ext.declarative import declarative_base
from keystone.openstack.common.db.sqlalchemy import models
class KdsBase(models.ModelBase):
pass
Base = declarative_base(cls=KdsBase)
class Host(Base):
__tablename__ = 'kds_hosts'
id = sql.Column(sql.Integer(), primary_key=True, autoincrement=True)
name = sql.Column(sql.Text(), index=True, unique=True, nullable=False)
group = sql.Column(sql.Boolean(), nullable=False, index=True)
latest_generation = sql.Column(sql.Integer(), nullable=False)
class Key(Base):
__tablename__ = 'kds_keys'
host_id = sql.Column(sql.Integer(),
sql.ForeignKey('kds_hosts.id'),
primary_key=True,
autoincrement=False)
generation = sql.Column(sql.Integer(),
primary_key=True,
autoincrement=False)
signature = sql.Column(sql.LargeBinary(),
nullable=False)
enc_key = sql.Column(sql.LargeBinary(),
nullable=False)
expiration = sql.Column(sql.DateTime(),
nullable=True,
index=True)
owner = sql.orm.relationship('Host',
backref=sql.orm.backref('keys',
order_by=sql.desc(
generation)))

View File

@ -1,177 +0,0 @@
# Copyright 2013 Red Hat, Inc.
#
# 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 base64
from Crypto.Hash import HMAC
from Crypto import Random
from keystone.openstack.common.gettextutils import _ # noqa
from keystone.openstack.common import importutils
class CryptoutilsException(Exception):
"""Generic Exception for Crypto utilities."""
message = _("An unknown error occurred in crypto utils.")
class CipherBlockLengthTooBig(CryptoutilsException):
"""The block size is too big."""
def __init__(self, requested, permitted):
msg = _("Block size of %(given)d is too big, max = %(maximum)d")
message = msg % {'given': requested, 'maximum': permitted}
super(CryptoutilsException, self).__init__(message)
class HKDFOutputLengthTooLong(CryptoutilsException):
"""The amount of Key Material asked is too much."""
def __init__(self, requested, permitted):
msg = _("Length of %(given)d is too long, max = %(maximum)d")
message = msg % {'given': requested, 'maximum': permitted}
super(CryptoutilsException, self).__init__(message)
class HKDF(object):
"""An HMAC-based Key Derivation Function implementation (RFC5869)
This class creates an object that allows to use HKDF to derive keys.
"""
def __init__(self, hashtype='SHA256'):
self.hashfn = importutils.import_module('Crypto.Hash.' + hashtype)
self.max_okm_length = 255 * self.hashfn.digest_size
def extract(self, ikm, salt=None):
"""An extract function that can be used to derive a robust key given
weak Input Key Material (IKM) which could be a password.
Returns a pseudorandom key (of HashLen octets)
:param ikm: input keying material (ex a password)
:param salt: optional salt value (a non-secret random value)
"""
if salt is None:
salt = '\x00' * self.hashfn.digest_size
return HMAC.new(salt, ikm, self.hashfn).digest()
def expand(self, prk, info, length):
"""An expand function that will return arbitrary length output that can
be used as keys.
Returns a buffer usable as key material.
:param prk: a pseudorandom key of at least HashLen octets
:param info: optional string (can be a zero-length string)
:param length: length of output keying material (<= 255 * HashLen)
"""
if length > self.max_okm_length:
raise HKDFOutputLengthTooLong(length, self.max_okm_length)
N = (length + self.hashfn.digest_size - 1) / self.hashfn.digest_size
okm = ""
tmp = ""
for block in range(1, N + 1):
tmp = HMAC.new(prk, tmp + info + chr(block), self.hashfn).digest()
okm += tmp
return okm[:length]
MAX_CB_SIZE = 256
class SymmetricCrypto(object):
"""Symmetric Key Crypto object.
This class creates a Symmetric Key Crypto object that can be used
to encrypt, decrypt, or sign arbitrary data.
:param enctype: Encryption Cipher name (default: AES)
:param hashtype: Hash/HMAC type name (default: SHA256)
"""
def __init__(self, enctype='AES', hashtype='SHA256'):
self.cipher = importutils.import_module('Crypto.Cipher.' + enctype)
self.hashfn = importutils.import_module('Crypto.Hash.' + hashtype)
def new_key(self, size):
return Random.new().read(size)
def encrypt(self, key, msg, b64encode=True):
"""Encrypt the provided msg and returns the cyphertext optionally
base64 encoded.
Uses AES-128-CBC with a Random IV by default.
The plaintext is padded to reach blocksize length.
The last byte of the block is the length of the padding.
The length of the padding does not include the length byte itself.
:param key: The Encryption key.
:param msg: the plain text.
:returns encblock: a block of encrypted data.
"""
iv = Random.new().read(self.cipher.block_size)
cipher = self.cipher.new(key, self.cipher.MODE_CBC, iv)
# CBC mode requires a fixed block size. Append padding and length of
# padding.
if self.cipher.block_size > MAX_CB_SIZE:
raise CipherBlockLengthTooBig(self.cipher.block_size, MAX_CB_SIZE)
r = len(msg) % self.cipher.block_size
padlen = self.cipher.block_size - r - 1
msg += '\x00' * padlen
msg += chr(padlen)
enc = iv + cipher.encrypt(msg)
if b64encode:
enc = base64.b64encode(enc)
return enc
def decrypt(self, key, msg, b64decode=True):
"""Decrypts the provided ciphertext, optionally base 64 encoded, and
returns the plaintext message, after padding is removed.
Uses AES-128-CBC with an IV by default.
:param key: The Encryption key.
:param msg: the ciphetext, the first block is the IV
"""
if b64decode:
msg = base64.b64decode(msg)
iv = msg[:self.cipher.block_size]
cipher = self.cipher.new(key, self.cipher.MODE_CBC, iv)
padded = cipher.decrypt(msg[self.cipher.block_size:])
l = ord(padded[-1]) + 1
plain = padded[:-l]
return plain
def sign(self, key, msg, b64encode=True):
"""Signs a message string and returns a base64 encoded signature.
Uses HMAC-SHA-256 by default.
:param key: The Signing key.
:param msg: the message to sign.
"""
h = HMAC.new(key, msg, self.hashfn)
out = h.digest()
if b64encode:
out = base64.b64encode(out)
return out

View File

@ -1,98 +0,0 @@
# 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 os
import ssl
from oslo.config import cfg
from keystone.openstack.common.gettextutils import _ # noqa
ssl_opts = [
cfg.StrOpt('ca_file',
default=None,
help="CA certificate file to use to verify "
"connecting clients"),
cfg.StrOpt('cert_file',
default=None,
help="Certificate file to use when starting "
"the server securely"),
cfg.StrOpt('key_file',
default=None,
help="Private key file to use when starting "
"the server securely"),
]
CONF = cfg.CONF
CONF.register_opts(ssl_opts, "ssl")
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)

View File

@ -1,78 +0,0 @@
# 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 webtest
import pecan.testing
from keystone.openstack.common import jsonutils
from keystone.tests.contrib.kds import base
def urljoin(*args):
return "/%s/" % "/".join([a.strip("/") for a in args])
def method_func(method):
def func(self, url, **kwargs):
kwargs['method'] = method
return self.request(url, **kwargs)
return func
class BaseTestCase(base.BaseTestCase):
METHODS = {'get': webtest.TestApp.get,
'post': webtest.TestApp.post,
'put': webtest.TestApp.put,
'patch': webtest.TestApp.patch,
'delete': webtest.TestApp.delete,
'options': webtest.TestApp.options,
'head': webtest.TestApp.head}
def setUp(self):
super(BaseTestCase, self).setUp()
root = 'keystone.contrib.kds.api.root.RootController'
self.app_config = {
'app': {
'root': root,
'modules': ['keystone.contrib.kds.api']
},
}
self.app = pecan.testing.load_test_app(self.app_config)
self.addCleanup(pecan.set_config, {}, overwrite=True)
def request(self, url, method, **kwargs):
try:
json = kwargs.pop('json')
except KeyError:
pass
else:
kwargs['content_type'] = 'application/json'
kwargs['params'] = jsonutils.dumps(json)
try:
func = self.METHODS[method.lower()]
except KeyError:
self.fail("Unsupported HTTP Method: %s" % method)
else:
return func(self.app, url, **kwargs)
get = method_func('get')
post = method_func('post')
put = method_func('put')
delete = method_func('delete')
options = method_func('options')
head = method_func('head')

View File

@ -1,28 +0,0 @@
# 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 keystone.tests.contrib.kds.api import base
class SimpleTest(base.BaseTestCase):
def test_version(self):
resp = self.get('/')
versions = resp.json['versions']
self.assertEqual(resp.status_code, 300)
host = 'http://localhost' # webtest default
self.assertEqual(versions[0]['status'], 'stable')
self.assertEqual(versions[0]['id'], 'v1.0')
self.assertEqual(versions[0]['links'][0]['href'], '%s/v1/' % host)
self.assertEqual(versions[0]['links'][0]['rel'], 'self')

View File

@ -1,29 +0,0 @@
# 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 keystone.tests.contrib.kds.api import base
def v1_url(*args):
return base.urljoin('v1', *args)
class BaseTestCase(base.BaseTestCase):
def get(self, url, *args, **kwargs):
return super(BaseTestCase, self).get(v1_url(url), *args, **kwargs)
def post(self, url, *args, **kwargs):
return super(BaseTestCase, self).post(v1_url(url), *args, **kwargs)
def put(self, url, *args, **kwargs):
return super(BaseTestCase, self).put(v1_url(url), *args, **kwargs)

View File

@ -1,28 +0,0 @@
# 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 keystone.tests.contrib.kds.api.v1 import base
class TestVersion(base.BaseTestCase):
def test_versions(self):
resp = self.get('/')
version = resp.json['version']
self.assertEqual(resp.status_code, 200)
host = 'http://localhost' # webtest default
self.assertEqual(version['id'], 'v1.0')
self.assertEqual(version['status'], 'stable')
self.assertEqual(version['links'][0]['href'], '%s/v1/' % host)
self.assertEqual(version['links'][0]['rel'], 'self')

View File

@ -1,28 +0,0 @@
# 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 keystone.contrib.kds.common import service
from keystone.openstack.common.fixture import config
from keystone.openstack.common import test
class BaseTestCase(test.BaseTestCase):
def setUp(self):
super(BaseTestCase, self).setUp()
self.config_fixture = self.useFixture(config.Config())
self.CONF = self.config_fixture.conf
service.parse_args(args=[])
def config(self, *args, **kwargs):
self.config_fixture.config(*args, **kwargs)

View File

@ -1,28 +0,0 @@
# 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 keystone.contrib.kds.db import api as db_api
from keystone.tests.contrib.kds import base
from keystone.tests.contrib.kds import fixture
class BaseTestCase(base.BaseTestCase):
scenarios = [('sqlitedb', {'sql_fixture': fixture.SqliteDb}),
('kvsdb', {'sql_fixture': fixture.KvsDb})]
def setUp(self):
super(BaseTestCase, self).setUp()
self.useFixture(self.sql_fixture())
self.DB = db_api.get_instance()

View File

@ -1,136 +0,0 @@
# 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 testscenarios import load_tests_apply_scenarios as load_tests # noqa
from keystone.contrib.kds.common import exception
from keystone.tests.contrib.kds.db import base
TEST_NAME = 'test-name'
TEST_SIG = 'test-sig'
TEST_KEY = 'test-enc'
class KeyDbTestCase(base.BaseTestCase):
def test_retrieve(self):
# Set a key and expect to get the same key back.
generation = self.DB.set_key(name=TEST_NAME,
signature=TEST_SIG,
key=TEST_KEY,
group=False)
key = self.DB.get_key(TEST_NAME)
self.assertEqual(key['name'], TEST_NAME)
self.assertEqual(key['key'], TEST_KEY)
self.assertEqual(key['signature'], TEST_SIG)
self.assertEqual(key['generation'], generation)
self.assertIs(key['group'], False)
self.assertIsNone(key['expiration'])
def test_no_key(self):
# return None if a key is not in the database
self.assertIsNone(self.DB.get_key(TEST_NAME))
def test_generations(self):
another_key = 'another-key'
# set a key and make sure that the generation is set and returned
gen1 = self.DB.set_key(name=TEST_NAME,
signature=TEST_SIG,
key=TEST_KEY,
group=False)
key1 = self.DB.get_key(TEST_NAME)
self.assertEqual(key1['key'], TEST_KEY)
self.assertEqual(key1['generation'], gen1)
# set a new key for the same name and make sure that the generation is
# updated
gen2 = self.DB.set_key(name=TEST_NAME,
signature='another-sig',
key=another_key,
group=False)
key2 = self.DB.get_key(TEST_NAME)
self.assertEqual(key2['generation'], gen2)
self.assertEqual(key2['key'], another_key)
# Check that if we ask specifically for the first key we get it back
key3 = self.DB.get_key(TEST_NAME, gen1)
self.assertEqual(key3['key'], TEST_KEY)
self.assertEqual(key3['generation'], gen1)
def test_no_group_filter(self):
# install a non group key
generation = self.DB.set_key(name=TEST_NAME,
signature=TEST_SIG,
key=TEST_KEY,
group=False)
# test that if i can retrieve and specify a non-group key
key1 = self.DB.get_key(TEST_NAME)
self.assertEqual(key1['key'], TEST_KEY)
self.assertEqual(key1['generation'], generation)
key2 = self.DB.get_key(TEST_NAME, group=False)
self.assertEqual(key2['key'], TEST_KEY)
self.assertEqual(key2['generation'], generation)
# if i ask for a group key of that name then it should fail
key3 = self.DB.get_key(TEST_NAME, group=True)
self.assertIsNone(key3)
def test_with_group_filter(self):
# install a group key
generation = self.DB.set_key(name=TEST_NAME,
signature=TEST_SIG,
key=TEST_KEY,
group=True)
# i should be able to ask for and retrieve a group key
key1 = self.DB.get_key(TEST_NAME)
self.assertEqual(key1['key'], TEST_KEY)
self.assertEqual(key1['generation'], generation)
key2 = self.DB.get_key(TEST_NAME, group=True)
self.assertEqual(key2['key'], TEST_KEY)
self.assertEqual(key2['generation'], generation)
# if i ask for that key but not a group key it will fail
key3 = self.DB.get_key(TEST_NAME, group=False)
self.assertIsNone(key3)
def test_cant_change_group_status(self):
group_key_name = 'name1'
host_key_name = 'name2'
# install a host and group key
self.DB.set_key(name=group_key_name,
signature=TEST_SIG,
key=TEST_KEY,
group=True)
self.DB.set_key(name=host_key_name,
signature=TEST_SIG,
key=TEST_KEY,
group=False)
# should not be able to change a group key to a host key
self.assertRaises(exception.IntegrityError, self.DB.set_key,
name=group_key_name, signature='xxx', key='xxx',
group=False)
# should not be able to change a host key to a group key
self.assertRaises(exception.IntegrityError, self.DB.set_key,
name=host_key_name, signature='xxx', key='xxx',
group=True)

View File

@ -1,19 +0,0 @@
# 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 keystone.tests.contrib.kds.fixture import kvsdb
from keystone.tests.contrib.kds.fixture import sqlitedb
SqliteDb = sqlitedb.SqliteDb
KvsDb = kvsdb.KvsDb
__all__ = ['SqliteDb', 'KvsDb']

View File

@ -1,28 +0,0 @@
# 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 fixtures
from oslo.config import cfg
from keystone.contrib.kds.db import api as db_api
CONF = cfg.CONF
class KvsDb(fixtures.Fixture):
def setUp(self):
super(KvsDb, self).setUp()
CONF.set_override('backend', 'kvs', 'database')
db_api.reset()

View File

@ -1,54 +0,0 @@
# 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 fixtures
from oslo.config import cfg
from keystone.contrib.kds.db import api as db_api
from keystone.contrib.kds.db.sqlalchemy import migration
from keystone.openstack.common.db import exception as db_exception
from keystone import tests
from keystone.tests.contrib.kds import paths
CONF = cfg.CONF
class SqliteDb(fixtures.Fixture):
"""Connect to Keystone's sqlite database.
KDS is not designed with the intention that it should run within the same
database as keystone however there is nothing preventing that. There seems
to be issues regarding the conflicting CONF objects between keystone and
KDS that prevent the connection to separate databases for testing.
Therefore this fixture must simply bridge the gap back to the testing
database for keystone and setup the KDS tables.
"""
def setUp(self):
super(SqliteDb, self).setUp()
sqlite_db = os.path.abspath(paths.tmp_path('test.db'))
CONF.set_override('connection_debug', '51', 'database')
CONF.set_override('connection', 'sqlite:///%s' % sqlite_db, 'database')
db_api.reset()
tests.setup_database()
try:
migration.db_sync()
except db_exception.DbMigrationError:
migration.db_version_control(0)
migration.db_sync()

View File

@ -1,28 +0,0 @@
# 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
TEST_DIR = os.path.abspath(os.path.join(os.path.dirname(__file__)))
TMP_DIR = os.path.join(TEST_DIR, '..', '..', 'tmp')
def root_path(*args):
return os.path.join(TEST_DIR, *args)
def test_path(*args):
return os.path.join(TEST_DIR, *args)
def tmp_path(*args):
return os.path.join(TMP_DIR, *args)

View File

@ -5,7 +5,6 @@ module=db
module=db.sqlalchemy
module=config
module=colorizer
module=crypto
module=fixture
module=importutils
module=install_venv_common

View File

@ -22,9 +22,3 @@ oauthlib>=0.6
dogpile.cache>=0.5.0
jsonschema>=2.0.0,<3.0.0
pycadf>=0.1.9
# KDS exclusive dependencies
pecan>=0.4.5
pycrypto>=2.6
WSME>=0.6

View File

@ -64,9 +64,5 @@ warnerrors = True
#autodoc_tree_root = ./keystone
[entry_points]
console_scripts =
kds-api = keystone.contrib.kds.cli.api:main
kds-manage = keystone.contrib.kds.cli.manage:main
oslo.config.opts =
keystone = keystone.common.config:list_opts