From 1941fbd6763df40ffa08ac97efc5a97131b62117 Mon Sep 17 00:00:00 2001 From: Elvin Tubillara Date: Wed, 9 Sep 2015 15:03:47 -0500 Subject: [PATCH] Add filter to secret list for acl secrets Adds a ACL only filter when getting the list of secrets. If 'http://barbican:9311/v1/secrets/acl_only=true' is given then the list of secrets returned should only contain secrets that the user is on the ACL for (regardless of project). If acl_only is false or is not given, then the default project based behaviour will be used. DocImpact APIImpact Change-Id: I8e511d29b77ce15d2000ee2876a12cf6a95771c6 Closes-Bug: #1459780 --- barbican/api/controllers/secrets.py | 9 ++++- barbican/model/repositories.py | 12 +++++-- barbican/tests/api/controllers/test_acls.py | 37 +++++++++++++++++++++ doc/source/api/reference/secrets.rst | 37 +++++++++++---------- 4 files changed, 74 insertions(+), 21 deletions(-) diff --git a/barbican/api/controllers/secrets.py b/barbican/api/controllers/secrets.py index 3a93c41b1..a3050ad42 100644 --- a/barbican/api/controllers/secrets.py +++ b/barbican/api/controllers/secrets.py @@ -270,6 +270,11 @@ class SecretsController(controllers.ACLMixin): # the default should be used. bits = 0 + ctxt = controllers._get_barbican_context(pecan.request) + user_id = None + if ctxt: + user_id = ctxt.user + result = self.secret_repo.get_by_create_date( external_project_id, offset_arg=kw.get('offset', 0), @@ -278,7 +283,9 @@ class SecretsController(controllers.ACLMixin): alg=kw.get('alg'), mode=kw.get('mode'), bits=bits, - suppress_exception=True + suppress_exception=True, + acl_only=kw.get('acl_only', None), + user_id=user_id ) secrets, offset, limit, total = result diff --git a/barbican/model/repositories.py b/barbican/model/repositories.py index 84155bdc7..fedfd74f5 100755 --- a/barbican/model/repositories.py +++ b/barbican/model/repositories.py @@ -593,7 +593,7 @@ class SecretRepo(BaseRepo): def get_by_create_date(self, external_project_id, offset_arg=None, limit_arg=None, name=None, alg=None, mode=None, bits=0, secret_type=None, suppress_exception=False, - session=None): + session=None, acl_only=None, user_id=None): """Returns a list of secrets The returned secrets are ordered by the date they were created at @@ -625,8 +625,14 @@ class SecretRepo(BaseRepo): if secret_type: query = query.filter(models.Secret.secret_type == secret_type) - query = query.join(models.Project) - query = query.filter(models.Project.external_id == external_project_id) + if acl_only and acl_only.lower() == 'true' and user_id: + query = query.join(models.SecretACL) + query = query.join(models.SecretACLUser) + query = query.filter(models.SecretACLUser.user_id == user_id) + else: + query = query.join(models.Project) + query = query.filter( + models.Project.external_id == external_project_id) total = query.count() end_offset = offset + limit diff --git a/barbican/tests/api/controllers/test_acls.py b/barbican/tests/api/controllers/test_acls.py index 0c30eb151..7a81f0c30 100644 --- a/barbican/tests/api/controllers/test_acls.py +++ b/barbican/tests/api/controllers/test_acls.py @@ -490,6 +490,43 @@ class WhenTestingSecretACLsResource(utils.BarbicanAPIBaseTestCase, expect_errors=True) self.assertEqual(405, resp.status_int) + def test_list_secrets_with_no_acls_and_acl_only_should_be_empty(self): + """Return list should be empty""" + creator_user_id = 'creatorUserID' + self._create_secret_with_creator_user( + self.app, creator_user_id) + + resp = self.app.get( + '/secrets/?acl_only=TRUE') + self.assertEqual(200, resp.status_int) + self.assertEqual([], resp.json['secrets']) + + def test_list_secrets_with_acls(self): + """Return List should not include secrets with no ACL for user""" + creator_user_id = 'creatorUserID' + secret_uuid_acl_1 = self._create_secret_with_creator_user( + self.app, creator_user_id) + secret_uuid_acl_2 = self._create_secret_with_creator_user( + self.app, creator_user_id) + secret_uuid_no_acl = self._create_secret_with_creator_user( + self.app, creator_user_id) + create_acls( + self.app, 'secrets', secret_uuid_acl_1, + read_user_ids=[creator_user_id], + read_project_access=False) + + create_acls( + self.app, 'secrets', secret_uuid_acl_2, + read_user_ids=[creator_user_id], + read_project_access=False) + resp = self.app.get( + '/secrets/?acl_only=TrUe') + self.assertEqual(200, resp.status_int) + secret_list = resp.json.get('secrets') + self.assertEqual(len(secret_list), 2) + + self.assertNotIn(secret_uuid_no_acl, secret_list) + class WhenTestingContainerAclsResource(utils.BarbicanAPIBaseTestCase, TestACLsWithContextMixin): diff --git a/doc/source/api/reference/secrets.rst b/doc/source/api/reference/secrets.rst index 62275a045..a78532a7f 100644 --- a/doc/source/api/reference/secrets.rst +++ b/doc/source/api/reference/secrets.rst @@ -17,23 +17,26 @@ make a separate call to get the secret details to view the secret. Parameters ********** -+--------+---------+----------------------------------------------------------------+ -| Name | Type | Description | -+========+=========+================================================================+ -| offset | integer | The starting index within the total list of the secrets that | -| | | you would like to retrieve. | -+--------+---------+----------------------------------------------------------------+ -| limit | integer | The maximum number of records to return (up to 100). The | -| | | default limit is 10. | -+--------+---------+----------------------------------------------------------------+ -| name | string | Selects all secrets with name equal to this value. | -+--------+---------+----------------------------------------------------------------+ -| bits | integer | Selects all secrets with bit_length equal to this value. | -+--------+---------+----------------------------------------------------------------+ -| alg | string | Selects all secrets with algorithm equal to this value. | -+--------+---------+----------------------------------------------------------------+ -| mode | string | Selects all secrets with mode equal to this value. | -+--------+---------+----------------------------------------------------------------+ ++----------+---------+----------------------------------------------------------------+ +| Name | Type | Description | ++==========+=========+================================================================+ +| offset | integer | The starting index within the total list of the secrets that | +| | | you would like to retrieve. | ++----------+---------+----------------------------------------------------------------+ +| limit | integer | The maximum number of records to return (up to 100). The | +| | | default limit is 10. | ++----------+---------+----------------------------------------------------------------+ +| name | string | Selects all secrets with name equal to this value. | ++----------+---------+----------------------------------------------------------------+ +| bits | integer | Selects all secrets with bit_length equal to this value. | ++----------+---------+----------------------------------------------------------------+ +| alg | string | Selects all secrets with algorithm equal to this value. | ++----------+---------+----------------------------------------------------------------+ +| mode | string | Selects all secrets with mode equal to this value. | ++----------+---------+----------------------------------------------------------------+ +| acl_only | boolean | Selects all secrets with an ACL that contains the user. | +| | | Project scope is ignored. | ++----------+---------+----------------------------------------------------------------+ .. _secret_response_attributes: