Merge "Pin barbican-tempest-plugin for jobs in EM"
diff --git a/.zuul.yaml b/.zuul.yaml
index 8ed8cfb..011f03c 100644
--- a/.zuul.yaml
+++ b/.zuul.yaml
@@ -7,6 +7,7 @@
       jobs:
         - barbican-tempest-plugin-simple-crypto
         - barbican-tempest-plugin-simple-crypto-secure-rbac
+        - barbican-tempest-plugin-simple-crypto-2023-1
         - barbican-tempest-plugin-simple-crypto-zed
         - barbican-tempest-plugin-simple-crypto-yoga
         - barbican-tempest-plugin-simple-crypto-xena
@@ -58,6 +59,19 @@
         - barbican-tempest-plugin
 
 - job:
+    name: barbican-tempest-plugin-simple-crypto-2023-1
+    parent: barbican-tempest-plugin-simple-crypto
+    nodeset: openstack-single-node-jammy
+    override-checkout: stable/2023.1
+    vars:
+      devstack_local_conf:
+        test-config:
+          $TEMPEST_CONFIG:
+            key_manager:
+              min_microversion: '1.0'
+              max_microversion: '1.1'
+
+- job:
     name: barbican-tempest-plugin-simple-crypto-zed
     parent: barbican-tempest-plugin-simple-crypto
     nodeset: openstack-single-node-focal
@@ -140,12 +154,19 @@
             oslo_policy:
               enforce_new_defaults: True
               enforce_scope: True
+            secretstore:
+              enable_multiple_secret_stores: True
+              stores_lookup_suffix: simple_crypto
+            secretstore:simple_crypto:
+              secret_store_plugin: store_crypto
+              crypto_plugin: simple_crypto
+              global_default: true
         test-config:
           $TEMPEST_CONFIG:
-            auth:
-              tempest_roles: member
             barbican_rbac_scope_verification:
               enforce_scope: True
+            barbican_tempest:
+              enable_multiple_secret_stores: True
 
 - job:
     name: barbican-tempest-plugin-simple-crypto-secure-rbac-yoga
diff --git a/README.rst b/README.rst
index 6ee45c6..929d44f 100644
--- a/README.rst
+++ b/README.rst
@@ -22,4 +22,4 @@
 
 Bugs
 ----
-Please report bugs to: https://storyboard.openstack.org/#!/project/openstack/barbican-tempest-plugin
+Please report bugs to: http://bugs.launchpad.net/barbican
diff --git a/barbican_tempest_plugin/config.py b/barbican_tempest_plugin/config.py
index da78d15..c358aee 100644
--- a/barbican_tempest_plugin/config.py
+++ b/barbican_tempest_plugin/config.py
@@ -43,7 +43,12 @@
                     "min_microversion and max_microversion. "
                     "If both values are not specified, Tempest avoids tests "
                     "which require a microversion. Valid values are string "
-                    "with format 'X.Y' or string 'latest'")
+                    "with format 'X.Y' or string 'latest'"),
+    cfg.StrOpt('region',
+               default='regionOne',
+               help="The barbican region name to use. If no such region is"
+                    "found in the service catalog, the first found one is "
+                    "used.")
 ]
 
 barbican_tempest_group = cfg.OptGroup(
@@ -90,6 +95,10 @@
                 default=True,
                 help="Does the test environment enforce glance image "
                      "verification?"),
+    cfg.BoolOpt('certificate_validation',
+                default=True,
+                help="Does the test environment enforce image signature"
+                     "certificate validation?")
 ]
 
 barbican_rbac_scope_verification_group = cfg.OptGroup(
diff --git a/barbican_tempest_plugin/services/key_manager/json/base.py b/barbican_tempest_plugin/services/key_manager/json/base.py
index dedc0fd..d4a2a8a 100644
--- a/barbican_tempest_plugin/services/key_manager/json/base.py
+++ b/barbican_tempest_plugin/services/key_manager/json/base.py
@@ -9,10 +9,13 @@
 # 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 tempest import config
 from tempest.lib.common import rest_client
 
+CONF = config.CONF
 
 _DEFAULT_SERVICE_TYPE = 'key-manager'
+_DEFAULT_REGION = CONF.key_manager.region
 _MICROVERSION_HEADER = 'OpenStack-API-Version'
 
 
@@ -22,6 +25,7 @@
 
     def __init__(self, *args, **kwargs):
         kwargs['service'] = _DEFAULT_SERVICE_TYPE
+        kwargs['region'] = _DEFAULT_REGION
         super().__init__(*args, **kwargs)
 
     def get_headers(self, accept_type=None, send_type=None):
diff --git a/barbican_tempest_plugin/services/key_manager/json/secret_stores_client.py b/barbican_tempest_plugin/services/key_manager/json/secret_stores_client.py
index cb5fd5e..6d3094c 100644
--- a/barbican_tempest_plugin/services/key_manager/json/secret_stores_client.py
+++ b/barbican_tempest_plugin/services/key_manager/json/secret_stores_client.py
@@ -49,12 +49,10 @@
 
     def set_preferred_secret_store(self, secret_store_id):
         uri = '/v1/secret-stores/{}/preferred'.format(secret_store_id)
-        resp, body = self.post(uri)
-        self.expected_success(200, resp.status)
-        return json.loads(body.decode('UTF-8'))
+        resp, body = self.post(uri, None)
+        self.expected_success(204, resp.status)
 
     def unset_preferred_secret_store(self, secret_store_id):
         uri = '/v1/secret-stores/{}/preferred'.format(secret_store_id)
         resp, body = self.delete(uri)
-        self.expected_success(200, resp.status)
-        return json.loads(body.decode('UTF-8'))
+        self.expected_success(204, resp.status)
diff --git a/barbican_tempest_plugin/tests/api/base.py b/barbican_tempest_plugin/tests/api/base.py
index c098978..aa500f7 100644
--- a/barbican_tempest_plugin/tests/api/base.py
+++ b/barbican_tempest_plugin/tests/api/base.py
@@ -81,22 +81,16 @@
     def setup_clients(cls):
         super(BaseKeyManagerTest, cls).setup_clients()
         os = getattr(cls, 'os_%s' % cls.credentials[0])
-        cls.consumer_client = os.secret_v1.ConsumerClient(
-            service='key-manager'
-        )
-        cls.container_client = os.secret_v1.ContainerClient(
-            service='key-manager'
-        )
-        cls.order_client = os.secret_v1.OrderClient(service='key-manager')
-        cls.secret_client = os.secret_v1.SecretClient(service='key-manager')
+        cls.consumer_client = os.secret_v1.ConsumerClient()
+        cls.container_client = os.secret_v1.ContainerClient()
+        cls.order_client = os.secret_v1.OrderClient()
+        cls.secret_client = os.secret_v1.SecretClient()
         cls.secret_consumer_client = os.secret_v1_1.SecretConsumerClient()
-        cls.secret_metadata_client = os.secret_v1.SecretMetadataClient(
-            service='key-manager'
-        )
+        cls.secret_metadata_client = os.secret_v1.SecretMetadataClient()
         cls.version_client = os.secret_v1_1.VersionClient()
 
         os = getattr(cls, 'os_roles_%s' % cls.credentials[1][0])
-        cls.quota_client = os.secret_v1.QuotaClient(service='key-manager')
+        cls.quota_client = os.secret_v1.QuotaClient()
 
     @classmethod
     def setup_credentials(cls):
diff --git a/barbican_tempest_plugin/tests/api/test_quotas.py b/barbican_tempest_plugin/tests/api/test_quotas.py
index 2546249..7840406 100644
--- a/barbican_tempest_plugin/tests/api/test_quotas.py
+++ b/barbican_tempest_plugin/tests/api/test_quotas.py
@@ -16,6 +16,7 @@
 
 from tempest import config
 from tempest.lib import decorators
+from tempest.lib import exceptions
 
 CONF = config.CONF
 
@@ -25,14 +26,22 @@
 
     @decorators.idempotent_id('47ebc42b-0e53-4060-b1a1-55bee2c7c43f')
     def test_get_effective_quota(self):
-        # Verify the default quota settings
-        body = self.quota_client.get_default_project_quota()
-        quotas = body.get('quotas')
-        self.assertEqual(-1, quotas.get('secrets'))
-        self.assertEqual(-1, quotas.get('cas'))
-        self.assertEqual(-1, quotas.get('orders'))
-        self.assertEqual(-1, quotas.get('containers'))
-        self.assertEqual(-1, quotas.get('consumers'))
+        if CONF.barbican_rbac_scope_verification.enforce_scope:
+            # This test is using key-manager:service-admin legacy
+            # role. User with only this role should get a Forbidden
+            # error when trying to get effective quotas in SRBAC
+            # environment.
+            self.assertRaises(
+                exceptions.Forbidden,
+                self.quota_client.get_default_project_quota)
+        else:
+            body = self.quota_client.get_default_project_quota()
+            quotas = body.get('quotas')
+            self.assertEqual(-1, quotas.get('secrets'))
+            self.assertEqual(-1, quotas.get('cas'))
+            self.assertEqual(-1, quotas.get('orders'))
+            self.assertEqual(-1, quotas.get('containers'))
+            self.assertEqual(-1, quotas.get('consumers'))
 
 
 class ProjectQuotasTest(base.BaseKeyManagerTest):
diff --git a/barbican_tempest_plugin/tests/rbac/v1/test_quotas.py b/barbican_tempest_plugin/tests/rbac/v1/test_quotas.py
index 16edc18..ffabc1e 100644
--- a/barbican_tempest_plugin/tests/rbac/v1/test_quotas.py
+++ b/barbican_tempest_plugin/tests/rbac/v1/test_quotas.py
@@ -193,3 +193,89 @@
     def setup_clients(cls):
         super().setup_clients()
         cls.client = cls.os_project_admin.secret_v1.QuotaClient()
+
+    def test_list_project_quotas(self):
+        quotas = self.client.list_quotas()
+        self.assertIn("project_quotas", quotas)
+
+    def test_get_custom_quota_for_project(self):
+        project_id = self.client.tenant_id
+        self.client.create_project_quota(
+            project_id,
+            project_quotas={
+                "secrets": 1000,
+                "orders": 1000,
+                "containers": 1000
+            })
+        quota = self.client.get_project_quota(project_id)
+        self.assertIn("project_quotas", quota)
+
+    def test_set_new_quota_for_project(self):
+        project_id = self.client.tenant_id
+        self.client.create_project_quota(
+            project_id,
+            project_quotas={
+                "secrets": 1000,
+                "orders": 1000,
+                "containers": 1000
+            })
+        quota = self.client.get_project_quota(project_id)
+        self.assertIn("project_quotas", quota)
+
+    def test_remove_custom_quota_for_project(self):
+        project_id = self.client.tenant_id
+        self.client.create_project_quota(
+            project_id,
+            project_quotas={
+                "secrets": 1000,
+                "orders": 1000,
+                "containers": 1000
+            })
+        quota = self.client.get_project_quota(project_id)
+        self.assertIn("project_quotas", quota)
+        self.client.delete_project_quota(project_id)
+        self.assertRaises(
+            exceptions.NotFound,
+            self.client.get_project_quota,
+            project_id)
+
+    def test_get_custom_quota_for_other_project(self):
+        project_id = self.other_secret_client.tenant_id
+        self.client.create_project_quota(
+            project_id,
+            project_quotas={
+                "secrets": 1000,
+                "orders": 1000,
+                "containers": 1000
+            })
+        quota = self.client.get_project_quota(project_id)
+        self.assertIn("project_quotas", quota)
+
+    def test_set_new_quota_for_other_project(self):
+        project_id = self.other_secret_client.tenant_id
+        self.client.create_project_quota(
+            project_id,
+            project_quotas={
+                "secrets": 1000,
+                "orders": 1000,
+                "containers": 1000
+            })
+        quota = self.client.get_project_quota(project_id)
+        self.assertIn("project_quotas", quota)
+
+    def test_remove_custom_quota_for_other_project(self):
+        project_id = self.other_secret_client.tenant_id
+        self.client.create_project_quota(
+            project_id,
+            project_quotas={
+                "secrets": 1000,
+                "orders": 1000,
+                "containers": 1000
+            })
+        quota = self.client.get_project_quota(project_id)
+        self.assertIn("project_quotas", quota)
+        self.client.delete_project_quota(project_id)
+        self.assertRaises(
+            exceptions.NotFound,
+            self.client.get_project_quota,
+            project_id)
diff --git a/barbican_tempest_plugin/tests/rbac/v1/test_secret_stores.py b/barbican_tempest_plugin/tests/rbac/v1/test_secret_stores.py
index 6f0a00d..6c12624 100644
--- a/barbican_tempest_plugin/tests/rbac/v1/test_secret_stores.py
+++ b/barbican_tempest_plugin/tests/rbac/v1/test_secret_stores.py
@@ -92,11 +92,7 @@
 
     @classmethod
     def skip_checks(cls):
-        """TODO(redrobot): Run this with multiple backends
-
-        We need to set up the devstack plugin to use multiple backends
-        so we can run these tests.
-        """
+        super().skip_checks()
         if not CONF.barbican_tempest.enable_multiple_secret_stores:
             raise cls.skipException("enable_multiple_secret_stores is not "
                                     "configured.  Skipping RBAC tests.")
@@ -125,6 +121,18 @@
         self.assertTrue(resp['global_default'])
 
     def test_get_preferred_secret_store(self):
+        # First use project admin to set preferred secret store
+        resp = self.do_request('list_secret_stores')
+        secret_store_id = self.ref_to_uuid(
+            resp['secret_stores'][0]['secret_store_ref']
+        )
+        admin_client = self.os_project_admin.secret_v1.SecretStoresClient()
+        self.do_request('set_preferred_secret_store',
+                        client=admin_client,
+                        secret_store_id=secret_store_id)
+
+        # Check that other users in project can view the newly set
+        # preferred secret store
         resp = self.do_request('get_preferred_secret_store')
         self.assertEqual('ACTIVE', resp['status'])
 
@@ -142,7 +150,7 @@
         secret_store_id = self.ref_to_uuid(
             resp['secret_stores'][0]['secret_store_ref']
         )
-        self.do_request('unset_peferred_secret_store',
+        self.do_request('unset_preferred_secret_store',
                         expected_status=exceptions.Forbidden,
                         secret_store_id=secret_store_id)
 
@@ -172,11 +180,10 @@
         )
         self.do_request('set_preferred_secret_store',
                         secret_store_id=secret_store_id)
-        self.do_request('unset_peferred_secret_store',
+        self.do_request('unset_preferred_secret_store',
                         secret_store_id=secret_store_id)
-        resp = self.do_request('get_preferred_secret_store')
-        self.assertEqual(secret_store_id,
-                         self.ref_to_uuid(resp['secret_store_ref']))
+        self.do_request('get_preferred_secret_store',
+                        expected_status=exceptions.NotFound)
 
 
 class ProjectReaderTests(ProjectMemberTests):
diff --git a/barbican_tempest_plugin/tests/rbac/v1/test_transport_keys.py b/barbican_tempest_plugin/tests/rbac/v1/test_transport_keys.py
index 1984943..fa142f1 100644
--- a/barbican_tempest_plugin/tests/rbac/v1/test_transport_keys.py
+++ b/barbican_tempest_plugin/tests/rbac/v1/test_transport_keys.py
@@ -112,6 +112,13 @@
         super().setup_clients()
         cls.client = cls.os_project_admin.secret_v1.TransportKeyClient()
 
+    def test_create_transport_key(self):
+        transport_key = self.client.create_transport_key(
+            plugin_name="simple-crypto",
+            transport_key="UUUU-UUUU-IIII-DDDD"
+        )
+        self.assertIn("transport_key_ref", transport_key)
+
 
 class ProjectReaderTests(ProjectMemberTests):
 
diff --git a/barbican_tempest_plugin/tests/scenario/manager.py b/barbican_tempest_plugin/tests/scenario/manager.py
index b7f8914..cb4e52c 100644
--- a/barbican_tempest_plugin/tests/scenario/manager.py
+++ b/barbican_tempest_plugin/tests/scenario/manager.py
@@ -16,7 +16,6 @@
 
 from oslo_log import log
 
-from tempest.common import image as common_image
 from tempest.common import waiters
 from tempest import config
 from tempest.lib.common.utils import data_utils
@@ -46,24 +45,16 @@
             'name': name,
             'container_format': fmt,
             'disk_format': disk_format or fmt,
+            'visibility': 'private'
         }
-        if CONF.image_feature_enabled.api_v1:
-            params['is_public'] = 'False'
-            params['properties'] = properties
-            params = {'headers': common_image.image_meta_to_headers(**params)}
-        else:
-            params['visibility'] = 'private'
-            # Additional properties are flattened out in the v2 API.
-            params.update(properties)
+        # Additional properties are flattened out in the v2 API.
+        params.update(properties)
         body = self.image_client.create_image(**params)
         image = body['image'] if 'image' in body else body
         self.addCleanup(self.image_client.delete_image, image['id'])
         self.assertEqual("queued", image['status'])
         with open(path, 'rb') as image_file:
-            if CONF.image_feature_enabled.api_v1:
-                self.image_client.update_image(image['id'], data=image_file)
-            else:
-                self.image_client.store_image_file(image['id'], image_file)
+            self.image_client.store_image_file(image['id'], image_file)
 
         if CONF.image_feature_enabled.import_image:
             available_stores = []
diff --git a/barbican_tempest_plugin/tests/scenario/test_certificate_validation.py b/barbican_tempest_plugin/tests/scenario/test_certificate_validation.py
index e64952c..2f22329 100644
--- a/barbican_tempest_plugin/tests/scenario/test_certificate_validation.py
+++ b/barbican_tempest_plugin/tests/scenario/test_certificate_validation.py
@@ -11,6 +11,7 @@
 # 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 testtools
 
 from oslo_log import log as logging
 from tempest.common import utils
@@ -79,6 +80,9 @@
 
     @decorators.idempotent_id('6d354881-35a6-4568-94b8-2204bbf67b29')
     @utils.services('compute', 'image')
+    @testtools.skipUnless(
+        CONF.image_signature_verification.certificate_validation,
+        "Image signature certificate validation is not enforced")
     def test_signed_image_invalid_cert_boot_failure(self):
         """Test that Nova refuses to boot an unvalidated signed image.