diff --git a/functionaltests/client/__init__.py b/functionaltests/client/__init__.py index 70a50994..7453542c 100644 --- a/functionaltests/client/__init__.py +++ b/functionaltests/client/__init__.py @@ -32,3 +32,4 @@ CONF.register_opt(cfg.StrOpt('password'), group='keymanager') CONF.register_opt(cfg.StrOpt('project_name'), group='keymanager') CONF.register_opt(cfg.StrOpt('project_id'), group='keymanager') CONF.register_opt(cfg.IntOpt('max_payload_size'), group='keymanager') +CONF.register_opt(cfg.StrOpt('project_domain_name'), group='keymanager') diff --git a/functionaltests/client/v1/behaviors/base_behaviors.py b/functionaltests/client/v1/behaviors/base_behaviors.py new file mode 100644 index 00000000..7237d922 --- /dev/null +++ b/functionaltests/client/v1/behaviors/base_behaviors.py @@ -0,0 +1,52 @@ +""" +Copyright 2015 Rackspace + +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 tempest.openstack.common import log as logging + + +class BaseBehaviors(object): + + def __init__(self, client): + self.LOG = logging.getLogger(type(self).__name__) + self.client = client + self.created_entities = [] + + def get_json(self, response): + json_data = dict() + + try: + json_data = response.json() + except ValueError as e: + self.LOG.exception(e) + self.LOG.error("Error converting response to JSON: %s", e.message) + self.LOG.error("Response Content: %s", response.content) + + return json_data + + def get_id_from_href(self, href): + """Returns the id from reference. + + The id must be the last item in the href. + + :param href: The href containing the id. + :returns the id portion of the href + """ + + item_id = None + if href and len(href) > 0: + base, item_id = os.path.split(href) + return item_id diff --git a/functionaltests/client/v1/behaviors/secret_behaviors.py b/functionaltests/client/v1/behaviors/secret_behaviors.py new file mode 100644 index 00000000..89d19f05 --- /dev/null +++ b/functionaltests/client/v1/behaviors/secret_behaviors.py @@ -0,0 +1,95 @@ +""" +Copyright 2015 Rackspace + +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 functionaltests.client.v1.behaviors import base_behaviors + + +class SecretBehaviors(base_behaviors.BaseBehaviors): + + def create_secret(self, data): + """Creates a Barbican client secret object. + + This does not store the object in the database. + + :param data: Data for creation of the barbican object. + :return: Barbican client secret object + """ + return self.client.secrets.create(**data) + + def store_secret(self, secret): + """Stores a secret object in the barbican datastore. + + Creating a secret in the client only creates the Secret object. + The secret is not saved to the database until a store is called. + + :param secret: A barbican client secret object + :return: The ref to the created secret + """ + + resp = secret.store() + + if resp: + self.created_entities.append(resp) + + return resp + + def get_secret(self, secret_ref, payload_content_type=None): + """Retrieves a secret and its payload. + + :param secret_ref: A secret reference + :param payload_content_type: The secrets content type + :return: A barbican secret object with all meta and payload + information + """ + + return self.client.secrets.get( + secret_ref, + payload_content_type=payload_content_type) + + def get_secrets(self, limit=10, offset=0): + """Handles getting a list of secrets. + + :param limit: limits number of returned secrets + :param offset: represents how many records to skip before retrieving + the list + :return: A list of secret objects + """ + + return self.client.secrets.list(limit=limit, offset=offset) + + def delete_secret(self, secret_ref, expected_fail=False): + """Delete a secret. + + :param secret_ref: HATEOS ref of the secret to be deleted + :param expected_fail: If test is expected to fail the deletion + :return: On failure will return a string + """ + resp = self.client.secrets.delete(secret_ref) + + if not expected_fail: + self.created_entities.remove(secret_ref) + + return resp + + def delete_all_created_secrets(self): + """Delete all of the secrets that we have created.""" + slist = [] + + for entity in self.created_entities: + slist.append(entity) + + for secret_ref in slist: + self.delete_secret(secret_ref) diff --git a/functionaltests/client/v1/smoke/test_secrets.py b/functionaltests/client/v1/smoke/test_secrets.py new file mode 100644 index 00000000..8b7be335 --- /dev/null +++ b/functionaltests/client/v1/smoke/test_secrets.py @@ -0,0 +1,145 @@ +# Copyright (c) 2015 Rackspace, 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. +from testtools import testcase +from functionaltests.client import base +from functionaltests.client.v1.behaviors import secret_behaviors +from functionaltests import utils + +secret_create_defaults_data = { + "name": "AES key", + "expiration": "2018-02-28T19:14:44.180394", + "algorithm": "aes", + "bit_length": 256, + "mode": "cbc", + "payload": "gF6+lLoF3ohA9aPRpt+6bQ==", + "payload_content_type": "application/octet-stream", + "payload_content_encoding": "base64", +} + +secret_create_nones_data = { + "name": None, + "expiration": None, + "algorithm": None, + "bit_length": None, + "mode": None, + "payload": "gF6+lLoF3ohA9aPRpt+6bQ==", + "payload_content_type": "application/octet-stream", + "payload_content_encoding": "base64", +} + + +@utils.parameterized_test_case +class SecretsTestCase(base.TestCase): + + def setUp(self): + super(SecretsTestCase, self).setUp() + self.behaviors = secret_behaviors.SecretBehaviors(self.barbicanclient) + + def tearDown(self): + self.behaviors.delete_all_created_secrets() + super(SecretsTestCase, self).tearDown() + + @testcase.attr('positive') + def test_create_secret_defaults(self): + """Creates a secret with default values""" + test_model = self.behaviors.create_secret(secret_create_defaults_data) + + secret_ref = self.behaviors.store_secret(test_model) + self.assertIsNotNone(secret_ref) + + @testcase.attr('positive') + def test_secret_create_defaults_no_expiration(self): + """Covers creating a secret without an expiration.""" + test_model = self.behaviors.create_secret(secret_create_defaults_data) + test_model.expiration = None + + secret_ref = self.behaviors.store_secret(test_model) + self.assertIsNotNone(secret_ref) + + @utils.parameterized_dataset({ + 'alphanumeric': ['1f34ds'], + 'punctuation': ['~!@#$%^&*()_+`-={}[]|:;<>,.?'], + 'uuid': ['54262d9d-4bc7-4821-8df0-dc2ca8e112bb'], + 'len_255': [str(bytearray().zfill(255))], + 'empty': [''], + 'null': [None] + }) + @testcase.attr('positive') + def test_secret_get_defaults_metadata_w_valid_name(self, name): + """Covers getting and checking a secret's metadata.""" + test_model = self.behaviors.create_secret(secret_create_defaults_data) + test_model.name = name + + secret_ref = self.behaviors.store_secret(test_model) + self.assertIsNotNone(secret_ref) + + get_resp = self.behaviors.get_secret(secret_ref) + self.assertEqual(get_resp.status, "ACTIVE") + self.assertEqual(get_resp.name, name) + self.assertEqual(get_resp.mode, test_model.mode) + self.assertEqual(get_resp.algorithm, test_model.algorithm) + self.assertEqual(get_resp.bit_length, test_model.bit_length) + + @testcase.attr('positive') + def test_secret_delete_defaults(self): + """Covers deleting a secret.""" + test_model = self.behaviors.create_secret(secret_create_defaults_data) + + secret_ref = self.behaviors.store_secret(test_model) + + del_response = self.behaviors.delete_secret(secret_ref) + self.assertIsNone(del_response) + + @testcase.attr('positive') + def test_secret_delete_minimal_secret_w_no_metadata(self): + """Covers deleting a secret with nones data.""" + test_model = self.behaviors.create_secret(secret_create_nones_data) + + secret_ref = self.behaviors.store_secret(test_model) + self.assertIsNotNone(secret_ref) + + del_resp = self.behaviors.delete_secret(secret_ref) + self.assertIsNone(del_resp) + + @testcase.attr('positive') + def test_secret_get_defaults_payload(self): + """Covers getting a secret's payload data.""" + test_model = self.behaviors.create_secret(secret_create_defaults_data) + + secret_ref = self.behaviors.store_secret(test_model) + + get_resp = self.behaviors.get_secret( + secret_ref, + payload_content_type=test_model.payload_content_type) + self.assertEqual(get_resp.payload, test_model.payload) + + @testcase.attr('positive') + def test_secrets_get_defaults_multiple_secrets(self): + """Covers getting a list of secrets. + + Creates 11 secrets then returns a list of 5 secrets + """ + limit = 5 + offset = 5 + total = 10 + + for i in range(0, total + 1): + test_model = self.behaviors.create_secret( + secret_create_defaults_data) + self.behaviors.store_secret(test_model) + + secret_list = self.behaviors.get_secrets(limit=limit, + offset=offset) + self.assertEqual(len(secret_list), limit)