Activity log for bug #1217017

Date Who What changed Old value New value Message
2013-08-26 17:05:00 Mark Miller bug added bug
2013-08-27 00:20:01 Dolph Mathews bug added subscriber Henry Nash
2013-08-27 00:22:42 Dolph Mathews description I am still working my way through the new multi-ldap split backend code in an attempt to get it working locally. I have isolated one bug and am looking into the next one. The setup is still the same as described in the previous email below. The first bug: File “/keystone/common/dependency.py” has a method named “requires” which is a decorator for the “Assignment” class of both files “/keystone/assignment/backends/ldap.py” and “/keystone/assignment/backends/sql.py”. File “/keystone/assignment/backends/ldap.py”: @dependency.requires('identity_api') class Assignment(assignment.Driver): File “/keystone/assignment/backends/sql.py”: @dependency.requires('identity_api') class Assignment(sql.Base, assignment.Driver): When I specify the following contents for file “/etc/keystone/domains/keystone.Default.conf” I am telling Keystone to use an SQL backend for the default domain: [assignment] driver = keystone.assignment.backends.sql.Assignment [identity] driver = keystone.identity.backends.sql.Identity [ldap] However, there is a problem with the following line in method requires of file “dependency.py”: def wrapper(self, *args, **kwargs): """Inject each dependency from the registry.""" self.__wrapped_init__(*args, **kwargs) for dependency in self._dependencies: if dependency not in REGISTRY: if dependency in _future_dependencies: _future_dependencies[dependency] += [self] else: _future_dependencies[dependency] = [self] continue setattr(self, dependency, REGISTRY[dependency]) because it is passing arguments to the constructor of the Assignment class in file “/keystone/assignment/backends/sql.py” which extends the sql.Base class (i.e. class Base(object) of file “/keystone/common/sql/core.py“) that extends class “object” which does not accept any parameters for its constructor. It took me a full day to pin this one down. To get around this problem I added the following lines to class Base(object) of file “/keystone/common/sql/core.py“ in order to accept any number of parameters: def __init__(self, *args, **kwargs): super(Base, self).__init__() Now onto the second bug. I am still chasing this one down and have added quite a few log lines to debug it. Somehow the domain_id is not getting translated into a valid domain_scope. 2013-08-23 14:51:41,803 INFO sqlalchemy.engine.base.Engine ('MyDomain',) 2013-08-23 14:51:41 INFO [sqlalchemy.engine.base.Engine] ('MyDomain',) 2013-08-23 14:51:41 INFO [keystone.identity.core] ************ method _load_driver, assignment_api = <keystone.assignment.core.Manager object at 0x20bbd10>, domain_id = 464bdc5784a446378a85f99a25d216b4 2013-08-23 14:51:41 INFO [keystone.identity.core] ########## method _load_driver, domain_config = {'cfg': <oslo.config.cfg.ConfigOpts object at 0x3143710>} 2013-08-23 14:51:41 INFO [keystone.openstack.common.importutils] ******** import_object: import_str=keystone.identity.backends.ldap.Identity, args=(<oslo.config.cfg.ConfigOpts object at 0x3143710>,), kwargs={} 2013-08-23 14:51:41 INFO [keystone.openstack.common.importutils] ******** import_class: mod_str=keystone.identity.backends.ldap, _sep=., class_str=Identity 2013-08-23 14:51:41 INFO [keystone.openstack.common.importutils] ******** import_class: attr = <class 'keystone.identity.backends.ldap.Identity'> 2013-08-23 14:51:41 INFO [keystone.common.dependency] *********** requires:wrapper: args=(<oslo.config.cfg.ConfigOpts object at 0x3143710>,), kwargs={} 2013-08-23 14:51:41 INFO [keystone.common.dependency] *********** requires:wrapper: class=keystone.identity.backends.ldap.Identity 2013-08-23 14:51:41 INFO [keystone.common.dependency] *********** requires:wrapper: after __Wraped_init__ 2013-08-23 14:51:41 INFO [keystone.identity.core] *************** class Manager, method:_get_domain_id_and_driver domain_scope = None************** 2013-08-23 14:51:41 INFO [keystone.identity.core] *************** class Manager, method:_normailize_scope, domain_scope = None************** 2013-08-23 14:51:41 INFO [keystone.identity.core] *************** class Manager, method:_select_identity_driver, domain_id = default, driver = <keystone.identity.backends.ldap.Identity object at 0x3140d10> ************** 2013-08-23 14:51:41 INFO [keystone.identity.core] *************** class Manager, method:get_user, driver = <keystone.identity.backends.ldap.Identity object at 0x3140d10>, domain_scope=None ************** 2013-08-23 14:51:41 INFO [keystone.identity.core] *************** class Manager, method:get_user, user_id = mark.m.miller@hp.com, driver.is_domain_aware= False ************** 2013-08-23 14:51:42 INFO [keystone.identity.core] *************** in class Manager9b ************** 2013-08-23 14:51:42 INFO [keystone.identity.core] *************** in class Manager9c ************** 2013-08-23 14:51:42 INFO [keystone.identity.core] *************** class Manager, method:_set_domain_id, domain_id = default ************** -------------------------------------------------------------------- From: Miller, Mark M (EB SW Cloud - R&D - Corvallis) Sent: Wednesday, August 21, 2013 4:33 PM To: 'Dolph Mathews'; openstack@lists.openstack.org Subject: Possible Bug: Support domain-specific Identity Backends Hello, I am trying to test multiple split LDAP frontends based off of multiple domains (i.e. one LDAP server per domain). I have the identity and ldap sections of file “keystone.conf” configured as follows: keystone.conf: [identity] # driver = keystone.identity.backends.sql.Identity domain_specific_drivers_enabled = True domain_config_dir = /etc/keystone/domains # This references the domain to use for all Identity API v2 requests (which are # not aware of domains). A domain with this ID will be created for you by # keystone-manage db_sync in migration 008. The domain referenced by this ID # cannot be deleted on the v3 API, to prevent accidentally breaking the v2 API. # There is nothing special about this domain, other than the fact that it must # exist to order to maintain support for your v2 clients. default_domain_id = default [ldap] I have 2 domains (Default and MyDomain) and in the domains directory I have 2 files with identical content named “keystone.Default.conf” and “keystone.MyDomain.conf”. [identity] driver = keystone.identity.backends.ldap.Identity [ldap] # url = "ldap://ldap.hp.com:389" url = "ldaps://ldap.hp.com:636" user = "cn=CloudOSKeystoneDev, ou=Applications, o=hp.com" password = "secretword" suffix = "o=hp.com" # suffix = cn=example,cn=com use_dumb_member = False allow_subtree_delete = False # dumb_member = cn=dumb,dc=example,dc=com # Maximum results per page; a value of zero ('0') disables paging (default) page_size = 0 # The LDAP dereferencing option for queries. This can be either 'never', # 'searching', 'always', 'finding' or 'default'. The 'default' option falls # back to using default dereferencing configured by your ldap.conf. alias_dereferencing = never # The LDAP scope for queries, this can be either 'one' # (onelevel/singleLevel) or 'sub' (subtree/wholeSubtree) query_scope = sub user_tree_dn = ou=People,o=hp.com user_filter = "(hpStatus=Active)" user_objectclass = hpPerson user_domain_id_attribute = Groups user_id_attribute = uid user_name_attribute = cn user_mail_attribute = mail user_pass_attribute = userPassword user_enabled_mask = 0 # user_enabled_attribute = # user_enabled_default = user_attribute_ignore = tenant_id,tenants user_allow_create = False user_allow_update = False user_allow_delete = False user_enabled_emulation = False user_enabled_emulation_dn = Noneuse_tls = False use_tls = False tls_cacertfile = "/etc/keystone/ssl/certs/hpca2ssG2_ns.cer" tls_req_cert = demand I also have a role assigned to user mark.m.miller@hp.com for project “myapp” in domain “MyDomain” and can get a token with the following JSON script: { "auth": { "identity": { "methods": [ "password" ], "password": { "user": { "domain": { "name": "MyDomain" }, "id": "mark.m.miller@hp.com", "password": "secretword" } } }, "scope": { "project": { "domain": { "name": "MyDomain" }, "name": "myapp" } } } } If I change the domain name to “Default” in the JSON script above I get an unauthorized response as expected. Now I wanted to make sure that the Keystone code was indeed accessing the correct configuration file in directory “/etc/keystone/domains” so I changed the contents of the file “keystone.Default.conf” to: [identity] driver = keystone.identity.backends.sql.Identity [ldap] In order to force Keystone to use an SQL Identity backend for the default domain. When I do I get the following error for the token request above (Note: the INFO log lines with “********” in them were added by me): 2013-08-21 16:21:38 DEBUG [routes.middleware] Matched POST /auth/tokens 2013-08-21 16:21:38 DEBUG [routes.middleware] Route path: '{path_info:.*}', defaults: {'controller': <keystone.contrib.s3.core.S3Extension object at 0x3ccb810>} 2013-08-21 16:21:38 DEBUG [routes.middleware] Match dict: {'controller': <keystone.contrib.s3.core.S3Extension object at 0x3ccb810>, 'path_info': '/auth/tokens'} 2013-08-21 16:21:38 DEBUG [routes.middleware] Matched POST /auth/tokens 2013-08-21 16:21:38 DEBUG [routes.middleware] Route path: '{path_info:.*}', defaults: {'controller': <keystone.common.wsgi.ComposingRouter object at 0x3cd5550>} 2013-08-21 16:21:38 DEBUG [routes.middleware] Match dict: {'controller': <keystone.common.wsgi.ComposingRouter object at 0x3cd5550>, 'path_info': '/auth/tokens'} 2013-08-21 16:21:38 DEBUG [routes.middleware] Matched POST /auth/tokens 2013-08-21 16:21:38 DEBUG [routes.middleware] Route path: '/auth/tokens', defaults: {'action': u'authenticate_for_token', 'controller': <keystone.auth.controllers.Auth object at 0x3ccb410>} 2013-08-21 16:21:38 DEBUG [routes.middleware] Match dict: {'action': u'authenticate_for_token', 'controller': <keystone.auth.controllers.Auth object at 0x3ccb410>} 2013-08-21 16:21:38 INFO [keystone.identity.core] *************** class Manager, method:__init__ ************** 2013-08-21 16:21:38,570 INFO sqlalchemy.engine.base.Engine SELECT domain.id AS domain_id, domain.name AS domain_name, domain.enabled AS domain_enabled, domain.extra AS domain_extra FROM domain WHERE domain.name = %s 2013-08-21 16:21:38 INFO [sqlalchemy.engine.base.Engine] SELECT domain.id AS domain_id, domain.name AS domain_name, domain.enabled AS domain_enabled, domain.extra AS domain_extra FROM domain WHERE domain.name = %s 2013-08-21 16:21:38,571 INFO sqlalchemy.engine.base.Engine ('MyDomain',) 2013-08-21 16:21:38 INFO [sqlalchemy.engine.base.Engine] ('MyDomain',) 2013-08-21 16:21:38,574 INFO sqlalchemy.engine.base.Engine SELECT project.id AS project_id, project.name AS project_name, project.domain_id AS project_domain_id, project.description AS project_description, project.enabled AS project_enabled, project.extra AS project_extra FROM project WHERE project.name = %s AND project.domain_id = %s 2013-08-21 16:21:38 INFO [sqlalchemy.engine.base.Engine] SELECT project.id AS project_id, project.name AS project_name, project.domain_id AS project_domain_id, project.description AS project_description, project.enabled AS project_enabled, project.extra AS project_extra FROM project WHERE project.name = %s AND project.domain_id = %s 2013-08-21 16:21:38,575 INFO sqlalchemy.engine.base.Engine ('myapp', '464bdc5784a446378a85f99a25d216b4') 2013-08-21 16:21:38 INFO [sqlalchemy.engine.base.Engine] ('myapp', '464bdc5784a446378a85f99a25d216b4') 2013-08-21 16:21:38 INFO [keystone.identity.core] *************** class Manager, method:__init__ ************** 2013-08-21 16:21:38,580 INFO sqlalchemy.engine.base.Engine SELECT domain.id AS domain_id, domain.name AS domain_name, domain.enabled AS domain_enabled, domain.extra AS domain_extra FROM domain WHERE domain.name = %s 2013-08-21 16:21:38 INFO [sqlalchemy.engine.base.Engine] SELECT domain.id AS domain_id, domain.name AS domain_name, domain.enabled AS domain_enabled, domain.extra AS domain_extra FROM domain WHERE domain.name = %s 2013-08-21 16:21:38,581 INFO sqlalchemy.engine.base.Engine ('Default',) 2013-08-21 16:21:38 INFO [sqlalchemy.engine.base.Engine] ('Default',) 2013-08-21 16:21:38 ERROR [keystone.common.wsgi] object.__init__() takes no parameters Traceback (most recent call last): File "/usr/local/lib/python2.7/dist-packages/keystone/common/wsgi.py", line 237, in __call__ result = method(context, **params) File "/usr/local/lib/python2.7/dist-packages/keystone/auth/controllers.py", line 287, in authenticate_for_token self.authenticate(context, auth_info, auth_context) File "/usr/local/lib/python2.7/dist-packages/keystone/auth/controllers.py", line 344, in authenticate auth_context) File "/usr/local/lib/python2.7/dist-packages/keystone/auth/plugins/password.py", line 103, in authenticate user_info = UserAuthInfo(auth_payload) File "/usr/local/lib/python2.7/dist-packages/keystone/auth/plugins/password.py", line 34, in __init__ self._validate_and_normalize_auth_data(auth_payload) File "/usr/local/lib/python2.7/dist-packages/keystone/auth/plugins/password.py", line 87, in _validate_and_normalize_auth_data user_ref = self.identity_api.get_user(user_id) File "/usr/local/lib/python2.7/dist-packages/keystone/identity/core.py", line 170, in wrapper self.driver, self.assignment_api) File "/usr/local/lib/python2.7/dist-packages/keystone/identity/core.py", line 126, in setup_domain_drivers names[1]) File "/usr/local/lib/python2.7/dist-packages/keystone/identity/core.py", line 106, in _load_config self._load_driver(assignment_api, domain) File "/usr/local/lib/python2.7/dist-packages/keystone/identity/core.py", line 83, in _load_driver domain_config['cfg'].identity.driver, domain_config['cfg'])) File "/usr/local/lib/python2.7/dist-packages/keystone/openstack/common/importutils.py", line 40, in import_object return import_class(import_str)(*args, **kwargs) File "/usr/local/lib/python2.7/dist-packages/keystone/common/dependency.py", line 51, in wrapper self.__wrapped_init__(*args, **kwargs) TypeError: object.__init__() takes no parameters 2013-08-21 16:21:38 INFO [access] 15.253.57.88 - - [21/Aug/2013:23:21:38 +0000] "POST https://havanatest:35357/v3/auth/tokens HTTP/1.0" 400 100 Mark File “/keystone/common/dependency.py” has a method named “requires” which is a decorator for the “Assignment” class of both files “/keystone/assignment/backends/ldap.py” and “/keystone/assignment/backends/sql.py”. File “/keystone/assignment/backends/ldap.py”: @dependency.requires('identity_api') class Assignment(assignment.Driver): File “/keystone/assignment/backends/sql.py”: @dependency.requires('identity_api') class Assignment(sql.Base, assignment.Driver): When I specify the following contents for file “/etc/keystone/domains/keystone.Default.conf” I am telling Keystone to use an SQL backend for the default domain: [assignment] driver = keystone.assignment.backends.sql.Assignment [identity] driver = keystone.identity.backends.sql.Identity [ldap] However, there is a problem with the following line in method requires of file “dependency.py”:     def wrapper(self, *args, **kwargs):         """Inject each dependency from the registry."""         self.__wrapped_init__(*args, **kwargs)         for dependency in self._dependencies:             if dependency not in REGISTRY:                 if dependency in _future_dependencies:                     _future_dependencies[dependency] += [self]                 else:                     _future_dependencies[dependency] = [self]                 continue             setattr(self, dependency, REGISTRY[dependency]) because it is passing arguments to the constructor of the Assignment class in file “/keystone/assignment/backends/sql.py” which extends the sql.Base class (i.e. class Base(object) of file “/keystone/common/sql/core.py“) that extends class “object” which does not accept any parameters for its constructor. It took me a full day to pin this one down. To get around this problem I added the following lines to class Base(object) of file “/keystone/common/sql/core.py“ in order to accept any number of parameters:     def __init__(self, *args, **kwargs):         super(Base, self).__init__()
2013-08-27 00:42:50 Dolph Mathews keystone: status New Incomplete
2013-08-29 00:51:02 Dolph Mathews summary Split LDAP/SQL Identity Frontend Domain Selection Bug dependency injection fails to init domain-specific identity drivers
2013-08-29 00:51:10 Dolph Mathews keystone: status Incomplete Triaged
2013-08-29 00:51:15 Dolph Mathews keystone: importance Undecided Medium
2013-08-29 00:51:24 Dolph Mathews bug added subscriber David Stanek
2013-08-29 15:22:15 David Stanek keystone: status Triaged Incomplete
2013-09-06 19:07:50 Dolph Mathews keystone: milestone next
2014-09-03 12:53:37 Bruno Bompastor bug added subscriber Bruno Bompastor
2014-09-08 10:25:08 Marcus Klein keystone: status Incomplete New
2014-09-08 10:28:12 Marcus Klein keystone: status New Invalid
2014-09-08 10:39:40 Marcus Klein keystone: status Invalid New
2014-09-08 11:58:33 Henry Nash keystone: assignee Henry Nash (henry-nash)
2014-09-08 13:32:54 Henry Nash keystone: milestone next juno-rc1
2014-09-12 21:34:40 OpenStack Infra keystone: status New In Progress
2014-09-15 00:08:36 OpenStack Infra keystone: assignee Henry Nash (henry-nash) Brant Knudson (blk-u)
2014-09-15 00:19:18 Brant Knudson keystone: assignee Brant Knudson (blk-u) Henry Nash (henry-nash)
2014-09-15 00:19:35 Brant Knudson summary dependency injection fails to init domain-specific identity drivers Can't use sql as domain-specific driver
2014-09-17 22:11:57 OpenStack Infra keystone: assignee Henry Nash (henry-nash) Morgan Fainberg (mdrnstm)
2014-09-18 09:17:44 OpenStack Infra keystone: assignee Morgan Fainberg (mdrnstm) Henry Nash (henry-nash)
2014-09-18 16:42:58 OpenStack Infra keystone: status In Progress Fix Committed
2014-09-30 07:04:23 Thierry Carrez keystone: status Fix Committed Fix Released
2014-10-16 08:21:36 Thierry Carrez keystone: milestone juno-rc1 2014.2
2014-10-16 15:41:00 Dolph Mathews tags juno-backport-potential
2014-10-16 15:41:38 Dolph Mathews tags juno-backport-potential
2015-05-16 04:35:32 Krishna bug added subscriber Krishna