Add functional tests for Barbican key manager wrapper
Creates the initial functional testing infrastructure for Castellan. Functional tests are run using: tox -e functional The Barbican wrapper tests require running local Barbican and Keystone instances. The functional testing config parameters can be overwritten by creating a config file at /etc/castellan/castellan-functional.conf. A sample config can be generated using: tox -e genconfig The generated sample config can be found at etc/castellan/castellan-functional.conf Implements: blueprint add-barbican-key-manager Change-Id: Ideb9b1f01e51d85ff56575d8ab6ac970053a9604
This commit is contained in:
parent
a6c9df4849
commit
573235913f
@ -20,4 +20,4 @@ from oslotest import base
|
||||
|
||||
class TestCase(base.BaseTestCase):
|
||||
|
||||
"""Test case base class for all unit tests."""
|
||||
"""Test case base class for all tests."""
|
||||
|
0
castellan/tests/functional/__init__.py
Normal file
0
castellan/tests/functional/__init__.py
Normal file
67
castellan/tests/functional/config.py
Normal file
67
castellan/tests/functional/config.py
Normal file
@ -0,0 +1,67 @@
|
||||
# Copyright (c) The Johns Hopkins University/Applied Physics Laboratory
|
||||
# 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 os
|
||||
|
||||
from oslo_config import cfg
|
||||
|
||||
TEST_CONF = None
|
||||
|
||||
identity_group = cfg.OptGroup(name='identity')
|
||||
identity_options = [
|
||||
cfg.StrOpt('uri',
|
||||
default='http://localhost:5000/v3',
|
||||
help='Keystone endpoint'),
|
||||
cfg.StrOpt('username',
|
||||
default='admin',
|
||||
help='Keystone username'),
|
||||
cfg.StrOpt('password',
|
||||
default='secretadmin',
|
||||
help='Password used with Keystone username'),
|
||||
cfg.StrOpt('project_name',
|
||||
default='admin',
|
||||
help='Name of project, used by the given username')]
|
||||
|
||||
|
||||
def setup_config(config_file=''):
|
||||
global TEST_CONF
|
||||
TEST_CONF = cfg.ConfigOpts()
|
||||
|
||||
TEST_CONF.register_group(identity_group)
|
||||
TEST_CONF.register_opts(identity_options, group=identity_group)
|
||||
|
||||
config_to_load = []
|
||||
local_config = './../../../etc/castellan/castellan-functional.conf'
|
||||
if os.path.isfile(config_file):
|
||||
config_to_load.append(config_file)
|
||||
elif os.path.isfile(local_config):
|
||||
config_to_load.append(local_config)
|
||||
else:
|
||||
config_to_load.append('/etc/castellan/castellan-functional.conf')
|
||||
|
||||
TEST_CONF(
|
||||
(), # Required to load an anonymous config
|
||||
default_config_files=config_to_load
|
||||
)
|
||||
|
||||
|
||||
def get_config():
|
||||
if not TEST_CONF:
|
||||
setup_config()
|
||||
return TEST_CONF
|
||||
|
||||
|
||||
def list_opts():
|
||||
yield identity_group.name, identity_options
|
0
castellan/tests/functional/key_manager/__init__.py
Normal file
0
castellan/tests/functional/key_manager/__init__.py
Normal file
@ -0,0 +1,148 @@
|
||||
# Copyright (c) 2015 The Johns Hopkins University/Applied Physics Laboratory
|
||||
# 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.
|
||||
|
||||
"""
|
||||
Functional test cases for the Barbican key manager.
|
||||
|
||||
Note: This requires local running instances of Barbican and Keystone.
|
||||
"""
|
||||
|
||||
import uuid
|
||||
|
||||
from barbicanclient import exceptions as barbican_exceptions
|
||||
from keystoneclient.v3 import client
|
||||
from oslo_context import context
|
||||
|
||||
from castellan.common import exception
|
||||
from castellan.key_manager import barbican_key_manager
|
||||
from castellan.key_manager import symmetric_key
|
||||
from castellan.tests.functional import config
|
||||
from castellan.tests.functional.key_manager import test_key_manager
|
||||
|
||||
|
||||
CONF = config.get_config()
|
||||
|
||||
|
||||
class BarbicanKeyManagerTestCase(test_key_manager.KeyManagerTestCase):
|
||||
|
||||
def _create_key_manager(self):
|
||||
return barbican_key_manager.BarbicanKeyManager()
|
||||
|
||||
def setUp(self):
|
||||
super(BarbicanKeyManagerTestCase, self).setUp()
|
||||
username = CONF.identity.username
|
||||
password = CONF.identity.password
|
||||
project_name = CONF.identity.project_name
|
||||
auth_url = CONF.identity.uri
|
||||
keystone_client = client.Client(username=username,
|
||||
password=password,
|
||||
project_name=project_name,
|
||||
auth_url=auth_url)
|
||||
self.ctxt = context.RequestContext(
|
||||
auth_token=keystone_client.auth_token)
|
||||
|
||||
def tearDown(self):
|
||||
super(BarbicanKeyManagerTestCase, self).tearDown()
|
||||
|
||||
def test_create_key(self):
|
||||
key_uuid = self.key_mgr.create_key(self.ctxt,
|
||||
algorithm='AES',
|
||||
length=256)
|
||||
self.addCleanup(self.key_mgr.delete_key, self.ctxt, key_uuid)
|
||||
self.assertIsNotNone(key_uuid)
|
||||
|
||||
def test_create_null_context(self):
|
||||
self.assertRaises(exception.Forbidden,
|
||||
self.key_mgr.create_key, None, 'AES', 256)
|
||||
|
||||
def test_delete_symmetric_key(self):
|
||||
key_uuid = self.key_mgr.create_key(self.ctxt,
|
||||
algorithm='AES',
|
||||
length=256)
|
||||
self.key_mgr.delete_key(self.ctxt, key_uuid)
|
||||
try:
|
||||
self.key_mgr.get_key(self.ctxt, key_uuid)
|
||||
except barbican_exceptions.HTTPClientError as e:
|
||||
self.assertEqual(404, e.status_code)
|
||||
else:
|
||||
self.fail('No exception when deleting non-existent key')
|
||||
|
||||
def test_delete_null_context(self):
|
||||
key_uuid = self.key_mgr.create_key(self.ctxt,
|
||||
algorithm='AES',
|
||||
length=256)
|
||||
self.addCleanup(self.key_mgr.delete_key, self.ctxt, key_uuid)
|
||||
self.assertRaises(exception.Forbidden,
|
||||
self.key_mgr.delete_key, None, key_uuid)
|
||||
|
||||
def test_delete_null_key(self):
|
||||
self.assertRaises(exception.KeyManagerError,
|
||||
self.key_mgr.delete_key, self.ctxt, None)
|
||||
|
||||
def test_delete_unknown_key(self):
|
||||
bad_key_uuid = str(uuid.uuid4())
|
||||
self.assertRaises(barbican_exceptions.HTTPClientError,
|
||||
self.key_mgr.delete_key, self.ctxt, bad_key_uuid)
|
||||
|
||||
def test_get_key(self):
|
||||
secret_key = b'\x01\x02\xA0\xB3'
|
||||
key = symmetric_key.SymmetricKey('AES', secret_key)
|
||||
|
||||
uuid = self.key_mgr.store_key(self.ctxt, key)
|
||||
self.addCleanup(self.key_mgr.delete_key, self.ctxt, uuid)
|
||||
|
||||
retrieved_key = self.key_mgr.get_key(self.ctxt, uuid)
|
||||
self.assertEqual(key.get_encoded(), retrieved_key.get_encoded())
|
||||
|
||||
def test_get_null_context(self):
|
||||
key_uuid = self.key_mgr.create_key(self.ctxt,
|
||||
algorithm='AES',
|
||||
length=256)
|
||||
self.assertRaises(exception.Forbidden,
|
||||
self.key_mgr.get_key, None, key_uuid)
|
||||
|
||||
def test_get_null_key(self):
|
||||
key_uuid = self.key_mgr.create_key(self.ctxt,
|
||||
algorithm='AES',
|
||||
length=256)
|
||||
self.addCleanup(self.key_mgr.delete_key, self.ctxt, key_uuid)
|
||||
self.assertRaises(exception.KeyManagerError,
|
||||
self.key_mgr.get_key, self.ctxt, None)
|
||||
|
||||
def test_get_unknown_key(self):
|
||||
key_uuid = self.key_mgr.create_key(self.ctxt,
|
||||
algorithm='AES',
|
||||
length=256)
|
||||
self.addCleanup(self.key_mgr.delete_key, self.ctxt, key_uuid)
|
||||
bad_key_uuid = str(uuid.uuid4())
|
||||
self.assertRaises(barbican_exceptions.HTTPClientError,
|
||||
self.key_mgr.get_key, self.ctxt, bad_key_uuid)
|
||||
|
||||
def test_store(self):
|
||||
secret_key = b'\x01\x02\xA0\xB3'
|
||||
key = symmetric_key.SymmetricKey('AES', secret_key)
|
||||
|
||||
uuid = self.key_mgr.store_key(self.ctxt, key)
|
||||
self.addCleanup(self.key_mgr.delete_key, self.ctxt, uuid)
|
||||
|
||||
retrieved_key = self.key_mgr.get_key(self.ctxt, uuid)
|
||||
self.assertEqual(key.get_encoded(), retrieved_key.get_encoded())
|
||||
|
||||
def test_store_null_context(self):
|
||||
secret_key = b'\x01\x02\xA0\xB3'
|
||||
key = symmetric_key.SymmetricKey('AES', secret_key)
|
||||
|
||||
self.assertRaises(exception.Forbidden,
|
||||
self.key_mgr.store_key, None, key)
|
31
castellan/tests/functional/key_manager/test_key_manager.py
Normal file
31
castellan/tests/functional/key_manager/test_key_manager.py
Normal file
@ -0,0 +1,31 @@
|
||||
# Copyright (c) 2015 The Johns Hopkins University/Applied Physics Laboratory
|
||||
# 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.
|
||||
|
||||
"""
|
||||
Test cases for the key manager.
|
||||
"""
|
||||
|
||||
from castellan.tests import base
|
||||
|
||||
|
||||
class KeyManagerTestCase(base.TestCase):
|
||||
|
||||
def _create_key_manager(self):
|
||||
raise NotImplementedError()
|
||||
|
||||
def setUp(self):
|
||||
super(KeyManagerTestCase, self).setUp()
|
||||
|
||||
self.key_mgr = self._create_key_manager()
|
4
etc/castellan/functional-config-generator.conf
Normal file
4
etc/castellan/functional-config-generator.conf
Normal file
@ -0,0 +1,4 @@
|
||||
[DEFAULT]
|
||||
output_file = etc/castellan/castellan-functional.conf.sample
|
||||
wrap_width = 79
|
||||
namespace = castellan.tests.functional.config
|
@ -23,6 +23,10 @@ classifier =
|
||||
packages =
|
||||
castellan
|
||||
|
||||
[entry_points]
|
||||
oslo.config.opts =
|
||||
castellan.tests.functional.config = castellan.tests.functional.config:list_opts
|
||||
|
||||
[build_sphinx]
|
||||
source-dir = doc/source
|
||||
build-dir = doc/build
|
||||
|
15
tox.ini
15
tox.ini
@ -25,6 +25,21 @@ commands = python setup.py testr --coverage --testr-args='{posargs}'
|
||||
[testenv:docs]
|
||||
commands = python setup.py build_sphinx
|
||||
|
||||
[testenv:functional]
|
||||
usedevelop = True
|
||||
install_command = pip install -U {opts} {packages}
|
||||
setenv =
|
||||
VIRTUAL_ENV={envdir}
|
||||
OS_TEST_PATH=./castellan/tests/functional
|
||||
deps = -r{toxinidir}/requirements.txt
|
||||
-r{toxinidir}/test-requirements.txt
|
||||
commands = python setup.py testr --slowest --testr-args='{posargs}'
|
||||
|
||||
[testenv:genconfig]
|
||||
commands =
|
||||
oslo-config-generator --config-file=etc/castellan/functional-config-generator.conf
|
||||
#TODO(kfarr): add config generator for main Castellan options
|
||||
|
||||
[flake8]
|
||||
# H803 skipped on purpose per list discussion.
|
||||
# E123, E125 skipped as they are invalid PEP-8.
|
||||
|
Loading…
Reference in New Issue
Block a user