Support bytes type in generate_public_ID()

python-ldap3.0 or later running on python3 uses str or bytes
data type according to what fields are returned.
local_id may be a bytes data type.
To handle it properly, mapping[key] needs to be examined for
identifying its data type and what python version is used.

Closes-Bug: #1901654
Change-Id: Iac097235fd31e166028c169d14ec0937c663c21c
(cherry picked from commit f7df9fba82)
(cherry picked from commit 5b860e0b3b)
This commit is contained in:
Keigo Noha 2020-10-27 15:07:53 +09:00
parent 5a7ebf53bc
commit f4819fe36f
3 changed files with 35 additions and 2 deletions

View File

@ -13,7 +13,6 @@
# under the License.
import hashlib
from keystone.identity import generator
@ -22,5 +21,12 @@ class Generator(generator.IDGenerator):
def generate_public_ID(self, mapping):
m = hashlib.sha256()
for key in sorted(mapping.keys()):
m.update(mapping[key].encode('utf-8'))
# python-ldap >3.0 returns bytes data type for attribute values
# except distinguished names, relative distinguished names,
# attribute names, queries on python3.
# Please see Bytes/text management in python-ldap module.
if isinstance(mapping[key], bytes):
m.update(mapping[key])
else:
m.update(mapping[key].encode('utf-8'))
return m.hexdigest()

View File

@ -152,6 +152,23 @@ class SqlIDMapping(test_backend_sql.SqlTests):
self.assertEqual(
public_id, PROVIDERS.id_mapping_api.get_public_id(local_entity))
def test_id_mapping_handles_bytes(self):
initial_mappings = len(mapping_sql.list_id_mappings())
local_id = b'FaKeID'
local_entity = {'domain_id': self.domainA['id'],
'local_id': local_id,
'entity_type': mapping.EntityType.USER}
# Check no mappings for the new local entity
self.assertIsNone(PROVIDERS.id_mapping_api.get_public_id(local_entity))
# Create the new mapping and then read it back
public_id = PROVIDERS.id_mapping_api.create_id_mapping(local_entity)
self.assertThat(mapping_sql.list_id_mappings(),
matchers.HasLength(initial_mappings + 1))
self.assertEqual(
public_id, PROVIDERS.id_mapping_api.get_public_id(local_entity))
def test_delete_public_id_is_silent(self):
# Test that deleting an invalid public key is silent
PROVIDERS.id_mapping_api.delete_id_mapping(uuid.uuid4().hex)

View File

@ -0,0 +1,10 @@
---
fixes:
- |
[`bug 1901654 <https://bugs.launchpad.net/keystone/+bug/1901654>`_]
Previously, generate_public_ID() in sha256.py assumed the passed arguments is str data type.
However, python-ldap 3.0 or later returns bytes data type for attribute values except fields
of distinguished names, relative distinguished names, attribute names, queries.
If keystone running on Python3 is integrated with LDAP and the LDAP server has local_id variable
in its attribute, user login operations will fail due to the assumption and modifiation of python-ldap.
By this fix, generate_public_ID() properly handles bytes data type in the parameter.