Optionalize instance_uuid in console_auth_token_get_valid()
The original design of the conversion of consoles to objects and storing the token authorizations in the database backend proposed adding the instance UUID to the access URL for consoles and did additional validation of the instance UUID when getting the token authorization from the database in the console_auth_token_get_valid() method. In testing that design with Tempest jobs, we found that noVNC was not handling the instance UUID in the access URL as expected and would not work with existing proxies. So, instead we could change to a design where we run one websocketproxy per cells v2 cell and avoid adding instance UUID to access URLs. With that, we need a way to get console token authorizations from the database without the instance UUID. Part of blueprint convert-consoles-to-objects Change-Id: I2bf3b56e6b92c40aaf95fa957de452bd7754d859
This commit is contained in:
@@ -2052,16 +2052,22 @@ def console_auth_token_create(context, values):
|
||||
return IMPL.console_auth_token_create(context, values)
|
||||
|
||||
|
||||
def console_auth_token_get_valid(context, token_hash, instance_uuid):
|
||||
def console_auth_token_get_valid(context, token_hash, instance_uuid=None):
|
||||
"""Get a valid console authorization by token_hash and instance_uuid.
|
||||
|
||||
The console authorizations expire at the time specified by their
|
||||
'expires' column. An expired console auth token will not be returned
|
||||
to the caller - it is treated as if it does not exist.
|
||||
|
||||
If instance_uuid is specified, the token is validated against both
|
||||
expiry and instance_uuid.
|
||||
|
||||
If instance_uuid is not specified, the token is validated against
|
||||
expiry only.
|
||||
"""
|
||||
return IMPL.console_auth_token_get_valid(context,
|
||||
token_hash,
|
||||
instance_uuid)
|
||||
instance_uuid=instance_uuid)
|
||||
|
||||
|
||||
def console_auth_token_destroy_all_by_instance(context, instance_uuid):
|
||||
|
@@ -1864,7 +1864,7 @@ def instance_destroy(context, instance_uuid, constraint=None):
|
||||
filter_by(instance_uuid=instance_uuid).\
|
||||
soft_delete()
|
||||
# NOTE(snikitin): We can't use model_query here, because there is no
|
||||
# column 'deleted' in 'tags' table.
|
||||
# column 'deleted' in 'tags' or 'console_auth_tokens' tables.
|
||||
context.session.query(models.Tag).filter_by(
|
||||
resource_id=instance_uuid).delete()
|
||||
context.session.query(models.ConsoleAuthToken).filter_by(
|
||||
@@ -6646,13 +6646,15 @@ def console_auth_token_create(context, values):
|
||||
|
||||
|
||||
@pick_context_manager_reader
|
||||
def console_auth_token_get_valid(context, token_hash, instance_uuid):
|
||||
_check_instance_exists_in_project(context, instance_uuid)
|
||||
return context.session.query(models.ConsoleAuthToken).\
|
||||
filter_by(token_hash=token_hash).\
|
||||
filter_by(instance_uuid=instance_uuid).\
|
||||
filter(models.ConsoleAuthToken.expires > timeutils.utcnow_ts()).\
|
||||
first()
|
||||
def console_auth_token_get_valid(context, token_hash, instance_uuid=None):
|
||||
if instance_uuid is not None:
|
||||
_check_instance_exists_in_project(context, instance_uuid)
|
||||
query = context.session.query(models.ConsoleAuthToken).\
|
||||
filter_by(token_hash=token_hash)
|
||||
if instance_uuid is not None:
|
||||
query = query.filter_by(instance_uuid=instance_uuid)
|
||||
return query.filter(
|
||||
models.ConsoleAuthToken.expires > timeutils.utcnow_ts()).first()
|
||||
|
||||
|
||||
@pick_context_manager_writer
|
||||
|
@@ -10519,6 +10519,7 @@ class ConsoleAuthTokenTestCase(test.TestCase):
|
||||
db_obj1 = db.console_auth_token_get_valid(self.context, hash1, uuid1)
|
||||
db_obj2 = db.console_auth_token_get_valid(self.context, hash1, uuid2)
|
||||
self.assertIsNotNone(db_obj1, "a valid token should be found here")
|
||||
self.assertEqual(hash1, db_obj1['token_hash'])
|
||||
self.assertIsNone(db_obj2, "the token uuid should not match")
|
||||
|
||||
def test_console_auth_token_destroy_expired_by_host(self):
|
||||
@@ -10551,6 +10552,37 @@ class ConsoleAuthTokenTestCase(test.TestCase):
|
||||
self.assertIsNotNone(db_obj2, "a valid token should be found here")
|
||||
self.assertIsNotNone(db_obj3, "a valid token should be found here")
|
||||
|
||||
def test_console_auth_token_get_valid_without_uuid_deleted_instance(self):
|
||||
uuid1 = uuidsentinel.uuid1
|
||||
hash1 = utils.get_sha256_str(uuidsentinel.token1)
|
||||
self._create_instances([uuid1])
|
||||
self._create(hash1, uuid1, 100)
|
||||
|
||||
db_obj1 = db.console_auth_token_get_valid(self.context, hash1)
|
||||
self.assertIsNotNone(db_obj1, "a valid token should be in database")
|
||||
|
||||
db.instance_destroy(self.context, uuid1)
|
||||
db_obj1 = db.console_auth_token_get_valid(self.context, hash1)
|
||||
self.assertIsNone(db_obj1, "the token should have been deleted")
|
||||
|
||||
def test_console_auth_token_get_valid_without_uuid_by_expiry(self):
|
||||
uuid1 = uuidsentinel.uuid1
|
||||
uuid2 = uuidsentinel.uuid2
|
||||
hash1 = utils.get_sha256_str(uuidsentinel.token1)
|
||||
hash2 = utils.get_sha256_str(uuidsentinel.token2)
|
||||
self.addCleanup(timeutils.clear_time_override)
|
||||
timeutils.set_time_override(timeutils.utcnow())
|
||||
self._create_instances([uuid1, uuid2])
|
||||
|
||||
self._create(hash1, uuid1, 10)
|
||||
timeutils.advance_time_seconds(100)
|
||||
self._create(hash2, uuid2, 10)
|
||||
|
||||
db_obj1 = db.console_auth_token_get_valid(self.context, hash1)
|
||||
db_obj2 = db.console_auth_token_get_valid(self.context, hash2)
|
||||
self.assertIsNone(db_obj1, "the token should have expired")
|
||||
self.assertIsNotNone(db_obj2, "a valid token should be found here")
|
||||
|
||||
|
||||
class SortMarkerHelper(test.TestCase):
|
||||
def setUp(self):
|
||||
|
Reference in New Issue
Block a user