[Openstack] Bug Found: Support domain-specific Identity Backends
Miller, Mark M (EB SW Cloud - R&D - Corvallis)
mark.m.miller at hp.com
Fri Aug 23 21:56:50 UTC 2013
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 at 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 at 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 at hp.com<mailto:mark.m.miller at 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 at hp.com<mailto:mark.m.miller at 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
From: Dolph Mathews [mailto:dolph.mathews at gmail.com]
Sent: Monday, August 19, 2013 4:33 PM
To: openstack at lists.openstack.org<mailto:openstack at lists.openstack.org>
Subject: [Openstack] Fwd: [keystone] Support domain-specific Identity Backends
On Mon, Aug 19, 2013 at 6:09 PM, Miller, Mark M (EB SW Cloud - R&D - Corvallis) <mark.m.miller at hp.com<mailto:mark.m.miller at hp.com>> wrote:
Hello Dolph,
We have recently been looking for a way to access multiple LDAP servers from a single Keystone server. It looks like the code you just finished provides this functionality. Am I correct?
I assume you're referring to this blueprint:
https://blueprints.launchpad.net/keystone/+spec/multiple-ldap-servers
Which was implemented in a commit by henry nash:
https://review.openstack.org/#/c/39530/
If so, do you have any sample configuration files that demonstrate how it is implemented?
The change in itself describes basic impact on configuration:
https://review.openstack.org/#/c/39530/21/doc/source/configuration.rst
Subsequent doc work is being tracked against openstack-manuals:
https://bugs.launchpad.net/openstack-manuals/+bug/1209255
Regards,
Mark Miller
--
-Dolph
--
-Dolph
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.openstack.org/pipermail/openstack/attachments/20130823/903ee15e/attachment.html>
More information about the Openstack
mailing list