Merge branch 'master' into oslo-log-integration
This commit is contained in:
commit
bc36541f52
@ -2,6 +2,7 @@ CHANGES
|
||||
=======
|
||||
|
||||
* Add oslo.log integration to Deckhand.
|
||||
* DECKHAND-10: Barbican initial integration
|
||||
* DECKHAND-2: Design core Deckhand API framework
|
||||
* Oslo config integration (#1)
|
||||
* Add ChangeLog
|
||||
|
0
deckhand/barbican/__init__.py
Normal file
0
deckhand/barbican/__init__.py
Normal file
114
deckhand/barbican/client_wrapper.py
Normal file
114
deckhand/barbican/client_wrapper.py
Normal file
@ -0,0 +1,114 @@
|
||||
# Copyright 2017 AT&T Intellectual Property. All other 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.
|
||||
|
||||
from keystoneauth1.identity import v3
|
||||
from keystoneauth1 import session
|
||||
|
||||
from deckhand.conf import config
|
||||
from deckhand import errors
|
||||
|
||||
from barbicanclient import barbican
|
||||
from barbicanclient import exceptions as barbican_exc
|
||||
|
||||
CONF = config.CONF
|
||||
|
||||
|
||||
class BarbicanClientWrapper(object):
|
||||
"""Barbican client wrapper class that encapsulates authentication logic."""
|
||||
|
||||
def __init__(self):
|
||||
"""Initialise the BarbicanClientWrapper for use."""
|
||||
self._cached_client = None
|
||||
|
||||
def _invalidate_cached_client(self):
|
||||
"""Tell the wrapper to invalidate the cached barbican-client."""
|
||||
self._cached_client = None
|
||||
|
||||
def _get_client(self, retry_on_conflict=True):
|
||||
# If we've already constructed a valid, authed client, just return
|
||||
# that.
|
||||
if retry_on_conflict and self._cached_client is not None:
|
||||
return self._cached_client
|
||||
|
||||
# TODO: Deckhand's configuration file needs to be populated with
|
||||
# correct Keysone authentication values as well as the Barbican
|
||||
# endpoint URL automatically.
|
||||
barbican_url = (CONF.barbican.api_endpoint
|
||||
if CONF.barbican.api_endpoint
|
||||
else 'http://127.0.0.1:9311')
|
||||
|
||||
keystone_auth = dict(CONF.keystone_authtoken)
|
||||
auth = v3.Password(**keystone_auth)
|
||||
sess = session.Session(auth=auth)
|
||||
|
||||
try:
|
||||
# TODO: replace with ``barbican_url``.
|
||||
cli = barbican.client.Client(endpoint=barbican_url,
|
||||
session=sess)
|
||||
# Cache the client so we don't have to reconstruct and
|
||||
# reauthenticate it every time we need it.
|
||||
if retry_on_conflict:
|
||||
self._cached_client = cli
|
||||
|
||||
except barbican_exc.HTTPAuthError:
|
||||
msg = _("Unable to authenticate Barbican client.")
|
||||
# TODO: Log the error.
|
||||
raise errors.ApiError(msg)
|
||||
|
||||
return cli
|
||||
|
||||
def _multi_getattr(self, obj, attr):
|
||||
"""Support nested attribute path for getattr().
|
||||
|
||||
:param obj: Root object.
|
||||
:param attr: Path of final attribute to get. E.g., "a.b.c.d"
|
||||
|
||||
:returns: The value of the final named attribute.
|
||||
:raises: AttributeError will be raised if the path is invalid.
|
||||
"""
|
||||
for attribute in attr.split("."):
|
||||
obj = getattr(obj, attribute)
|
||||
return obj
|
||||
|
||||
def call(self, method, *args, **kwargs):
|
||||
"""Call a barbican client method and retry on stale token.
|
||||
|
||||
:param method: Name of the client method to call as a string.
|
||||
:param args: Client method arguments.
|
||||
:param kwargs: Client method keyword arguments.
|
||||
:param retry_on_conflict: Boolean value. Whether the request should be
|
||||
retried in case of a conflict error
|
||||
(HTTP 409) or not. If retry_on_conflict is
|
||||
False the cached instance of the client
|
||||
won't be used. Defaults to True.
|
||||
"""
|
||||
retry_on_conflict = kwargs.pop('retry_on_conflict', True)
|
||||
|
||||
for attempt in range(2):
|
||||
client = self._get_client(retry_on_conflict=retry_on_conflict)
|
||||
|
||||
try:
|
||||
return self._multi_getattr(client, method)(*args, **kwargs)
|
||||
except barbican_exc.HTTPAuthError:
|
||||
# In this case, the authorization token of the cached
|
||||
# barbican-client probably expired. So invalidate the cached
|
||||
# client and the next try will start with a fresh one.
|
||||
if not attempt:
|
||||
self._invalidate_cached_client()
|
||||
# TODO: include after implementing oslo.log.
|
||||
# LOG.debug("The Barbican client became unauthorized. "
|
||||
# "Will attempt to reauthorize and try again.")
|
||||
else:
|
||||
# This code should be unreachable actually
|
||||
raise
|
26
deckhand/barbican/driver.py
Normal file
26
deckhand/barbican/driver.py
Normal file
@ -0,0 +1,26 @@
|
||||
# Copyright 2017 AT&T Intellectual Property. All other 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.
|
||||
|
||||
from deckhand.barbican import client_wrapper
|
||||
|
||||
|
||||
class BarbicanDriver(object):
|
||||
|
||||
def __init__(self):
|
||||
self.barbicanclient = client_wrapper.BarbicanClientWrapper()
|
||||
|
||||
def ca_list(self, **kwargs):
|
||||
# FIXME(felipemonteiro): Testing cas.list endpoint.
|
||||
ca_list = self.barbicanclient.call("cas.list", **kwargs)
|
||||
return ca_list
|
@ -14,6 +14,29 @@
|
||||
|
||||
from oslo_config import cfg
|
||||
|
||||
CONF = cfg.CONF
|
||||
|
||||
|
||||
keystone_auth_group = cfg.OptGroup(
|
||||
name='keystone_authtoken',
|
||||
title='Keystone Authentication Options'
|
||||
)
|
||||
|
||||
keystone_auth_opts = [
|
||||
cfg.StrOpt(name='project_domain_name',
|
||||
default='Default'),
|
||||
cfg.StrOpt(name='project_name',
|
||||
default='admin'),
|
||||
cfg.StrOpt(name='user_domain_name',
|
||||
default='Default'),
|
||||
cfg.StrOpt(name='password',
|
||||
default='devstack'),
|
||||
cfg.StrOpt(name='username',
|
||||
default='admin'),
|
||||
cfg.StrOpt(name='auth_url',
|
||||
default='http://127.0.0.1/identity/v3')
|
||||
]
|
||||
|
||||
barbican_group = cfg.OptGroup(
|
||||
name='barbican',
|
||||
title='Barbican Options',
|
||||
@ -21,7 +44,12 @@ barbican_group = cfg.OptGroup(
|
||||
Barbican options for allowing Deckhand to communicate with Barbican.
|
||||
""")
|
||||
|
||||
barbican_opts = []
|
||||
barbican_opts = [
|
||||
cfg.StrOpt(
|
||||
'api_endpoint',
|
||||
sample_default='http://barbican.example.org:9311/',
|
||||
help='URL override for the Barbican API endpoint.'),
|
||||
]
|
||||
|
||||
logging_group = cfg.OptGroup(
|
||||
name='logging',
|
||||
@ -38,10 +66,16 @@ logging_opts = [
|
||||
def register_opts(conf):
|
||||
conf.register_group(barbican_group)
|
||||
conf.register_opts(barbican_opts, group=barbican_group)
|
||||
conf.register_group(keystone_auth_group)
|
||||
conf.register_opts(keystone_auth_opts, group=keystone_auth_group)
|
||||
conf.register_group(logging_group)
|
||||
conf.register_opts(logging_opts, group=logging_group)
|
||||
|
||||
|
||||
def list_opts():
|
||||
return {barbican_group: barbican_opts,
|
||||
keystone_auth_group: keystone_auth_opts,
|
||||
logging_group: logging_opts}
|
||||
|
||||
|
||||
register_opts(CONF)
|
||||
|
@ -16,6 +16,7 @@ import falcon
|
||||
|
||||
from oslo_serialization import jsonutils as json
|
||||
|
||||
from deckhand.barbican import driver
|
||||
from deckhand.control import base as api_base
|
||||
|
||||
|
||||
@ -29,8 +30,10 @@ class SecretsResource(api_base.BaseResource):
|
||||
def __init__(self, **kwargs):
|
||||
super(SecretsResource, self).__init__(**kwargs)
|
||||
self.authorized_roles = ['user']
|
||||
self.barbican_driver = driver.BarbicanDriver()
|
||||
|
||||
def on_get(self, req, resp):
|
||||
# TODO(felipemonteiro): Implement this API endpoint.
|
||||
resp.body = json.dumps({'secrets': 'test_secrets'})
|
||||
ca_list = self.barbican_driver.ca_list() # Random endpoint to test.
|
||||
resp.body = json.dumps({'secrets': [c.to_dict() for c in ca_list]})
|
||||
resp.status = falcon.HTTP_200
|
||||
|
@ -12,7 +12,7 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
from deckhand.control import api
|
||||
from .control import api
|
||||
|
||||
|
||||
def start_deckhand():
|
||||
@ -20,4 +20,4 @@ def start_deckhand():
|
||||
|
||||
|
||||
# Callable to be used by uwsgi.
|
||||
deckhand = start_deckhand()
|
||||
deckhand_callable = start_deckhand()
|
||||
|
47
etc/deckhand/deckhand.conf.sample
Normal file
47
etc/deckhand/deckhand.conf.sample
Normal file
@ -0,0 +1,47 @@
|
||||
[DEFAULT]
|
||||
|
||||
|
||||
[barbican]
|
||||
#
|
||||
# Barbican options for allowing Deckhand to communicate with Barbican.
|
||||
|
||||
#
|
||||
# From deckhand.conf
|
||||
#
|
||||
|
||||
# URL override for the Barbican API endpoint. (string value)
|
||||
#api_endpoint = http://barbican.example.org:9311/
|
||||
|
||||
|
||||
[keystone_authtoken]
|
||||
|
||||
#
|
||||
# From deckhand.conf
|
||||
#
|
||||
|
||||
# (string value)
|
||||
#signing_dir = <None>
|
||||
|
||||
# (string value)
|
||||
#cafile = <None>
|
||||
|
||||
# (string value)
|
||||
#project_domain_name = Default
|
||||
|
||||
# (string value)
|
||||
#project_name = admin
|
||||
|
||||
# (string value)
|
||||
#user_domain_name = Default
|
||||
|
||||
# (string value)
|
||||
#password = devstack
|
||||
|
||||
# (string value)
|
||||
#username = admin
|
||||
|
||||
# (string value)
|
||||
#auth_url = http://127.0.0.1/identity
|
||||
|
||||
# (string value)
|
||||
#auth_type = password
|
@ -3,12 +3,11 @@ falcon==1.1.0
|
||||
pbr!=2.1.0,>=2.0.0 # Apache-2.0
|
||||
six>=1.9.0 # MIT
|
||||
stevedore>=1.20.0 # Apache-2.0
|
||||
keystoneauth1>=2.21.0 # Apache-2.0
|
||||
oslo.config>=3.22.0 # Apache-2.0
|
||||
oslo.context>=2.14.0 # Apache-2.0
|
||||
oslo.log>=3.22.0 # Apache-2.0
|
||||
oslo.serialization>=1.10.0 # Apache-2.0
|
||||
oslo.utils>=3.20.0 # Apache-2.0
|
||||
oslo.i18n!=3.15.2,>=2.1.0 # Apache-2.0
|
||||
|
||||
python-barbicanclient>=4.0.0 # Apache-2.0
|
||||
keystoneauth1>=2.21.0 # Apache-2.0
|
||||
|
Loading…
Reference in New Issue
Block a user