Ensure pycadf initiator IDs are UUID

pycadf now has more strict validation for IDs, specifically, it tests to
make sure they are UUIDs. In a multi-domain configuration this fails
since the public ID that is generated by keystone is not an actual UUID.

Change-Id: I1fd13bd7a7fe037bd0e1b7d6fb0214460ff7c963
Closes-Bug: 1521844
Co-Authored-By: Steve Martinelli <stevemar@ca.ibm.com>
This commit is contained in:
Ajaya Agrawal 2016-01-20 17:01:52 +00:00
parent 1053b63e8c
commit 944bd0a2dc
3 changed files with 49 additions and 2 deletions

View File

@ -22,6 +22,7 @@ import grp
import hashlib
import os
import pwd
import uuid
from oslo_config import cfg
from oslo_log import log
@ -42,6 +43,24 @@ CONF = cfg.CONF
LOG = log.getLogger(__name__)
# NOTE(stevermar): This UUID must stay the same, forever, across
# all of keystone to preserve its value as a URN namespace, which is
# used for ID transformation.
RESOURCE_ID_NAMESPACE = uuid.UUID('4332ecab-770b-4288-a680-b9aca3b1b153')
def resource_uuid(value):
"""Converts input to valid UUID hex digits."""
try:
uuid.UUID(value)
return value
except ValueError:
if len(value) <= 64:
return uuid.uuid5(RESOURCE_ID_NAMESPACE, value).hex
raise ValueError(_('Length of transformable resource id > 64, '
'which is max allowed characters'))
def flatten_dict(d, parent_key=''):
"""Flatten a nested dictionary

View File

@ -31,6 +31,7 @@ from pycadf import eventfactory
from pycadf import resource
from keystone.i18n import _, _LE
from keystone.common import utils
notifier_opts = [
@ -501,8 +502,12 @@ def _get_request_audit_info(context, user_id=None):
{}).get('domain_id')
host = pycadf.host.Host(address=remote_addr, agent=http_user_agent)
initiator = resource.Resource(typeURI=taxonomy.ACCOUNT_USER,
id=user_id, host=host)
initiator = resource.Resource(typeURI=taxonomy.ACCOUNT_USER, host=host)
if user_id:
initiator.user_id = user_id
initiator.id = utils.resource_uuid(user_id)
if project_id:
initiator.project_id = project_id
if domain_id:

View File

@ -1,3 +1,4 @@
# encoding: utf-8
# 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
@ -36,6 +37,28 @@ class UtilsTestCase(unit.BaseTestCase):
super(UtilsTestCase, self).setUp()
self.config_fixture = self.useFixture(config_fixture.Config(CONF))
def test_resource_uuid(self):
uuid_str = '536e28c2017e405e89b25a1ed777b952'
self.assertEqual(uuid_str, common_utils.resource_uuid(uuid_str))
# Exact 64 length string.
uuid_str = ('536e28c2017e405e89b25a1ed777b952'
'f13de678ac714bb1b7d1e9a007c10db5')
resource_id_namespace = common_utils.RESOURCE_ID_NAMESPACE
transformed_id = uuid.uuid5(resource_id_namespace, uuid_str).hex
self.assertEqual(transformed_id, common_utils.resource_uuid(uuid_str))
# Non-ASCII character test.
non_ascii_ = 'ß' * 32
transformed_id = uuid.uuid5(resource_id_namespace, non_ascii_).hex
self.assertEqual(transformed_id,
common_utils.resource_uuid(non_ascii_))
# This input is invalid because it's length is more than 64.
invalid_input = 'x' * 65
self.assertRaises(ValueError, common_utils.resource_uuid,
invalid_input)
def test_hash(self):
password = 'right'
wrong = 'wrongwrong' # Two wrongs don't make a right