Tell clients what roles were created
If a client requests a role then inform them what role was actually created or already existed. If a client requests the creation of a role and that role already exists with a different mix of upper and lower case then the new role is not created. This is because keystone purports to be case insensative. However the client may not be case insesative (horizon) and may assume that the role was created. This change replies to the client with a new key 'created_roles'. This tells the client what the case sensative name actually is. Change-Id: Idc0865a688886a2066dfcdbd15e30118ae5c5bb8 Closes-Bug: #1890437
This commit is contained in:
parent
9e2d5cf2b7
commit
f72ae6160b
|
@ -1795,9 +1795,32 @@ def ensure_all_service_accounts_protected_for_pci_dss_options():
|
|||
protect_user_account_from_pci_dss_force_change_password(user['name'])
|
||||
|
||||
|
||||
def get_real_role_names(roles, manager):
|
||||
"""Return the name names of the roles.
|
||||
|
||||
Keystone attempts to be case insensative but not all client code is so
|
||||
sometimes the case sensative role name as it is stored in the DB is
|
||||
needed.
|
||||
|
||||
:param roles: List of role names
|
||||
:type roles: List[str]
|
||||
:param manager: Manager for this keystone api
|
||||
:type manager: keystone_utils.KeystoneManagerProxy
|
||||
:returns: List of role names
|
||||
:rtype: List[str]
|
||||
"""
|
||||
resolved_roles = []
|
||||
for role in roles:
|
||||
resolved_role = manager.resolve_role_name(role)
|
||||
if resolved_role:
|
||||
resolved_roles.append(resolved_role)
|
||||
return resolved_roles
|
||||
|
||||
|
||||
def add_service_to_keystone(relation_id=None, remote_unit=None):
|
||||
manager = get_manager()
|
||||
settings = relation_get(rid=relation_id, unit=remote_unit)
|
||||
requested_roles = get_requested_roles(settings)
|
||||
# the minimum settings needed per endpoint
|
||||
single = {'service', 'region', 'public_url', 'admin_url', 'internal_url'}
|
||||
https_cns = []
|
||||
|
@ -1822,12 +1845,14 @@ def add_service_to_keystone(relation_id=None, remote_unit=None):
|
|||
relation_data["api_version"] = get_api_version()
|
||||
relation_data["admin_domain_id"] = leader_get(
|
||||
attribute='admin_domain_id')
|
||||
|
||||
# Allow the remote service to request creation of any additional
|
||||
# roles. Currently used by Horizon
|
||||
for role in get_requested_roles(settings):
|
||||
for role in requested_roles:
|
||||
log("Creating requested role: {}".format(role))
|
||||
create_role(role)
|
||||
relation_data["created_roles"] = ','.join(get_real_role_names(
|
||||
requested_roles,
|
||||
manager))
|
||||
|
||||
peer_store_and_set(relation_id=relation_id, **relation_data)
|
||||
return
|
||||
|
@ -1940,6 +1965,8 @@ def add_service_to_keystone(relation_id=None, remote_unit=None):
|
|||
"admin_domain_id": leader_get(attribute='admin_domain_id'),
|
||||
"admin_project_id": admin_project_id,
|
||||
"admin_user_id": admin_user_id,
|
||||
"created_roles": ','.join(
|
||||
get_real_role_names(requested_roles, manager))
|
||||
}
|
||||
|
||||
peer_store_and_set(relation_id=relation_id, **relation_data)
|
||||
|
@ -2673,4 +2700,5 @@ def endpoints_dict(settings):
|
|||
'admin': settings.get('admin_url', None),
|
||||
'internal': settings.get('internal_url', None),
|
||||
}
|
||||
|
||||
return endpoints
|
||||
|
|
|
@ -190,6 +190,22 @@ class KeystoneManager(object):
|
|||
def resolve_domain_id(self, name):
|
||||
pass
|
||||
|
||||
def resolve_role_name(self, name):
|
||||
"""Find the role_name of a given role
|
||||
|
||||
Find the case-sensative role name that matches the case-insensative
|
||||
role name supplied.
|
||||
|
||||
:param name: Name of role to look up.
|
||||
:type name: str
|
||||
:returns: Role name
|
||||
:rtype: Optional[str]
|
||||
"""
|
||||
roles = [r._info for r in self.api.roles.list()]
|
||||
for r in roles:
|
||||
if name.lower() == r['name'].lower():
|
||||
return r['name']
|
||||
|
||||
def resolve_role_id(self, name):
|
||||
"""Find the role_id of a given role"""
|
||||
roles = [r._info for r in self.api.roles.list()]
|
||||
|
|
|
@ -320,13 +320,16 @@ class TestKeystoneUtils(CharmTestCase):
|
|||
_leader_set.assert_called_with({'db-initialised': True})
|
||||
mock_stop_manager_instance.assert_called_once_with()
|
||||
|
||||
@patch.object(utils, 'get_real_role_names')
|
||||
@patch.object(utils, 'leader_get')
|
||||
@patch.object(utils, 'get_api_version')
|
||||
@patch.object(utils, 'get_manager')
|
||||
@patch.object(utils, 'resolve_address')
|
||||
def test_add_service_to_keystone_clustered_https_none_values(
|
||||
self, _resolve_address, _get_manager,
|
||||
_get_api_version, _leader_get):
|
||||
_get_api_version, _leader_get,
|
||||
_get_real_role_names):
|
||||
_get_real_role_names.return_value = ['Member', 'SpecialRole']
|
||||
_get_api_version.return_value = 2
|
||||
_leader_get.return_value = None
|
||||
relation_id = 'identity-service:0'
|
||||
|
@ -358,10 +361,12 @@ class TestKeystoneUtils(CharmTestCase):
|
|||
'service_port': 81,
|
||||
'region': 'RegionOne',
|
||||
'api_version': 2,
|
||||
'admin_domain_id': None}
|
||||
'admin_domain_id': None,
|
||||
'created_roles': 'Member,SpecialRole'}
|
||||
self.peer_store_and_set.assert_called_with(relation_id=relation_id,
|
||||
**relation_data)
|
||||
|
||||
@patch.object(utils, 'get_real_role_names')
|
||||
@patch.object(utils, 'leader_set')
|
||||
@patch.object(utils, 'leader_get')
|
||||
@patch.object(utils, 'get_api_version')
|
||||
|
@ -373,7 +378,8 @@ class TestKeystoneUtils(CharmTestCase):
|
|||
def test_add_service_to_keystone_no_clustered_no_https_complete_values(
|
||||
self, KeystoneManager, add_endpoint, ensure_valid_service,
|
||||
_resolve_address, create_user, get_api_version, leader_get,
|
||||
leader_set, test_api_version=2):
|
||||
leader_set, _get_real_role_names, test_api_version=2):
|
||||
_get_real_role_names.return_value = ['Member', 'SpecialRole']
|
||||
get_api_version.return_value = test_api_version
|
||||
leader_get.return_value = None
|
||||
relation_id = 'identity-service:0'
|
||||
|
@ -449,7 +455,8 @@ class TestKeystoneUtils(CharmTestCase):
|
|||
'ca_cert': '__null__',
|
||||
'auth_protocol': 'http', 'service_protocol': 'http',
|
||||
'service_tenant_id': 'tenant_id',
|
||||
'api_version': test_api_version}
|
||||
'api_version': test_api_version,
|
||||
'created_roles': 'Member,SpecialRole'}
|
||||
|
||||
filtered = collections.OrderedDict()
|
||||
for k, v in relation_data.items():
|
||||
|
@ -504,6 +511,7 @@ class TestKeystoneUtils(CharmTestCase):
|
|||
adminurl='10.0.0.2',
|
||||
internalurl='192.168.1.2')
|
||||
|
||||
@patch.object(utils, 'get_real_role_names')
|
||||
@patch.object(utils, 'get_requested_roles')
|
||||
@patch.object(utils, 'create_service_credentials')
|
||||
@patch.object(utils, 'leader_get')
|
||||
|
@ -514,7 +522,8 @@ class TestKeystoneUtils(CharmTestCase):
|
|||
def test_add_service_to_keystone_multi_endpoints_bug_1739409(
|
||||
self, KeystoneManager, add_endpoint, ensure_valid_service,
|
||||
ip_config, leader_get, create_service_credentials,
|
||||
get_requested_roles):
|
||||
get_requested_roles, _get_real_role_names):
|
||||
_get_real_role_names.return_value = ['Member', 'SpecialRole']
|
||||
relation_id = 'identity-service:8'
|
||||
remote_unit = 'nova-cloud-controller/0'
|
||||
get_requested_roles.return_value = 'role1'
|
||||
|
@ -1921,3 +1930,17 @@ class TestKeystoneUtils(CharmTestCase):
|
|||
call({'transitional_charm_user_id': 'fakeid'}),
|
||||
])
|
||||
configs.write_all.assert_called_once_with()
|
||||
|
||||
def test_get_real_role_name(self):
|
||||
|
||||
def _resolve_role_name(role_name):
|
||||
roles = {'member': 'Member'}
|
||||
return roles.get(role_name)
|
||||
|
||||
manager = MagicMock()
|
||||
manager.resolve_role_name.side_effect = _resolve_role_name
|
||||
self.assertEqual(
|
||||
utils.get_real_role_names(
|
||||
['member', 'MissingRole'],
|
||||
manager),
|
||||
['Member'])
|
||||
|
|
Loading…
Reference in New Issue