Update local_id limit to 255 characters
This avoids the "String length exceeded." error, when using LDAP domain specific backend in case the user uses a user id attribute, which can exceed the previous constraint of 64 chars. Change-Id: I923a2a2a5e79c8f265ff436e96258288dddb867b Closes-Bug: #1929066 Resolves: rhbz#1959345
This commit is contained in:
parent
63ef8f81f3
commit
ce6031ca12
|
@ -146,6 +146,12 @@ then the same public ID will be created. This is useful if you are running
|
||||||
multiple keystones and want to ensure the same ID would be generated whichever
|
multiple keystones and want to ensure the same ID would be generated whichever
|
||||||
server you hit.
|
server you hit.
|
||||||
|
|
||||||
|
.. NOTE::
|
||||||
|
|
||||||
|
In case of the LDAP backend, the names of users and groups are not hashed.
|
||||||
|
As a result, these are length limited to 255 characters. Longer names
|
||||||
|
will result in an error.
|
||||||
|
|
||||||
While keystone will dynamically maintain the identity mapping, including
|
While keystone will dynamically maintain the identity mapping, including
|
||||||
removing entries when entities are deleted via the keystone, for those entities
|
removing entries when entities are deleted via the keystone, for those entities
|
||||||
in backends that are managed outside of keystone (e.g. a read-only LDAP),
|
in backends that are managed outside of keystone (e.g. a read-only LDAP),
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||||
|
# not use this file except in compliance with the License. You may obtain
|
||||||
|
# a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
# License for the specific language governing permissions and limitations
|
||||||
|
# under the License.
|
||||||
|
|
||||||
|
# This is a placeholder for Ussuri backports. Do not use this number for new
|
||||||
|
# Victoria work. New Victoria work starts after all the placeholders.
|
||||||
|
|
||||||
|
|
||||||
|
def upgrade(migrate_engine):
|
||||||
|
pass
|
|
@ -0,0 +1,18 @@
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||||
|
# not use this file except in compliance with the License. You may obtain
|
||||||
|
# a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
# License for the specific language governing permissions and limitations
|
||||||
|
# under the License.
|
||||||
|
|
||||||
|
# This is a placeholder for Ussuri backports. Do not use this number for new
|
||||||
|
# Victoria work. New Victoria work starts after all the placeholders.
|
||||||
|
|
||||||
|
|
||||||
|
def upgrade(migrate_engine):
|
||||||
|
pass
|
|
@ -0,0 +1,24 @@
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||||
|
# not use this file except in compliance with the License. You may obtain
|
||||||
|
# a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
# 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 sqlalchemy as sql
|
||||||
|
|
||||||
|
|
||||||
|
def upgrade(migrate_engine):
|
||||||
|
|
||||||
|
meta = sql.MetaData()
|
||||||
|
meta.bind = migrate_engine
|
||||||
|
|
||||||
|
id_mapping_table = sql.Table(
|
||||||
|
'id_mapping', meta, autoload=True
|
||||||
|
)
|
||||||
|
id_mapping_table.c.local_id.alter(type=sql.String(255))
|
|
@ -21,7 +21,7 @@ class IDMapping(sql.ModelBase, sql.ModelDictMixin):
|
||||||
__tablename__ = 'id_mapping'
|
__tablename__ = 'id_mapping'
|
||||||
public_id = sql.Column(sql.String(64), primary_key=True)
|
public_id = sql.Column(sql.String(64), primary_key=True)
|
||||||
domain_id = sql.Column(sql.String(64), nullable=False)
|
domain_id = sql.Column(sql.String(64), nullable=False)
|
||||||
local_id = sql.Column(sql.String(64), nullable=False)
|
local_id = sql.Column(sql.String(255), nullable=False)
|
||||||
# NOTE(henry-nash): Postgres requires a name to be defined for an Enum
|
# NOTE(henry-nash): Postgres requires a name to be defined for an Enum
|
||||||
entity_type = sql.Column(
|
entity_type = sql.Column(
|
||||||
sql.Enum(identity_mapping.EntityType.USER,
|
sql.Enum(identity_mapping.EntityType.USER,
|
||||||
|
|
|
@ -33,7 +33,7 @@ class SqlIDMappingTable(test_backend_sql.SqlModels):
|
||||||
def test_id_mapping(self):
|
def test_id_mapping(self):
|
||||||
cols = (('public_id', sql.String, 64),
|
cols = (('public_id', sql.String, 64),
|
||||||
('domain_id', sql.String, 64),
|
('domain_id', sql.String, 64),
|
||||||
('local_id', sql.String, 64),
|
('local_id', sql.String, 255),
|
||||||
('entity_type', sql.Enum, None))
|
('entity_type', sql.Enum, None))
|
||||||
self.assertExpectedSchema('id_mapping', cols)
|
self.assertExpectedSchema('id_mapping', cols)
|
||||||
|
|
||||||
|
@ -169,6 +169,26 @@ class SqlIDMapping(test_backend_sql.SqlTests):
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
public_id, PROVIDERS.id_mapping_api.get_public_id(local_entity))
|
public_id, PROVIDERS.id_mapping_api.get_public_id(local_entity))
|
||||||
|
|
||||||
|
def test_id_mapping_handles_ids_greater_than_64_characters(self):
|
||||||
|
initial_mappings = len(mapping_sql.list_id_mappings())
|
||||||
|
local_id = 'Aa' * 100
|
||||||
|
local_entity = {'domain_id': self.domainA['id'],
|
||||||
|
'local_id': local_id,
|
||||||
|
'entity_type': mapping.EntityType.GROUP}
|
||||||
|
|
||||||
|
# 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))
|
||||||
|
self.assertEqual(
|
||||||
|
local_id,
|
||||||
|
PROVIDERS.id_mapping_api.get_id_mapping(public_id)['local_id'])
|
||||||
|
|
||||||
def test_delete_public_id_is_silent(self):
|
def test_delete_public_id_is_silent(self):
|
||||||
# Test that deleting an invalid public key is silent
|
# Test that deleting an invalid public key is silent
|
||||||
PROVIDERS.id_mapping_api.delete_id_mapping(uuid.uuid4().hex)
|
PROVIDERS.id_mapping_api.delete_id_mapping(uuid.uuid4().hex)
|
||||||
|
|
|
@ -263,7 +263,12 @@ class TestKeystoneExpandSchemaMigrations(
|
||||||
# timestamp to datetime and updates the initial value in the contract
|
# timestamp to datetime and updates the initial value in the contract
|
||||||
# phase. Adding an exception here to pass expand banned tests,
|
# phase. Adding an exception here to pass expand banned tests,
|
||||||
# otherwise fails.
|
# otherwise fails.
|
||||||
4
|
4,
|
||||||
|
|
||||||
|
# Migration 79 changes a varchar column length, doesn't
|
||||||
|
# convert the data within that column/table and doesn't rebuild
|
||||||
|
# indexes.
|
||||||
|
79
|
||||||
]
|
]
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
|
|
|
@ -3499,6 +3499,25 @@ class FullMigration(SqlMigrateBase, unit.TestCase):
|
||||||
['id', 'domain_id', 'enabled', 'description',
|
['id', 'domain_id', 'enabled', 'description',
|
||||||
'authorization_ttl'])
|
'authorization_ttl'])
|
||||||
|
|
||||||
|
def test_migration_079_expand_update_local_id_limit(self):
|
||||||
|
self.expand(78)
|
||||||
|
self.migrate(78)
|
||||||
|
self.contract(78)
|
||||||
|
|
||||||
|
id_mapping_table = sqlalchemy.Table('id_mapping',
|
||||||
|
self.metadata, autoload=True)
|
||||||
|
# assert local_id column is a string of 64 characters (before)
|
||||||
|
self.assertEqual('VARCHAR(64)', str(id_mapping_table.c.local_id.type))
|
||||||
|
|
||||||
|
self.expand(79)
|
||||||
|
self.migrate(79)
|
||||||
|
self.contract(79)
|
||||||
|
|
||||||
|
id_mapping_table = sqlalchemy.Table('id_mapping',
|
||||||
|
self.metadata, autoload=True)
|
||||||
|
# assert local_id column is a string of 255 characters (after)
|
||||||
|
self.assertEqual('VARCHAR(255)', str(id_mapping_table.c.local_id.type))
|
||||||
|
|
||||||
|
|
||||||
class MySQLOpportunisticFullMigration(FullMigration):
|
class MySQLOpportunisticFullMigration(FullMigration):
|
||||||
FIXTURE = db_fixtures.MySQLOpportunisticFixture
|
FIXTURE = db_fixtures.MySQLOpportunisticFixture
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
---
|
||||||
|
upgrade:
|
||||||
|
- |
|
||||||
|
[`bug 1929066 <https://bugs.launchpad.net/keystone/+bug/1929066>`_]
|
||||||
|
Increase the length of the `local_id` column in the `id_mapping` table
|
||||||
|
to accommodate LDAP group names that result in names greater than
|
||||||
|
64 characters.
|
Loading…
Reference in New Issue