215 lines
8.0 KiB
Python
215 lines
8.0 KiB
Python
# (c) Copyright 2015-2016 Hewlett Packard Enterprise Development LP
|
|
#
|
|
# 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 barbican.api import controllers
|
|
from barbican.common import hrefs
|
|
from barbican.common import resources as res
|
|
from barbican.common import utils
|
|
from barbican import i18n as u
|
|
from barbican.model import repositories as repo
|
|
from barbican.plugin.util import multiple_backends
|
|
|
|
LOG = utils.getLogger(__name__)
|
|
|
|
|
|
def _secret_store_not_found():
|
|
"""Throw exception indicating secret store not found."""
|
|
pecan.abort(404, u._('Not Found. Secret store not found.'))
|
|
|
|
|
|
def _preferred_secret_store_not_found():
|
|
"""Throw exception indicating secret store not found."""
|
|
pecan.abort(404, u._('Not Found. No preferred secret store defined for '
|
|
'this project.'))
|
|
|
|
|
|
def _multiple_backends_not_enabled():
|
|
"""Throw exception indicating multiple backends support is not enabled."""
|
|
pecan.abort(404, u._('Not Found. Multiple backends support is not enabled '
|
|
'in service configuration.'))
|
|
|
|
|
|
def convert_secret_store_to_response_format(secret_store):
|
|
data = secret_store.to_dict_fields()
|
|
data['secret_store_plugin'] = data.pop('store_plugin')
|
|
data['secret_store_ref'] = hrefs.convert_secret_stores_to_href(
|
|
data['secret_store_id'])
|
|
# no need to pass store id as secret_store_ref is returned
|
|
data.pop('secret_store_id', None)
|
|
return data
|
|
|
|
|
|
class PreferredSecretStoreController(controllers.ACLMixin):
|
|
"""Handles preferred secret store set/removal requests."""
|
|
|
|
def __init__(self, secret_store):
|
|
LOG.debug(u._('=== Creating PreferredSecretStoreController ==='))
|
|
self.secret_store = secret_store
|
|
self.proj_store_repo = repo.get_project_secret_store_repository()
|
|
|
|
@pecan.expose(generic=True)
|
|
def index(self, **kwargs):
|
|
pecan.abort(405) # HTTP 405 Method Not Allowed as default
|
|
|
|
@index.when(method='DELETE', template='json')
|
|
@controllers.handle_exceptions(u._('Removing preferred secret store'))
|
|
@controllers.enforce_rbac('secretstore_preferred:delete')
|
|
def on_delete(self, external_project_id, **kw):
|
|
LOG.debug(u._('Start: Remove project preferred secret-store for store'
|
|
' id %s'), self.secret_store.id)
|
|
|
|
project = res.get_or_create_project(external_project_id)
|
|
|
|
project_store = self.proj_store_repo.get_secret_store_for_project(
|
|
project.id, None, suppress_exception=True)
|
|
if project_store is None:
|
|
_preferred_secret_store_not_found()
|
|
|
|
self.proj_store_repo.delete_entity_by_id(
|
|
entity_id=project_store.id,
|
|
external_project_id=external_project_id)
|
|
pecan.response.status = 204
|
|
|
|
@index.when(method='POST', template='json')
|
|
@controllers.handle_exceptions(u._('Setting preferred secret store'))
|
|
@controllers.enforce_rbac('secretstore_preferred:post')
|
|
def on_post(self, external_project_id, **kwargs):
|
|
LOG.debug(u._('Start: Set project preferred secret-store for store '),
|
|
'id %s', self.secret_store.id)
|
|
|
|
project = res.get_or_create_project(external_project_id)
|
|
|
|
self.proj_store_repo.create_or_update_for_project(project.id,
|
|
self.secret_store.id)
|
|
|
|
pecan.response.status = 204
|
|
|
|
|
|
class SecretStoreController(controllers.ACLMixin):
|
|
"""Handles secret store retrieval requests."""
|
|
|
|
def __init__(self, secret_store):
|
|
LOG.debug(u._('=== Creating SecretStoreController ==='))
|
|
self.secret_store = secret_store
|
|
|
|
@pecan.expose()
|
|
def _lookup(self, action, *remainder):
|
|
if (action == 'preferred'):
|
|
return PreferredSecretStoreController(self.secret_store), remainder
|
|
else:
|
|
pecan.abort(405)
|
|
|
|
@pecan.expose(generic=True)
|
|
def index(self, **kwargs):
|
|
pecan.abort(405) # HTTP 405 Method Not Allowed as default
|
|
|
|
@index.when(method='GET', template='json')
|
|
@controllers.handle_exceptions(u._('Secret store retrieval'))
|
|
@controllers.enforce_rbac('secretstore:get')
|
|
def on_get(self, external_project_id):
|
|
LOG.debug("== Getting secret store for %s", self.secret_store.id)
|
|
return convert_secret_store_to_response_format(self.secret_store)
|
|
|
|
|
|
class SecretStoresController(controllers.ACLMixin):
|
|
"""Handles secret-stores list requests."""
|
|
|
|
def __init__(self):
|
|
LOG.debug('Creating SecretStoresController')
|
|
self.secret_stores_repo = repo.get_secret_stores_repository()
|
|
self.proj_store_repo = repo.get_project_secret_store_repository()
|
|
|
|
def __getattr__(self, name):
|
|
route_table = {
|
|
'global-default': self.get_global_default,
|
|
'preferred': self.get_preferred,
|
|
}
|
|
if name in route_table:
|
|
return route_table[name]
|
|
raise AttributeError
|
|
|
|
@pecan.expose()
|
|
def _lookup(self, secret_store_id, *remainder):
|
|
if not utils.is_multiple_backends_enabled():
|
|
_multiple_backends_not_enabled()
|
|
|
|
secret_store = self.secret_stores_repo.get(entity_id=secret_store_id,
|
|
suppress_exception=True)
|
|
if not secret_store:
|
|
_secret_store_not_found()
|
|
return SecretStoreController(secret_store), remainder
|
|
|
|
@pecan.expose(generic=True)
|
|
def index(self, **kwargs):
|
|
pecan.abort(405) # HTTP 405 Method Not Allowed as default
|
|
|
|
@index.when(method='GET', template='json')
|
|
@controllers.handle_exceptions(u._('List available secret stores'))
|
|
@controllers.enforce_rbac('secretstores:get')
|
|
def on_get(self, external_project_id, **kw):
|
|
LOG.debug(u._('Start SecretStoresController on_get: listing secret '
|
|
'stores'))
|
|
if not utils.is_multiple_backends_enabled():
|
|
_multiple_backends_not_enabled()
|
|
|
|
res.get_or_create_project(external_project_id)
|
|
|
|
secret_stores = self.secret_stores_repo.get_all()
|
|
|
|
resp_list = []
|
|
for store in secret_stores:
|
|
item = convert_secret_store_to_response_format(store)
|
|
resp_list.append(item)
|
|
|
|
resp = {'secret_stores': resp_list}
|
|
|
|
return resp
|
|
|
|
@pecan.expose(generic=True, template='json')
|
|
@controllers.handle_exceptions(u._('Retrieve global default secret store'))
|
|
@controllers.enforce_rbac('secretstores:get_global_default')
|
|
def get_global_default(self, external_project_id, **kw):
|
|
LOG.debug(u._('Start secret-stores get global default secret store'))
|
|
|
|
if not utils.is_multiple_backends_enabled():
|
|
_multiple_backends_not_enabled()
|
|
|
|
res.get_or_create_project(external_project_id)
|
|
|
|
store = multiple_backends.get_global_default_secret_store()
|
|
|
|
return convert_secret_store_to_response_format(store)
|
|
|
|
@pecan.expose(generic=True, template='json')
|
|
@controllers.handle_exceptions(u._('Retrieve project preferred store'))
|
|
@controllers.enforce_rbac('secretstores:get_preferred')
|
|
def get_preferred(self, external_project_id, **kw):
|
|
LOG.debug(u._('Start secret-stores get preferred secret store'))
|
|
|
|
if not utils.is_multiple_backends_enabled():
|
|
_multiple_backends_not_enabled()
|
|
|
|
project = res.get_or_create_project(external_project_id)
|
|
|
|
project_store = self.proj_store_repo.get_secret_store_for_project(
|
|
project.id, None, suppress_exception=True)
|
|
|
|
if project_store is None:
|
|
_preferred_secret_store_not_found()
|
|
|
|
return convert_secret_store_to_response_format(
|
|
project_store.secret_store)
|