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):
|
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 =
|
packages =
|
||||||
castellan
|
castellan
|
||||||
|
|
||||||
|
[entry_points]
|
||||||
|
oslo.config.opts =
|
||||||
|
castellan.tests.functional.config = castellan.tests.functional.config:list_opts
|
||||||
|
|
||||||
[build_sphinx]
|
[build_sphinx]
|
||||||
source-dir = doc/source
|
source-dir = doc/source
|
||||||
build-dir = doc/build
|
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]
|
[testenv:docs]
|
||||||
commands = python setup.py build_sphinx
|
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]
|
[flake8]
|
||||||
# H803 skipped on purpose per list discussion.
|
# H803 skipped on purpose per list discussion.
|
||||||
# E123, E125 skipped as they are invalid PEP-8.
|
# E123, E125 skipped as they are invalid PEP-8.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user