Renaming ACL creator-only to project-access flag

In vancouver summit, it was decided that 'project-access' flag is more
clear than 'creator-only' flag mentioned in spec. The renamed flag
more clearly reflects the intended behavior associated with this flag.

As part of this change, following changes have been.
Column renamed in secret_acls and container_acls tables.
Updated existing creator_only flag values as now project_access flag
is negation of existing flag value.

Updated model as now default project_access value is True.
Updated controller logic to reflect default change.
Updated policy to reflect expected flag value.

Modified all tests to reflect flag rename and expected reverse value.

Updated ACL docs to reflect flag rename

Change-Id: I67942ed3efb1918c04efaff7ce31156750cb4207
This commit is contained in:
Arun Kant
2015-06-03 16:28:52 -07:00
parent 47ec34f112
commit b46302077c
14 changed files with 289 additions and 289 deletions
+8 -8
View File
@@ -190,11 +190,11 @@ class ACLMixin(object):
Token user is looked into users list present for each acl operation.
If there is a match, it means that ACL data is applicable for policy
logic. Policy logic requires data as dictionary so this method capture
acl's operation, creator_only data in that format.
acl's operation, project_access data in that format.
For operation value, matching ACL record's operation is stored in dict
as key and value both.
creator_only flag is intended to make secret/container private for a
project_access flag is intended to make secret/container private for a
given operation. It doesn't require user match. So its captured in dict
format where key is prefixed with related operation and flag is used as
its value.
@@ -208,14 +208,14 @@ class ACLMixin(object):
and token user is among the ACL users defined for 'read' and 'list'
operation.
{'read': 'read', 'list': 'list', 'read_creator_only': False,
'list_creator_only': False }
{'read': 'read', 'list': 'list', 'read_project_access': True,
'list_project_access': True }
Its possible that ACLs are defined without any user, they just
have creator_only flag set. This means only creator can read or list
have project_access flag set. This means only creator can read or list
ACL entities. In that case, dictionary output can be as follows.
{'read_creator_only': True, 'list_creator_only': True }
{'read_project_access': False, 'list_project_access': False }
"""
ctxt = _get_barbican_context(req)
@@ -223,8 +223,8 @@ class ACLMixin(object):
return None
acl_dict = {acl.operation: acl.operation for acl in acl_list
if ctxt.user in acl.to_dict_fields().get('users', [])}
co_dict = {'%s_creator_only' % acl.operation: acl.creator_only for acl
in acl_list if acl.creator_only is not None}
co_dict = {'%s_project_access' % acl.operation: acl.project_access for
acl in acl_list if acl.project_access is not None}
acl_dict.update(co_dict)
return acl_dict
+22 -22
View File
@@ -33,7 +33,7 @@ def _convert_acl_to_response_format(acl, acls_dict):
acl_data = {} # dict for each acl operation data
acl_data['creator-only'] = fields['creator_only']
acl_data['project-access'] = fields['project_access']
acl_data['users'] = fields.get('users', [])
acl_data['created'] = fields['created']
acl_data['updated'] = fields['updated']
@@ -41,7 +41,7 @@ def _convert_acl_to_response_format(acl, acls_dict):
acls_dict[operation] = acl_data
DEFAULT_ACL = {'read': {'creator-only': False}}
DEFAULT_ACL = {'read': {'project-access': True}}
class SecretACLsController(controllers.ACLMixin):
@@ -96,7 +96,7 @@ class SecretACLsController(controllers.ACLMixin):
"users":[
"5ecb18f341894e94baca9e8c7b6a824a"
],
"creator-only":true
"project-access":true
}
}
"""
@@ -107,16 +107,16 @@ class SecretACLsController(controllers.ACLMixin):
self.secret.secret_acls}
for operation in itertools.ifilter(lambda x: data.get(x),
validators.ACL_OPERATIONS):
creator_only = data[operation].get('creator-only')
project_access = data[operation].get('project-access')
user_ids = data[operation].get('users')
s_acl = None
if operation in existing_acls_map: # update if matching acl exists
s_acl = existing_acls_map[operation]
if creator_only is not None:
s_acl.creator_only = creator_only
if project_access is not None:
s_acl.project_access = project_access
else:
s_acl = models.SecretACL(self.secret.id, operation=operation,
creator_only=creator_only)
project_access=project_access)
self.acl_repo.create_or_replace_from(self.secret, secret_acl=s_acl,
user_ids=user_ids)
@@ -133,7 +133,7 @@ class SecretACLsController(controllers.ACLMixin):
Replaces existing secret ACL(s) with input ACL(s) data. Existing
ACL operation not specified in input are removed as part of update.
For missing creator-only in ACL, false is used as default.
For missing project-access in ACL, true is used as default.
In update, multiple operation ACL payload can be specified as
mentioned in sample below. A specific ACL can be updated by its
own id via SecretACLController patch request.
@@ -150,7 +150,7 @@ class SecretACLsController(controllers.ACLMixin):
"users":[
"5ecb18f341894e94baca9e8c7b6a824a"
],
"creator-only":true
"project-access":false
}
}
@@ -168,15 +168,15 @@ class SecretACLsController(controllers.ACLMixin):
self.secret.secret_acls}
for operation in itertools.ifilter(lambda x: data.get(x),
validators.ACL_OPERATIONS):
creator_only = data[operation].get('creator-only', False)
project_access = data[operation].get('project-access', True)
user_ids = data[operation].get('users', [])
s_acl = None
if operation in existing_acls_map: # update if matching acl exists
s_acl = existing_acls_map.pop(operation)
s_acl.creator_only = creator_only
s_acl.project_access = project_access
else:
s_acl = models.SecretACL(self.secret.id, operation=operation,
creator_only=creator_only)
project_access=project_access)
self.acl_repo.create_or_replace_from(self.secret, secret_acl=s_acl,
user_ids=user_ids)
# delete remaining existing acls as they are not present in input.
@@ -261,7 +261,7 @@ class ContainerACLsController(controllers.ACLMixin):
"users":[
"5ecb18f341894e94baca9e8c7b6a824a"
],
"creator-only":true
"project-access":false
}
}
"""
@@ -272,16 +272,16 @@ class ContainerACLsController(controllers.ACLMixin):
self.container.container_acls}
for operation in itertools.ifilter(lambda x: data.get(x),
validators.ACL_OPERATIONS):
creator_only = data[operation].get('creator-only')
project_access = data[operation].get('project-access')
user_ids = data[operation].get('users')
if operation in existing_acls_map: # update if matching acl exists
c_acl = existing_acls_map[operation]
if creator_only is not None:
c_acl.creator_only = creator_only
if project_access is not None:
c_acl.project_access = project_access
else:
c_acl = models.ContainerACL(self.container.id,
operation=operation,
creator_only=creator_only)
project_access=project_access)
self.acl_repo.create_or_replace_from(self.container,
container_acl=c_acl,
user_ids=user_ids)
@@ -299,7 +299,7 @@ class ContainerACLsController(controllers.ACLMixin):
Replaces existing container ACL(s) with input ACL(s) data. Existing
ACL operation not specified in input are removed as part of update.
For missing creator-only in ACL, false is used as default.
For missing project-access in ACL, true is used as default.
In update, multiple operation ACL payload can be specified as
mentioned in sample below. A specific ACL can be updated by its
own id via ContainerACLController patch request.
@@ -316,7 +316,7 @@ class ContainerACLsController(controllers.ACLMixin):
"users":[
"5ecb18f341894e94baca9e8c7b6a824a"
],
"creator-only":true
"project-access":false
}
}
@@ -336,15 +336,15 @@ class ContainerACLsController(controllers.ACLMixin):
self.container.container_acls}
for operation in itertools.ifilter(lambda x: data.get(x),
validators.ACL_OPERATIONS):
creator_only = data[operation].get('creator-only', False)
project_access = data[operation].get('project-access', True)
user_ids = data[operation].get('users', [])
if operation in existing_acls_map: # update if matching acl exists
c_acl = existing_acls_map.pop(operation)
c_acl.creator_only = creator_only
c_acl.project_access = project_access
else:
c_acl = models.ContainerACL(self.container.id,
operation=operation,
creator_only=creator_only)
project_access=project_access)
self.acl_repo.create_or_replace_from(self.container,
container_acl=c_acl,
user_ids=user_ids)
+1 -1
View File
@@ -630,7 +630,7 @@ class ACLValidator(ValidatorBase):
{"type": "string", "maxLength": 255}
]
},
"creator-only": {"type": "boolean"}
"project-access": {"type": "boolean"}
},
"additionalProperties": False
}
@@ -0,0 +1,54 @@
"""rename ACL creator_only to project_access
Revision ID: 6a4457517a3
Revises: 30dba269cc64
Create Date: 2015-06-03 11:54:55.187875
"""
# revision identifiers, used by Alembic.
revision = '6a4457517a3'
down_revision = '30dba269cc64'
from alembic import op
import sqlalchemy as sa
def upgrade():
ctx = op.get_context()
con = op.get_bind()
op.alter_column('secret_acls', 'creator_only', existing_type=sa.BOOLEAN(),
new_column_name='project_access')
# reverse existing flag value as project_access is negation of creator_only
op.execute('UPDATE secret_acls SET project_access = NOT project_access',
execution_options={'autocommit': True})
op.alter_column('container_acls', 'creator_only',
existing_type=sa.BOOLEAN(),
new_column_name='project_access')
# reverse existing flag value as project_access is negation of creator_only
op.execute('UPDATE container_acls SET project_access = NOT project_access',
execution_options={'autocommit': True})
def downgrade():
ctx = op.get_context()
con = op.get_bind()
op.alter_column('secret_acls', 'project_access',
existing_type=sa.BOOLEAN(), new_column_name='creator_only')
op.execute('UPDATE secret_acls SET creator_only = NOT creator_only',
execution_options={'autocommit': True})
op.alter_column('container_acls', 'project_access',
existing_type=sa.BOOLEAN(),
new_column_name='creator_only')
op.execute('UPDATE container_acls SET creator_only = NOT creator_only',
execution_options={'autocommit': True})
+11 -10
View File
@@ -1053,7 +1053,7 @@ class SecretACL(BASE, ModelBase):
operation = sa.Column(sa.String(255), nullable=False)
creator_only = sa.Column(sa.Boolean, nullable=False, default=False)
project_access = sa.Column(sa.Boolean, nullable=False, default=True)
secret = orm.relationship(
'Secret', backref=orm.backref('secret_acls', lazy=False))
@@ -1065,7 +1065,8 @@ class SecretACL(BASE, ModelBase):
__table_args__ = (sa.UniqueConstraint(
'secret_id', 'operation', name='_secret_acl_operation_uc'),)
def __init__(self, secret_id, operation, creator_only=None, user_ids=None):
def __init__(self, secret_id, operation, project_access=None,
user_ids=None):
"""Creates secret ACL entity."""
super(SecretACL, self).__init__()
@@ -1079,8 +1080,8 @@ class SecretACL(BASE, ModelBase):
raise exception.MissingArgumentError(msg.format("operation"))
self.operation = operation
if creator_only is not None:
self.creator_only = creator_only
if project_access is not None:
self.project_access = project_access
self.status = States.ACTIVE
if user_ids is not None and isinstance(user_ids, list):
userids = set(user_ids) # remove duplicate if any
@@ -1103,7 +1104,7 @@ class SecretACL(BASE, ModelBase):
fields = {'acl_id': self.id,
'secret_id': self.secret_id,
'operation': self.operation,
'creator_only': self.creator_only}
'project_access': self.project_access}
if users:
fields['users'] = users
return fields
@@ -1128,7 +1129,7 @@ class ContainerACL(BASE, ModelBase):
operation = sa.Column(sa.String(255), nullable=False)
creator_only = sa.Column(sa.Boolean, nullable=False, default=False)
project_access = sa.Column(sa.Boolean, nullable=False, default=True)
container = orm.relationship(
'Container', backref=orm.backref('container_acls', lazy=False))
@@ -1140,7 +1141,7 @@ class ContainerACL(BASE, ModelBase):
__table_args__ = (sa.UniqueConstraint(
'container_id', 'operation', name='_container_acl_operation_uc'),)
def __init__(self, container_id, operation, creator_only=None,
def __init__(self, container_id, operation, project_access=None,
user_ids=None):
"""Creates container ACL entity."""
super(ContainerACL, self).__init__()
@@ -1155,8 +1156,8 @@ class ContainerACL(BASE, ModelBase):
raise exception.MissingArgumentError(msg.format("operation"))
self.operation = operation
if creator_only is not None:
self.creator_only = creator_only
if project_access is not None:
self.project_access = project_access
self.status = States.ACTIVE
if user_ids is not None and isinstance(user_ids, list):
@@ -1180,7 +1181,7 @@ class ContainerACL(BASE, ModelBase):
fields = {'acl_id': self.id,
'container_id': self.container_id,
'operation': self.operation,
'creator_only': self.creator_only}
'project_access': self.project_access}
if users:
fields['users'] = users
return fields
+81 -80
View File
@@ -34,37 +34,38 @@ class WhenTestingSecretACLsResource(utils.BarbicanAPIBaseTestCase):
self.assertIn('/secrets/{0}/acl'.format(secret_uuid),
resp.json['acl_ref'])
acl_map = _get_acl_map(secret_uuid, is_secret=True)
# Check creator_only is False when not provided
self.assertFalse(acl_map['read']['creator_only'])
# Check project_access is True when not provided
self.assertTrue(acl_map['read']['project_access'])
def test_create_new_secret_acls_with_creator_only_true(self):
"""Should allow creating acls for a new secret with creator-only."""
def test_create_new_secret_acls_with_project_access_false(self):
"""Should allow creating acls for a new secret with project-access."""
secret_uuid, _ = create_secret(self.app)
resp = create_acls(
self.app, 'secrets', secret_uuid,
read_creator_only=True)
read_project_access=False)
self.assertEqual(200, resp.status_int)
self.assertIsNotNone(resp.json)
self.assertIn('/secrets/{0}/acl'.format(secret_uuid),
resp.json['acl_ref'])
acl_map = _get_acl_map(secret_uuid, is_secret=True)
self.assertTrue(acl_map['read']['creator_only'])
self.assertFalse(acl_map['read']['project_access'])
def test_new_secret_acls_with_invalid_creator_only_value_should_fail(self):
"""Should fail if creator-only flag is provided as string value."""
def test_new_secret_acls_with_invalid_project_access_value_should_fail(
self):
"""Should fail if project-access flag is provided as string value."""
secret_uuid, _ = create_secret(self.app)
resp = create_acls(
self.app, 'secrets', secret_uuid,
read_creator_only="False",
read_project_access="False",
read_user_ids=['u1', 'u3', 'u4'],
expect_errors=True)
self.assertEqual(400, resp.status_int)
resp = create_acls(
self.app, 'secrets', secret_uuid,
read_creator_only="None",
read_project_access="None",
expect_errors=True)
self.assertEqual(400, resp.status_int)
@@ -73,7 +74,7 @@ class WhenTestingSecretACLsResource(utils.BarbicanAPIBaseTestCase):
secret_id, _ = create_secret(self.app)
create_acls(
self.app, 'secrets', secret_id,
read_user_ids=['u1', 'u3'], read_creator_only=True)
read_user_ids=['u1', 'u3'], read_project_access=False)
resp = self.app.get(
'/secrets/{0}/acl'.format(secret_id),
@@ -82,17 +83,17 @@ class WhenTestingSecretACLsResource(utils.BarbicanAPIBaseTestCase):
self.assertIsNotNone(resp.json)
self.assertIn('read', resp.json)
self.assertTrue(resp.json['read']['creator-only'])
self.assertFalse(resp.json['read']['project-access'])
self.assertIsNotNone(resp.json['read']['created'])
self.assertIsNotNone(resp.json['read']['updated'])
self.assertEqual(set(['u1', 'u3']), set(resp.json['read']['users']))
def test_get_secret_acls_with_creator_only_data(self):
"""Read existing acls for acl when only creator-only flag is set."""
def test_get_secret_acls_with_project_access_data(self):
"""Read existing acls for acl when only project-access flag is set."""
secret_id, _ = create_secret(self.app)
create_acls(
self.app, 'secrets', secret_id,
read_creator_only=True)
read_project_access=False)
resp = self.app.get(
'/secrets/{0}/acl'.format(secret_id),
@@ -101,7 +102,7 @@ class WhenTestingSecretACLsResource(utils.BarbicanAPIBaseTestCase):
self.assertIsNotNone(resp.json)
self.assertEqual([], resp.json['read']['users'])
self.assertTrue(resp.json['read']['creator-only'])
self.assertFalse(resp.json['read']['project-access'])
self.assertIsNotNone(resp.json['read']['created'])
self.assertIsNotNone(resp.json['read']['updated'])
@@ -114,7 +115,7 @@ class WhenTestingSecretACLsResource(utils.BarbicanAPIBaseTestCase):
secret_id, _ = create_secret(self.app)
create_acls(
self.app, 'secrets', secret_id,
read_creator_only=False,
read_project_access=True,
read_user_ids=['u1', 'u3', 'u4'])
resp = self.app.get(
@@ -141,25 +142,25 @@ class WhenTestingSecretACLsResource(utils.BarbicanAPIBaseTestCase):
expect_errors=True)
self.assertEqual(405, resp.status_int)
def test_full_update_secret_acls_modify_creator_only_value(self):
"""ACLs full update with user ids where creator-only flag modified."""
def test_full_update_secret_acls_modify_project_access_value(self):
"""ACLs full update with userids where project-access flag modified."""
secret_uuid, _ = create_secret(self.app)
create_acls(
self.app, 'secrets', secret_uuid,
read_user_ids=['u1', 'u2'],
read_creator_only=True)
read_project_access=False)
# update acls with no user input so it should delete existing users
resp = update_acls(
self.app, 'secrets', secret_uuid, partial_update=False,
read_creator_only=False)
read_project_access=True)
self.assertEqual(200, resp.status_int)
self.assertIsNotNone(resp.json)
self.assertIn('/secrets/{0}/acl'.format(secret_uuid),
resp.json['acl_ref'])
acl_map = _get_acl_map(secret_uuid, is_secret=True)
self.assertFalse(acl_map['read']['creator_only'])
self.assertTrue(acl_map['read']['project_access'])
self.assertIsNone(acl_map['read'].to_dict_fields().get('users'))
def test_full_update_secret_acls_modify_users_only(self):
@@ -168,7 +169,7 @@ class WhenTestingSecretACLsResource(utils.BarbicanAPIBaseTestCase):
create_acls(
self.app, 'secrets', secret_uuid,
read_user_ids=['u1', 'u2'], read_creator_only=True)
read_user_ids=['u1', 'u2'], read_project_access=False)
resp = update_acls(
self.app, 'secrets', secret_uuid, partial_update=False,
@@ -179,7 +180,7 @@ class WhenTestingSecretACLsResource(utils.BarbicanAPIBaseTestCase):
self.assertIn('/secrets/{0}/acl'.format(secret_uuid),
resp.json['acl_ref'])
acl_map = _get_acl_map(secret_uuid, is_secret=True)
self.assertFalse(acl_map['read']['creator_only'])
self.assertTrue(acl_map['read']['project_access'])
self.assertNotIn('u2', acl_map['read'].to_dict_fields()['users'])
self.assertEqual(set(['u1', 'u3', 'u5']),
set(acl_map['read'].to_dict_fields()['users']))
@@ -213,7 +214,7 @@ class WhenTestingSecretACLsResource(utils.BarbicanAPIBaseTestCase):
acl_map = _get_acl_map(secret_uuid, is_secret=True)
# make sure 'list' operation is no longer after full update
self.assertNotIn('list', acl_map)
self.assertFalse(acl_map['read']['creator_only'])
self.assertTrue(acl_map['read']['project_access'])
self.assertEqual(set(['u1', 'u3', 'u5']),
set(acl_map['read'].to_dict_fields()['users']))
self.assertNotIn('u2', acl_map['read'].to_dict_fields()['users'])
@@ -247,7 +248,7 @@ class WhenTestingSecretACLsResource(utils.BarbicanAPIBaseTestCase):
self.assertIn('list', acl_map)
self.assertEqual(set(['u1', 'u2']),
set(acl_map['list'].to_dict_fields()['users']))
self.assertFalse(acl_map['read']['creator_only'])
self.assertTrue(acl_map['read']['project_access'])
self.assertEqual(set(['u1', 'u3', 'u5']),
set(acl_map['read'].to_dict_fields()['users']))
@@ -266,26 +267,26 @@ class WhenTestingSecretACLsResource(utils.BarbicanAPIBaseTestCase):
self.assertEqual(200, resp.status_int)
acl_map = _get_acl_map(secret_id, is_secret=True)
self.assertFalse(acl_map['read']['creator_only'])
self.assertTrue(acl_map['read']['project_access'])
def test_partial_update_secret_acls_modify_creator_only_values(self):
"""Acls partial update where creator-only flag is modified."""
def test_partial_update_secret_acls_modify_project_access_values(self):
"""Acls partial update where project-access flag is modified."""
secret_uuid, _ = create_secret(self.app)
create_acls(
self.app, 'secrets', secret_uuid,
read_user_ids=['u1', 'u2'],
read_creator_only=True)
read_project_access=False)
resp = update_acls(
self.app, 'secrets', secret_uuid, partial_update=True,
read_creator_only=False)
read_project_access=True)
self.assertEqual(200, resp.status_int)
self.assertIsNotNone(resp.json)
self.assertIn('/secrets/{0}/acl'.format(secret_uuid),
resp.json['acl_ref'])
acl_map = _get_acl_map(secret_uuid, is_secret=True)
self.assertFalse(acl_map['read']['creator_only'])
self.assertTrue(acl_map['read']['project_access'])
self.assertEqual(set(['u1', 'u2']),
set(acl_map['read'].to_dict_fields()['users']))
@@ -294,7 +295,7 @@ class WhenTestingSecretACLsResource(utils.BarbicanAPIBaseTestCase):
secret_id, _ = create_secret(self.app)
create_acls(
self.app, 'secrets', secret_id,
read_creator_only=True)
read_project_access=True)
resp = self.app.delete(
'/secrets/{0}/acl'.format(secret_id),
@@ -338,55 +339,55 @@ class WhenTestingContainerAclsResource(utils.BarbicanAPIBaseTestCase):
resp.json['acl_ref'])
acl_map = _get_acl_map(container_id, is_secret=False)
# Check creator_only is False when not provided
self.assertFalse(acl_map['read']['creator_only'])
# Check project_access is True when not provided
self.assertTrue(acl_map['read']['project_access'])
self.assertEqual(set(['u1', 'u2']),
set(acl_map['read'].to_dict_fields()['users']))
def test_create_new_container_acls_with_creator_only_false(self):
"""Should allow creating acls for a new container with creator-only."""
def test_create_new_container_acls_with_project_access_true(self):
"""Should allow creating acls for new container with project-access."""
container_id, _ = create_container(self.app)
resp = create_acls(
self.app, 'containers', container_id,
read_creator_only=False,
read_project_access=True,
read_user_ids=['u1', 'u3', 'u4'])
self.assertEqual(200, resp.status_int)
self.assertIsNotNone(resp.json)
self.assertIn('/containers/{0}/acl'.format(container_id),
resp.json['acl_ref'])
acl_map = _get_acl_map(container_id, is_secret=False)
self.assertFalse(acl_map['read']['creator_only'])
self.assertTrue(acl_map['read']['project_access'])
def test_create_new_container_acls_with_creator_only_true(self):
"""Should allow creating acls for a new container with creator-only."""
def test_create_new_container_acls_with_project_access_false(self):
"""Should allow creating acls for new container with project-access."""
container_id, _ = create_container(self.app)
resp = create_acls(
self.app, 'containers', container_id,
read_creator_only=True,
read_project_access=False,
read_user_ids=['u1', 'u3', 'u4'])
self.assertEqual(200, resp.status_int)
self.assertIsNotNone(resp.json)
self.assertIn('/containers/{0}/acl'.format(container_id),
resp.json['acl_ref'])
acl_map = _get_acl_map(container_id, is_secret=False)
self.assertTrue(acl_map['read']['creator_only'])
self.assertFalse(acl_map['read']['project_access'])
def test_container_acls_with_invalid_creator_only_value_should_fail(self):
"""Should fail if creator-only flag is provided as string value."""
def test_container_acls_with_invalid_project_access_value_fail(self):
"""Should fail if project-access flag is provided as string value."""
container_id, _ = create_container(self.app)
resp = create_acls(
self.app, 'containers', container_id,
read_creator_only="False",
read_project_access="False",
read_user_ids=['u1', 'u3', 'u4'],
expect_errors=True)
self.assertEqual(400, resp.status_int)
resp = create_acls(
self.app, 'containers', container_id,
read_creator_only="None",
read_project_access="None",
expect_errors=True)
self.assertEqual(400, resp.status_int)
@@ -395,7 +396,7 @@ class WhenTestingContainerAclsResource(utils.BarbicanAPIBaseTestCase):
container_id, _ = create_container(self.app)
create_acls(
self.app, 'containers', container_id,
read_user_ids=['u1', 'u3'], read_creator_only=True)
read_user_ids=['u1', 'u3'], read_project_access=False)
resp = self.app.get(
'/containers/{0}/acl'.format(container_id),
@@ -404,17 +405,17 @@ class WhenTestingContainerAclsResource(utils.BarbicanAPIBaseTestCase):
self.assertIsNotNone(resp.json)
self.assertIn('read', resp.json)
self.assertTrue(resp.json['read']['creator-only'])
self.assertFalse(resp.json['read']['project-access'])
self.assertIsNotNone(resp.json['read']['created'])
self.assertIsNotNone(resp.json['read']['updated'])
self.assertEqual(set(['u1', 'u3']), set(resp.json['read']['users']))
def test_get_container_acls_with_creator_only_data(self):
"""Read existing acls for acl when only creator-only flag is set."""
def test_get_container_acls_with_project_access_data(self):
"""Read existing acls for acl when only project-access flag is set."""
container_id, _ = create_container(self.app)
create_acls(
self.app, 'containers', container_id,
read_creator_only=True)
read_project_access=False)
resp = self.app.get(
'/containers/{0}/acl'.format(container_id),
@@ -423,7 +424,7 @@ class WhenTestingContainerAclsResource(utils.BarbicanAPIBaseTestCase):
self.assertIsNotNone(resp.json)
self.assertEqual([], resp.json['read']['users'])
self.assertTrue(resp.json['read']['creator-only'])
self.assertFalse(resp.json['read']['project-access'])
self.assertIsNotNone(resp.json['read']['created'])
self.assertIsNotNone(resp.json['read']['updated'])
@@ -436,7 +437,7 @@ class WhenTestingContainerAclsResource(utils.BarbicanAPIBaseTestCase):
container_id, _ = create_container(self.app)
create_acls(
self.app, 'containers', container_id,
read_creator_only=False)
read_project_access=True)
resp = self.app.get(
'/containers/{0}/acl'.format(uuid.uuid4().hex),
@@ -448,7 +449,7 @@ class WhenTestingContainerAclsResource(utils.BarbicanAPIBaseTestCase):
container_id, _ = create_container(self.app)
create_acls(
self.app, 'containers', container_id,
read_creator_only=False)
read_project_access=True)
resp = self.app.get(
'/containers/{0}/acl'.format('my_container_id'),
@@ -470,7 +471,7 @@ class WhenTestingContainerAclsResource(utils.BarbicanAPIBaseTestCase):
container_id, _ = create_container(self.app)
create_acls(
self.app, 'containers', container_id, read_creator_only=True,
self.app, 'containers', container_id, read_project_access=False,
read_user_ids=['u1', 'u2'])
resp = update_acls(
@@ -482,12 +483,12 @@ class WhenTestingContainerAclsResource(utils.BarbicanAPIBaseTestCase):
self.assertIn('/containers/{0}/acl'.format(container_id),
resp.json['acl_ref'])
acl_map = _get_acl_map(container_id, is_secret=False)
# Check creator_only is False when not provided
self.assertFalse(acl_map['read']['creator_only'])
# Check project_access is True when not provided
self.assertTrue(acl_map['read']['project_access'])
self.assertIn('u5', acl_map['read'].to_dict_fields()['users'])
def test_full_update_container_acls_modify_creator_only_values(self):
"""Acls update where user ids and creator-only flag is modified."""
def test_full_update_container_acls_modify_project_access_values(self):
"""Acls update where user ids and project-access flag is modified."""
container_id, _ = create_container(self.app)
create_acls(
@@ -496,13 +497,13 @@ class WhenTestingContainerAclsResource(utils.BarbicanAPIBaseTestCase):
resp = update_acls(
self.app, 'containers', container_id, partial_update=False,
read_creator_only=True)
read_project_access=False)
self.assertEqual(200, resp.status_int)
self.assertIsNotNone(resp.json)
self.assertIn('/containers/{0}/acl'.format(container_id),
resp.json['acl_ref'])
acl_map = _get_acl_map(container_id, is_secret=False)
self.assertTrue(acl_map['read']['creator_only'])
self.assertFalse(acl_map['read']['project_access'])
self.assertIsNone(acl_map['read'].to_dict_fields().get('users'))
def test_full_update_container_acls_with_read_users_only(self):
@@ -534,7 +535,7 @@ class WhenTestingContainerAclsResource(utils.BarbicanAPIBaseTestCase):
acl_map = _get_acl_map(container_id, is_secret=False)
# make sure 'list' operation is no longer after full update
self.assertNotIn('list', acl_map)
self.assertFalse(acl_map['read']['creator_only'])
self.assertTrue(acl_map['read']['project_access'])
self.assertEqual(set(['u1', 'u3', 'u5']),
set(acl_map['read'].to_dict_fields()['users']))
self.assertNotIn('u2', acl_map['read'].to_dict_fields()['users'])
@@ -568,7 +569,7 @@ class WhenTestingContainerAclsResource(utils.BarbicanAPIBaseTestCase):
self.assertIn('list', acl_map)
self.assertEqual(set(['u1', 'u2']),
set(acl_map['list'].to_dict_fields()['users']))
self.assertFalse(acl_map['read']['creator_only'])
self.assertTrue(acl_map['read']['project_access'])
self.assertEqual(set(['u1', 'u3', 'u5']),
set(acl_map['read'].to_dict_fields()['users']))
@@ -587,26 +588,26 @@ class WhenTestingContainerAclsResource(utils.BarbicanAPIBaseTestCase):
self.assertEqual(200, resp.status_int)
acl_map = _get_acl_map(container_id, is_secret=False)
self.assertFalse(acl_map['read']['creator_only'])
self.assertTrue(acl_map['read']['project_access'])
def test_partial_update_container_acls_modify_creator_only_values(self):
"""Acls partial update where creator-only flag is modified."""
def test_partial_update_container_acls_modify_project_access_values(self):
"""Acls partial update where project-access flag is modified."""
container_id, _ = create_container(self.app)
create_acls(
self.app, 'containers', container_id,
read_user_ids=['u1', 'u2'],
read_creator_only=True)
read_project_access=False)
resp = update_acls(
self.app, 'containers', container_id, partial_update=True,
read_creator_only=False)
read_project_access=True)
self.assertEqual(200, resp.status_int)
self.assertIsNotNone(resp.json)
self.assertIn('/containers/{0}/acl'.format(container_id),
resp.json['acl_ref'])
acl_map = _get_acl_map(container_id, is_secret=False)
self.assertFalse(acl_map['read']['creator_only'])
self.assertTrue(acl_map['read']['project_access'])
self.assertEqual(set(['u1', 'u2']),
set(acl_map['read'].to_dict_fields()['users']))
@@ -615,7 +616,7 @@ class WhenTestingContainerAclsResource(utils.BarbicanAPIBaseTestCase):
container_id, _ = create_container(self.app)
create_acls(
self.app, 'containers', container_id,
read_creator_only=False)
read_project_access=True)
resp = self.app.delete(
'/containers/{0}/acl'.format(container_id),
@@ -704,32 +705,32 @@ def create_container(app):
def create_acls(app, entity_type, entity_id, read_user_ids=None,
read_creator_only=None,
read_project_access=None,
expect_errors=False):
return manage_acls(app, entity_type, entity_id,
read_user_ids=read_user_ids,
read_creator_only=read_creator_only,
read_project_access=read_project_access,
is_update=False, partial_update=False,
expect_errors=expect_errors)
def update_acls(app, entity_type, entity_id, read_user_ids=None,
read_creator_only=None, partial_update=False,
read_project_access=None, partial_update=False,
expect_errors=False):
return manage_acls(app, entity_type, entity_id,
read_user_ids=read_user_ids,
read_creator_only=read_creator_only,
read_project_access=read_project_access,
is_update=True, partial_update=partial_update,
expect_errors=expect_errors)
def manage_acls(app, entity_type, entity_id, read_user_ids=None,
read_creator_only=None, is_update=False,
read_project_access=None, is_update=False,
partial_update=None, expect_errors=False):
request = {}
_append_acl_to_request(request, 'read', read_user_ids,
read_creator_only)
read_project_access)
cleaned_request = {key: val for key, val in request.items()
if val is not None}
@@ -748,12 +749,12 @@ def manage_acls(app, entity_type, entity_id, read_user_ids=None,
return resp
def _append_acl_to_request(req, operation, user_ids=None, creator_only=None):
def _append_acl_to_request(req, operation, user_ids=None, project_access=None):
op_dict = {}
if user_ids is not None:
op_dict['users'] = user_ids
if creator_only is not None:
op_dict['creator-only'] = creator_only
if project_access is not None:
op_dict['project-access'] = project_access
if op_dict:
req[operation] = op_dict
+10 -10
View File
@@ -465,13 +465,13 @@ class WhenCreatingStoredKeyOrders(utils.BarbicanAPIBaseTestCase,
self.assertIsInstance(order, models.Order)
def _setup_acl_order_context_and_create_order(
self, add_acls=False, read_creator_only=False, order_roles=None,
self, add_acls=False, read_project_access=True, order_roles=None,
order_user=None, expect_errors=False):
"""Helper method to setup acls, order context and return created order.
Create order uses actual oslo policy enforcer instead of being None.
Create ACLs for container if 'add_acls' is True.
Make container private when 'read_creator_only' is True.
Make container private when 'read_project_access' is False.
"""
container_name = 'rsa container name'
@@ -492,7 +492,7 @@ class WhenCreatingStoredKeyOrders(utils.BarbicanAPIBaseTestCase,
test_acls.manage_acls(
self.app, 'containers', container_id,
read_user_ids=['u1', 'u3', 'u4'],
read_creator_only=read_creator_only,
read_project_access=read_project_access,
is_update=False)
self.app.extra_environ = {
@@ -523,7 +523,7 @@ class WhenCreatingStoredKeyOrders(utils.BarbicanAPIBaseTestCase,
"""
create_resp, order_id = self._setup_acl_order_context_and_create_order(
add_acls=False, read_creator_only=False, order_roles=['creator'],
add_acls=False, read_project_access=True, order_roles=['creator'],
order_user='anyUserId', expect_errors=False)
self.assertEqual(202, create_resp.status_int)
@@ -542,7 +542,7 @@ class WhenCreatingStoredKeyOrders(utils.BarbicanAPIBaseTestCase,
"""
create_resp, _ = self._setup_acl_order_context_and_create_order(
add_acls=False, read_creator_only=False, order_roles=['observer'],
add_acls=False, read_project_access=True, order_roles=['observer'],
order_user='anyUserId', expect_errors=True)
self.assertEqual(403, create_resp.status_int)
@@ -554,7 +554,7 @@ class WhenCreatingStoredKeyOrders(utils.BarbicanAPIBaseTestCase,
successfully.
"""
create_resp, order_id = self._setup_acl_order_context_and_create_order(
add_acls=True, read_creator_only=True, order_roles=['creator'],
add_acls=True, read_project_access=False, order_roles=['creator'],
order_user=self.creator_user_id, expect_errors=False)
self.assertEqual(202, create_resp.status_int)
@@ -574,7 +574,7 @@ class WhenCreatingStoredKeyOrders(utils.BarbicanAPIBaseTestCase,
"""
create_resp, order_id = self._setup_acl_order_context_and_create_order(
add_acls=True, read_creator_only=True, order_roles=['creator'],
add_acls=True, read_project_access=False, order_roles=['creator'],
order_user='u3', expect_errors=False)
self.assertEqual(202, create_resp.status_int)
@@ -593,7 +593,7 @@ class WhenCreatingStoredKeyOrders(utils.BarbicanAPIBaseTestCase,
"""
create_resp, _ = self._setup_acl_order_context_and_create_order(
add_acls=True, read_creator_only=True, order_roles=['creator'],
add_acls=True, read_project_access=False, order_roles=['creator'],
order_user='anyProjectUser', expect_errors=True)
self.assertEqual(403, create_resp.status_int)
@@ -607,7 +607,7 @@ class WhenCreatingStoredKeyOrders(utils.BarbicanAPIBaseTestCase,
project. Order project is same as container.
"""
create_resp, order_id = self._setup_acl_order_context_and_create_order(
add_acls=True, read_creator_only=False, order_roles=['creator'],
add_acls=True, read_project_access=True, order_roles=['creator'],
order_user='anyProjectUser', expect_errors=False)
self.assertEqual(202, create_resp.status_int)
@@ -624,7 +624,7 @@ class WhenCreatingStoredKeyOrders(utils.BarbicanAPIBaseTestCase,
container successfully. Order project is same as container.
"""
create_resp, order_id = self._setup_acl_order_context_and_create_order(
add_acls=True, read_creator_only=False, order_roles=['creator'],
add_acls=True, read_project_access=True, order_roles=['creator'],
order_user=self.creator_user_id, expect_errors=False)
self.assertEqual(202, create_resp.status_int)
+19 -19
View File
@@ -318,7 +318,7 @@ class WhenTestingSecretResource(BaseTestCase):
self.setup_transport_key_repository_mock()
acl_read = models.SecretACL(secret_id=self.secret_id, operation='read',
creator_only=False,
project_access=True,
user_ids=[self.user_id, 'anyRandomId'])
self.acl_list = [acl_read]
secret = mock.MagicMock()
@@ -359,7 +359,7 @@ class WhenTestingSecretResource(BaseTestCase):
user_id=self.user_id,
project_id=self.external_project_id)
def test_should_raise_decrypt_secret_for_with_creator_only_enabled(self):
def test_should_raise_decrypt_secret_with_project_access_disabled(self):
"""Should raise authz error as secret is marked private.
As secret is private so project users should not be able to access
@@ -367,7 +367,7 @@ class WhenTestingSecretResource(BaseTestCase):
"""
self.acl_list.pop() # remove read acl from default setup
acl_read = models.SecretACL(secret_id=self.secret_id, operation='read',
creator_only=True,
project_access=False,
user_ids=['anyRandomUserX', 'aclUser1'])
self.acl_list.append(acl_read)
self._assert_fail_rbac(['admin', 'observer', 'creator', 'audit'],
@@ -377,7 +377,7 @@ class WhenTestingSecretResource(BaseTestCase):
user_id=self.user_id,
project_id=self.external_project_id)
def test_should_raise_decrypt_secret_for_with_creator_only_nolist(self):
def test_should_raise_decrypt_secret_for_with_project_access_nolist(self):
"""Should raise authz error as secret is marked private.
As secret is private so project users should not be able to access
@@ -386,7 +386,7 @@ class WhenTestingSecretResource(BaseTestCase):
"""
self.acl_list.pop() # remove read acl from default setup
acl_read = models.SecretACL(secret_id=self.secret_id, operation='read',
creator_only=True,
project_access=False,
user_ids=[])
self.acl_list.append(acl_read)
self._assert_fail_rbac(['admin', 'observer', 'creator', 'audit'],
@@ -404,7 +404,7 @@ class WhenTestingSecretResource(BaseTestCase):
"""
self.acl_list.pop() # remove read acl from default setup
acl_read = models.SecretACL(secret_id=self.secret_id, operation='read',
creator_only=True,
project_access=False,
user_ids=['anyRandomUserX', 'aclUser1'])
self.acl_list.append(acl_read)
self._assert_pass_rbac(['admin', 'observer', 'creator', 'audit',
@@ -418,7 +418,7 @@ class WhenTestingSecretResource(BaseTestCase):
def test_should_pass_decrypt_secret_different_user_valid_read_acl(self):
self.acl_list.pop() # remove read acl from default setup
acl_read = models.SecretACL(secret_id=self.secret_id, operation='read',
creator_only=False,
project_access=True,
user_ids=['anyRandomUserX', 'aclUser1'])
self.acl_list.append(acl_read)
# token project_id is different from secret's project id but another
@@ -435,7 +435,7 @@ class WhenTestingSecretResource(BaseTestCase):
self.acl_list.pop() # remove read acl from default setup
acl_read = models.SecretACL(secret_id=self.secret_id,
operation='write',
creator_only=False,
project_access=True,
user_ids=['anyRandomUserX', 'aclUser1'])
self.acl_list.append(acl_read)
# token project_id is different from secret's project id but another
@@ -502,7 +502,7 @@ class WhenTestingSecretResource(BaseTestCase):
user_id=self.user_id,
project_id=self.external_project_id)
def test_should_raise_get_secret_for_with_creator_only_enabled(self):
def test_should_raise_get_secret_for_with_project_access_disabled(self):
"""Should raise authz error as secret is marked private.
As secret is private so project users should not be able to access
@@ -510,7 +510,7 @@ class WhenTestingSecretResource(BaseTestCase):
"""
self.acl_list.pop() # remove read acl from default setup
acl_read = models.SecretACL(secret_id=self.secret_id, operation='read',
creator_only=True,
project_access=False,
user_ids=['anyRandomUserX', 'aclUser1'])
self.acl_list.append(acl_read)
self._assert_fail_rbac(['admin', 'observer', 'creator', 'audit'],
@@ -526,7 +526,7 @@ class WhenTestingSecretResource(BaseTestCase):
"""
self.acl_list.pop() # remove read acl from default setup
acl_read = models.SecretACL(secret_id=self.secret_id, operation='read',
creator_only=True,
project_access=False,
user_ids=['anyRandomUserX', 'aclUser1'])
self.acl_list.append(acl_read)
self._assert_pass_rbac(['admin', 'observer', 'creator', 'audit',
@@ -543,7 +543,7 @@ class WhenTestingSecretResource(BaseTestCase):
"""
self.acl_list.pop() # remove read acl from default setup
acl_read = models.SecretACL(secret_id=self.secret_id, operation='read',
creator_only=False,
project_access=True,
user_ids=['anyRandomUserX', 'aclUser1'])
self.acl_list.append(acl_read)
# token project_id is different from secret's project id but another
@@ -563,7 +563,7 @@ class WhenTestingSecretResource(BaseTestCase):
self.acl_list.pop() # remove read acl from default setup
acl_read = models.SecretACL(secret_id=self.secret_id,
operation='write',
creator_only=False,
project_access=True,
user_ids=['anyRandomUserX', 'aclUser1'])
self.acl_list.append(acl_read)
# token project_id is different from secret's project id but another
@@ -660,7 +660,7 @@ class WhenTestingContainerResource(BaseTestCase):
acl_read = models.ContainerACL(
container_id=self.container_id, operation='read',
creator_only=False, user_ids=[self.user_id, 'anyRandomId'])
project_access=True, user_ids=[self.user_id, 'anyRandomId'])
self.acl_list = [acl_read]
container = mock.MagicMock()
container.id = self.container_id
@@ -717,7 +717,7 @@ class WhenTestingContainerResource(BaseTestCase):
user_id=self.user_id,
project_id=self.external_project_id)
def test_should_raise_get_container_for_with_creator_only_enabled(self):
def test_should_raise_get_container_for_with_project_access_disabled(self):
"""Should raise authz error as container is marked private.
As container is private so project users should not be able to access
@@ -726,7 +726,7 @@ class WhenTestingContainerResource(BaseTestCase):
self.acl_list.pop() # remove read acl from default setup
acl_read = models.ContainerACL(
container_id=self.container_id, operation='read',
creator_only=True, user_ids=['anyRandomUserX', 'aclUser1'])
project_access=False, user_ids=['anyRandomUserX', 'aclUser1'])
self.acl_list.append(acl_read)
self._assert_fail_rbac(['admin', 'observer', 'creator', 'audit'],
self._invoke_on_get,
@@ -742,7 +742,7 @@ class WhenTestingContainerResource(BaseTestCase):
self.acl_list.pop() # remove read acl from default setup
acl_read = models.ContainerACL(
container_id=self.container_id, operation='read',
creator_only=True, user_ids=['anyRandomUserX', 'aclUser1'])
project_access=False, user_ids=['anyRandomUserX', 'aclUser1'])
self.acl_list.append(acl_read)
self._assert_pass_rbac(['admin', 'observer', 'creator', 'audit',
'bogusRole'],
@@ -761,7 +761,7 @@ class WhenTestingContainerResource(BaseTestCase):
self.acl_list.pop() # remove read acl from default setup
acl_read = models.ContainerACL(
container_id=self.container_id, operation='read',
creator_only=False, user_ids=['anyRandomUserX', 'aclUser1'])
project_access=True, user_ids=['anyRandomUserX', 'aclUser1'])
self.acl_list.append(acl_read)
self._assert_pass_rbac(['admin', 'observer', 'creator', 'audit',
'bogusRole'],
@@ -779,7 +779,7 @@ class WhenTestingContainerResource(BaseTestCase):
self.acl_list.pop() # remove read acl from default setup
acl_read = models.ContainerACL(
container_id=self.container_id, operation='write',
creator_only=False, user_ids=['anyRandomUserX', 'aclUser1'])
project_access=True, user_ids=['anyRandomUserX', 'aclUser1'])
self.acl_list.append(acl_read)
# token project_id is different from secret's project id but another
# user (from different project) has read acl for secret so should pass
+12 -11
View File
@@ -1306,11 +1306,12 @@ class WhenTestingAclValidator(utils.BaseTestCase):
self.validator = validators.ACLValidator()
@utils.parameterized_dataset({
'one_reader': [{'read': {'users': ['reader'], 'creator-only': False}}],
'one_reader': [{'read': {'users': ['reader'],
'project-access': True}}],
'two_reader': [{'read': {'users': ['r1', 'r2'],
'creator-only': False}}],
'private': [{'read': {'users': [], 'creator-only': True}}],
'default_users': [{'read': {'creator-only': True}}],
'project-access': True}}],
'private': [{'read': {'users': [], 'project-access': False}}],
'default_users': [{'read': {'project-access': False}}],
'default_creator': [{'read': {'users': ['reader']}}],
'almost_empty': [{'read': {}}],
'empty': [{}],
@@ -1320,11 +1321,11 @@ class WhenTestingAclValidator(utils.BaseTestCase):
@utils.parameterized_dataset({
'foo': ['foo'],
'bad_op': [{'bad_op': {'users': ['reader'], 'creator-only': False}}],
'bad_op': [{'bad_op': {'users': ['reader'], 'project-access': True}}],
'bad_field': [{'read': {'bad_field': ['reader'],
'creator-only': False}}],
'bad_user': [{'read': {'users': [27], 'creator-only': False}}],
'missing_op': [{'creator-only': True}],
'project-access': True}}],
'bad_user': [{'read': {'users': [27], 'project-access': True}}],
'missing_op': [{'project-access': False}],
})
def test_should_raise(self, acl_req):
self.assertRaises(excep.InvalidObject,
@@ -1332,9 +1333,9 @@ class WhenTestingAclValidator(utils.BaseTestCase):
acl_req)
@utils.parameterized_dataset({
'write': [{'write': {'users': ['writer'], 'creator-only': False}}],
'list': [{'list': {'users': ['lister'], 'creator-only': False}}],
'delete': [{'delete': {'users': ['deleter'], 'creator-only': False}}],
'write': [{'write': {'users': ['writer'], 'project-access': True}}],
'list': [{'list': {'users': ['lister'], 'project-access': True}}],
'delete': [{'delete': {'users': ['deleter'], 'project-access': True}}],
})
def test_should_raise_future(self, acl_req):
self.assertRaises(excep.InvalidObject,
@@ -117,7 +117,7 @@ class WhenTestingSecretACLRepository(database_utils.RepositoryTestCase,
secret, acl1, user_ids=['u1', 'u2'], session=session)
acl2 = self.acl_repo.create_from(models.SecretACL(
secret.id, 'write', True), session)
secret.id, 'write', False), session)
self.acl_repo.create_or_replace_from(
secret, acl2, user_ids=['u1', 'u2', 'u3'], session=session)
@@ -131,8 +131,8 @@ class WhenTestingSecretACLRepository(database_utils.RepositoryTestCase,
self.assertEqual(3, len(acls))
id_map = self._map_id_to_acl(acls)
self.assertEqual(False, id_map[acl1.id].creator_only)
self.assertEqual(True, id_map[acl2.id].creator_only)
self.assertEqual(True, id_map[acl1.id].project_access)
self.assertEqual(False, id_map[acl2.id].project_access)
self.assertEqual('read', id_map[acl1.id].operation)
self.assertEqual('write', id_map[acl2.id].operation)
self.assertEqual('delete', id_map[acl3.id].operation)
@@ -167,7 +167,7 @@ class WhenTestingSecretACLRepository(database_utils.RepositoryTestCase,
"""Check create_or_replace_from and get count call.
It modifies existing acls with users and make sure that updated users
and creator_only flag changes are returned when acls are queries by
and project_access flag changes are returned when acls are queries by
secret id. It uses get count to assert expected number of acls for that
secret.
"""
@@ -194,7 +194,7 @@ class WhenTestingSecretACLRepository(database_utils.RepositoryTestCase,
id_map = self._map_id_to_acl(acls)
# replace users in existing acls
id_map[acl1.id].creator_only = True
id_map[acl1.id].project_access = False
self.acl_repo.create_or_replace_from(
secret, id_map[acl1.id], user_ids=['u5'], session=session)
@@ -211,9 +211,9 @@ class WhenTestingSecretACLRepository(database_utils.RepositoryTestCase,
id_map = self._map_id_to_acl(acls)
self.assertEqual(3, len(acls))
self.assertEqual(True, id_map[acl1.id].creator_only)
self.assertEqual(False, id_map[acl2.id].creator_only)
self.assertEqual(False, id_map[acl3.id].creator_only)
self.assertEqual(False, id_map[acl1.id].project_access)
self.assertEqual(True, id_map[acl2.id].project_access)
self.assertEqual(True, id_map[acl3.id].project_access)
self._assert_acl_users(['u5'], acls, acl1.id)
self._assert_acl_users(['u1', 'u2', 'u3', 'u4'], acls, acl2.id)
self._assert_acl_users(['u1', 'u2', 'u4'], acls, acl3.id)
@@ -369,7 +369,7 @@ class WhenTestingContainerACLRepository(database_utils.RepositoryTestCase,
container, acl1, user_ids=['u1', 'u2'], session=session)
acl2 = self.acl_repo.create_from(models.ContainerACL(
container.id, 'write', True), session)
container.id, 'write', False), session)
self.acl_repo.create_or_replace_from(
container, acl2, user_ids=['u1', 'u2', 'u3'], session=session)
@@ -383,8 +383,8 @@ class WhenTestingContainerACLRepository(database_utils.RepositoryTestCase,
self.assertEqual(3, len(acls))
id_map = self._map_id_to_acl(acls)
self.assertEqual(False, id_map[acl1.id].creator_only)
self.assertEqual(True, id_map[acl2.id].creator_only)
self.assertEqual(True, id_map[acl1.id].project_access)
self.assertEqual(False, id_map[acl2.id].project_access)
self.assertEqual('read', id_map[acl1.id].operation)
self.assertEqual('write', id_map[acl2.id].operation)
self.assertEqual('list', id_map[acl3.id].operation)
@@ -419,7 +419,7 @@ class WhenTestingContainerACLRepository(database_utils.RepositoryTestCase,
"""Check create_or_replace_from and get count call.
It modifies existing acls with users and make sure that updated users
and creator_only flag changes are returned when acls are queries by
and project_access flag changes are returned when acls are queries by
secret id. It uses get count to assert expected number of acls for that
secret.
"""
@@ -446,7 +446,7 @@ class WhenTestingContainerACLRepository(database_utils.RepositoryTestCase,
id_map = self._map_id_to_acl(acls)
# replace users in existing acls
id_map[acl1.id].creator_only = True
id_map[acl1.id].project_access = False
self.acl_repo.create_or_replace_from(
container, id_map[acl1.id], user_ids=['u5'], session=session)
@@ -463,9 +463,9 @@ class WhenTestingContainerACLRepository(database_utils.RepositoryTestCase,
id_map = self._map_id_to_acl(acls)
self.assertEqual(3, len(acls))
self.assertEqual(True, id_map[acl1.id].creator_only)
self.assertEqual(False, id_map[acl2.id].creator_only)
self.assertEqual(False, id_map[acl3.id].creator_only)
self.assertEqual(False, id_map[acl1.id].project_access)
self.assertEqual(True, id_map[acl2.id].project_access)
self.assertEqual(True, id_map[acl3.id].project_access)
self._assert_acl_users(['u5'], acls, acl1.id)
self._assert_acl_users(['u1', 'u2', 'u3', 'u4'], acls, acl2.id)
self._assert_acl_users(['u1', 'u2', 'u4'], acls, acl3.id)
+16 -16
View File
@@ -329,24 +329,24 @@ class WhenCreatingNewSecretACL(utils.BaseTestCase):
self.secret_id = 'secret123456'
self.user_ids = ['user12345', 'user67890']
self.operation = 'read'
self.creator_only = False
self.project_access = True
def test_new_secretacl_for_given_all_input(self):
acl = models.SecretACL(self.secret_id, self.operation,
self.creator_only, self.user_ids)
self.project_access, self.user_ids)
self.assertEqual(self.secret_id, acl.secret_id)
self.assertEqual(self.operation, acl.operation)
self.assertEqual(self.creator_only, acl.creator_only)
self.assertEqual(self.project_access, acl.project_access)
self.assertTrue(all(acl_user.user_id in self.user_ids for acl_user
in acl.acl_users))
def test_new_secretacl_check_to_dict_fields(self):
acl = models.SecretACL(self.secret_id, self.operation,
self.creator_only, self.user_ids)
self.project_access, self.user_ids)
self.assertEqual(self.secret_id, acl.to_dict_fields()['secret_id'])
self.assertEqual(self.operation, acl.to_dict_fields()['operation'])
self.assertEqual(self.creator_only,
acl.to_dict_fields()['creator_only'])
self.assertEqual(self.project_access,
acl.to_dict_fields()['project_access'])
self.assertTrue(all(user_id in self.user_ids for user_id in
acl.to_dict_fields()['users']))
self.assertEqual(None, acl.to_dict_fields()['acl_id'])
@@ -357,7 +357,7 @@ class WhenCreatingNewSecretACL(utils.BaseTestCase):
self.assertEqual(acl.secret_id, self.secret_id)
self.assertEqual(0, len(acl.acl_users))
self.assertEqual(self.operation, acl.operation)
self.assertEqual(None, acl.creator_only)
self.assertEqual(None, acl.project_access)
def test_new_secretacl_with_duplicate_userids_input(self):
user_ids = list(self.user_ids)
@@ -366,7 +366,7 @@ class WhenCreatingNewSecretACL(utils.BaseTestCase):
None, user_ids=user_ids)
self.assertEqual(self.secret_id, acl.secret_id)
self.assertEqual(self.operation, acl.operation)
self.assertEqual(None, acl.creator_only)
self.assertEqual(None, acl.project_access)
self.assertEqual(2, len(acl.acl_users))
def test_should_throw_exception_missing_secret_id(self):
@@ -391,25 +391,25 @@ class WhenCreatingNewContainerACL(utils.BaseTestCase):
self.container_id = 'container123456'
self.user_ids = ['user12345', 'user67890']
self.operation = 'read'
self.creator_only = False
self.project_access = True
def test_new_containeracl_for_given_all_input(self):
acl = models.ContainerACL(self.container_id, self.operation,
self.creator_only, self.user_ids)
self.project_access, self.user_ids)
self.assertEqual(acl.container_id, self.container_id)
self.assertEqual(acl.operation, self.operation)
self.assertEqual(acl.creator_only, self.creator_only)
self.assertEqual(acl.project_access, self.project_access)
self.assertTrue(all(acl_user.user_id in self.user_ids for acl_user
in acl.acl_users))
def test_new_containeracl_check_to_dict_fields(self):
acl = models.ContainerACL(self.container_id, self.operation,
self.creator_only, self.user_ids)
self.project_access, self.user_ids)
self.assertEqual(self.container_id,
acl.to_dict_fields()['container_id'])
self.assertEqual(self.operation, acl.to_dict_fields()['operation'])
self.assertEqual(self.creator_only,
acl.to_dict_fields()['creator_only'])
self.assertEqual(self.project_access,
acl.to_dict_fields()['project_access'])
self.assertTrue(all(user_id in self.user_ids for user_id
in acl.to_dict_fields()['users']))
self.assertEqual(None, acl.to_dict_fields()['acl_id'])
@@ -420,7 +420,7 @@ class WhenCreatingNewContainerACL(utils.BaseTestCase):
self.assertEqual(self.container_id, acl.container_id)
self.assertEqual(0, len(acl.acl_users))
self.assertEqual(self.operation, acl.operation)
self.assertEqual(None, acl.creator_only)
self.assertEqual(None, acl.project_access)
def test_new_containeracl_with_duplicate_userids_input(self):
user_ids = list(self.user_ids)
@@ -429,7 +429,7 @@ class WhenCreatingNewContainerACL(utils.BaseTestCase):
True, user_ids=user_ids)
self.assertEqual(self.container_id, acl.container_id)
self.assertEqual(self.operation, acl.operation)
self.assertEqual(True, acl.creator_only)
self.assertEqual(True, acl.project_access)
self.assertEqual(2, len(acl.acl_users))
def test_should_throw_exception_missing_container_id(self):
+11 -11
View File
@@ -37,7 +37,7 @@ need to be added in related ACL users list.
An operation specific ACL definition has following attribute:
* `users`: Whitelist of users who are allowed access to target resource. In this case a user means
a Keystone user id.
* `creator-only`: Flag to mark a secret or a container private for an operation. Pass `true` to
* `project-access`: Flag to mark a secret or a container private for an operation. Pass `false` to
mark private.
To acommplish above mentioned behavior for a secret/container resource, having ACL data populated
@@ -65,14 +65,14 @@ Default ACL
By default when no ACL is explicitly set on a secret or a container, then clients with necessary
roles on secret's project or container's project can access it. This default access pattern translates
to `creator-only` as False and no `users` in ACL settings. That's why every secret and container by
to `project-access` as true and no `users` in ACL settings. That's why every secret and container by
default has following implicit ACL.
.. code-block:: json
{
"read":{
"creator-only": false
"project-access": true
}
}
@@ -106,7 +106,7 @@ To set/replace an ACL for a secret:
"721e27b8505b499e8ab3b38154705b9e",
"c1d20e4b7e7d4917aee6f0832152269b"
],
"creator-only":true
"project-access":false
}
}' \
http://localhost:9311/v1/secrets/15621a1b-efdf-41d8-92dc-356cec8e9da9/acl
@@ -133,7 +133,7 @@ To set/replace an ACL for a container:
"721e27b8505b499e8ab3b38154705b9e",
"c1d20e4b7e7d4917aee6f0832152269b"
],
"creator-only":true
"project-access":false
}
}' \
http://localhost:9311/v1/containers/8c077991-d524-4e15-8eaf-bc0c3bb225f2/acl
@@ -171,7 +171,7 @@ To replace an existing ACL for a container:
"2d0ee7c681cc4549b6d76769c320d91f",
"721e27b8505b499e8ab3b38154705b9e"
],
"creator-only":false
"project-access":true
}
}' \
http://localhost:9311/v1/containers/8c077991-d524-4e15-8eaf-bc0c3bb225f2/acl
@@ -194,7 +194,7 @@ To remove all users from an existing ACL for a container (pass empty list in `us
{
"read":{
"users":[],
"creator-only":false
"project-access":true
}
}' \
http://localhost:9311/v1/containers/8c077991-d524-4e15-8eaf-bc0c3bb225f2/acl
@@ -205,7 +205,7 @@ To remove all users from an existing ACL for a container (pass empty list in `us
{"acl_ref": "http://localhost:9311/v1/containers/8c077991-d524-4e15-8eaf-bc0c3bb225f2/acl"}
To update only the creator-only flag for container ACL (use PATCH):
To update only the `project-access` flag for container ACL (use PATCH):
.. code-block:: bash
@@ -216,7 +216,7 @@ To update only the creator-only flag for container ACL (use PATCH):
-d '
{
"read":{
"creator-only":true
"project-access":false
}
}' \
http://localhost:9311/v1/containers/8c077991-d524-4e15-8eaf-bc0c3bb225f2/acl
@@ -289,7 +289,7 @@ To get secret ACL data:
"c1d20e4b7e7d4917aee6f0832152269b",
"2d0ee7c681cc4549b6d76769c320d91f"
],
"creator-only":true
"project-access":false
}
}
@@ -315,7 +315,7 @@ To get container ACL data:
"c1d20e4b7e7d4917aee6f0832152269b",
"2d0ee7c681cc4549b6d76769c320d91f"
],
"creator-only":true
"project-access":false
}
}
+26 -83
View File
@@ -51,7 +51,7 @@ Request/Response (With ACL defined):
{user_id2},
.....
],
"creator-only":{creator-only-flag}
"project-access":{project-access-flag}
}
}
@@ -72,7 +72,7 @@ Request/Response (With no ACL defined):
HTTP/1.1 200 OK
{
"read":{
"creator-only": false
"project-access": true
}
}
@@ -122,16 +122,16 @@ This access is configured via operations on those secrets. Currently only the 'r
| users | [string] | (optional) List of user ids. This needs to be | [] |
| | | a user id as returned by Keystone. | |
+----------------------------+----------+-----------------------------------------------+----------+
| creator-only | boolean | (optional) Flag to mark a secret private so | `false` |
| project-access | boolean | (optional) Flag to mark a secret private so | `true` |
| | | that the user who created the secret and | |
| | | ``users`` specified in above list can only | |
| | | access the secret. Pass `true` to mark the | |
| | | access the secret. Pass `false` to mark the | |
| | | secret private. | |
+----------------------------+----------+-----------------------------------------------+----------+
Request/Response (Set ACL):
***************************
Request/Response (Set or Replace ACL):
**************************************
.. code-block:: none
@@ -150,7 +150,7 @@ Request/Response (Set ACL):
{user_id2},
.....
],
"creator-only":{creator-only-flag}
"project-access":{project-access-flag}
}
}
@@ -159,33 +159,6 @@ Request/Response (Set ACL):
HTTP/1.1 200 OK
{"acl_ref": "https://{barbican_host}/v1/secrets/{uuid}/acl"}
Request/Response (Replace ACL):
******************************
.. code-block:: none
PUT /v1/secrets/{uuid}/acl
Headers:
Content-Type: application/json
X-Auth-Token: {token_id}
Body:
{
"read":{
"users":[
{user_id1},
{user_id2},
.....
],
"creator-only":{creator-only-flag}
}
}
Response:
HTTP/1.1 200 OK
{"acl_ref": "https://{barbican_host}/v1/secrets/{uuid}/acl"}
HTTP Status Codes
*****************
@@ -213,7 +186,7 @@ PATCH /v1/secrets/{uuid}/acl
############################
Updates existing ACL for a given secret. This method can be used to apply partial changes on
existing ACL settings. Client can update the `users` list and enable or disable `creator-only`
existing ACL settings. Client can update the `users` list and enable or disable `project-access`
flag for existing ACL. List of provided users replaces existing users if any. For an existing
list of provided users from an ACL definition, pass empty list [] for `users`.
@@ -235,15 +208,15 @@ Attributes
| users | [string] | (optional) List of user ids. This needs to be | None |
| | | a user id as returned by Keystone. | |
+----------------------------+----------+-----------------------------------------------+----------+
| creator-only | boolean | (optional) Flag to mark a secret private so | None |
| project-access | boolean | (optional) Flag to mark a secret private so | None |
| | | that the user who created the secret and | |
| | | ``users`` specified in above list can only | |
| | | access the secret. Pass `true` to mark the | |
| | | access the secret. Pass `false` to mark the | |
| | | secret private. | |
+----------------------------+----------+-----------------------------------------------+----------+
Request/Response (Updating creator-only flag):
**********************************************
Request/Response (Updating project-access flag):
************************************************
.. code-block:: none
@@ -256,7 +229,7 @@ Request/Response (Updating creator-only flag):
{
"read":
{
"creator-only":true
"project-access":false
}
}
@@ -377,7 +350,7 @@ Request/Response (With ACL defined):
{user_id2},
.....
],
"creator-only":{creator-only-flag}
"project-access":{project-access-flag}
}
}
@@ -398,7 +371,7 @@ Request/Response (With no ACL defined):
HTTP/1.1 200 OK
{
"read":{
"creator-only": false
"project-access": true
}
}
@@ -448,45 +421,15 @@ This access is configured via operations on those containers. Currently only the
| users | [string] | (optional) List of user ids. This needs to be | [] |
| | | a user id as returned by Keystone. | |
+----------------------------+----------+-----------------------------------------------+----------+
| creator-only | boolean | (optional) Flag to mark a container private | `false` |
| project-access | boolean | (optional) Flag to mark a container private | `true` |
| | | so that the user who created the container and| |
| | | ``users`` specified in above list can only | |
| | | access the container. Pass `true` to mark the | |
| | | access the container. Pass `false` to mark the| |
| | | container private. | |
+----------------------------+----------+-----------------------------------------------+----------+
Request/Response (Set ACL):
***************************
.. code-block:: none
Request:
PUT /v1/containers/{uuid}/acl
Headers:
Content-Type: application/json
X-Auth-Token: {token_id}
Body:
{
"read":{
"users":[
{user_id1},
{user_id2},
.....
],
"creator-only":{creator-only-flag}
}
}
Response:
HTTP/1.1 201 Created
{"acl_ref": "https://{barbican_host}/v1/containers/{uuid}/acl"}
Request/Response (Replace ACL):
******************************
Request/Response (Set or Replace ACL):
**************************************
.. code-block:: none
@@ -503,7 +446,7 @@ Request/Response (Replace ACL):
{user_id2},
.....
],
"creator-only":{creator-only-flag}
"project-access":{project-access-flag}
}
}
@@ -539,7 +482,7 @@ PATCH /v1/containers/{uuid}/acl
###############################
Update existing ACL for a given container. This method can be used to apply partial changes
on existing ACL settings. Client can update `users` list and enable or disable `creator-only`
on existing ACL settings. Client can update `users` list and enable or disable `project-access`
flag for existing ACL. List of provided users replaces existing users if any. For an existing
list of provided users from an ACL definition, pass empty list [] for `users`.
@@ -561,15 +504,15 @@ Attributes
| users | [string] | (optional) List of user ids. This needs to be | None |
| | | a user id as returned by Keystone. | |
+----------------------------+----------+-----------------------------------------------+----------+
| creator-only | boolean | (optional) Flag to mark a container private | None |
| project-access | boolean | (optional) Flag to mark a container private | None |
| | | so that the user who created the container and| |
| | | ``users`` specified in above list can only | |
| | | access the container. Pass `true` to mark the | |
| | | access the container. Pass `false` to mark the| |
| | | container private. | |
+----------------------------+----------+-----------------------------------------------+----------+
Request/Response (Updating creator-only flag):
**********************************************
Request/Response (Updating project-access flag):
************************************************
.. code-block:: none
@@ -582,7 +525,7 @@ Request/Response (Updating creator-only flag):
{
"read":
{
"creator-only":true
"project-access":false
}
}
+2 -2
View File
@@ -10,11 +10,11 @@
"all_users": "role:admin or role:observer or role:creator or role:audit",
"secret_project_match": "project:%(target.secret.project_id)s",
"secret_acl_read": "'read':%(target.secret.read)s",
"secret_private_read": "'True':%(target.secret.read_creator_only)s",
"secret_private_read": "'False':%(target.secret.read_project_access)s",
"secret_creator_user": "user:%(target.secret.creator_id)s",
"container_project_match": "project:%(target.container.project_id)s",
"container_acl_read": "'read':%(target.container.read)s",
"container_private_read": "'True':%(target.container.read_creator_only)s",
"container_private_read": "'False':%(target.container.read_project_access)s",
"container_creator_user": "user:%(target.container.creator_id)s",
"secret_non_private_read": "rule:all_users and rule:secret_project_match and not rule:secret_private_read",