Adding a user to a domain fails with ldap identity and sql assignment driver

Bug #1382822 reported by Mahesh Sawaiker
16
This bug affects 3 people
Affects Status Importance Assigned to Milestone
OpenStack Identity (keystone)
Won't Fix
Undecided
Unassigned

Bug Description

1) following is the configuration in keystone.conf. Domain specific drivers are not enabled.
[assignment]
driver = keystone.assignment.backends.sql.Assignment

[identity]
driver = keystone.identity.backends.ldap.Identity

1) Create a domain using curl.
curl -k -sX POST -H "X-Auth-Token:7f981073c17e4288adaa69291d7873bb" -H "Accept: application/json" -H "Content-Type: application/json" -H "Content-type: application/json" https://<ip>:5000/v3/domains -d '{"domain": {"description": "MaheshTest","enabled": "true","name": "MaheshTest"}}'

2) Check if the domain is created. Indeed its there.
curl -k -sX GET -H "X-Auth-Token:7f981073c17e4288adaa69291d7873bb" -H "Accept: application/json" -H "Content-Type: application/json" -H "Content-type: application/json" https://172.20.14.120:5000/v3/domains/172e2bb98f744d21b1b8124d39ef7500
{"domain": {"links": {"self": "https://192.168.101.10:5000/v3/domains/172e2bb98f744d21b1b8124d39ef7500"}, "enabled": true, "description": "MaheshTest", "name": "MaheshTest", "id": "172e2bb98f744d21b1b8124d39ef7500"}}

3) Try creating a user in this domain
 curl -k -sX POST -H "X-Auth-Token:7f981073c17e4288adaa69291d7873bb" -H "Accept: application/json" -d '{"user":{"name": "mahesh_in_domain","password": "Sm4rtcl0ud!","enabled": true,"email": "<email address hidden>","domain_id":"172e2bb98f744d21b1b8124d39ef7500" }}' -H "Content-type: application/json" https://172.20.14.120:5000/v3/users

The problem is this function in file /usr/lib/python2.6/site-packages/keystone/identity/core.py, _clear_domain_id should not be called if Domain specific drivers is not enabled, more so considering its an experimental feature. Also i don't really understand why ldap driver is marked as domain_aware false, that may be a candidate for a new bug.

def create_user(self, user_id, user_ref):
        user = user_ref.copy()
        user['name'] = clean.user_name(user['name'])
        user.setdefault('enabled', True)
        user['enabled'] = clean.user_enabled(user['enabled'])

        # For creating a user, the domain is in the object itself
        domain_id = user_ref['domain_id']
        driver = self._select_identity_driver(domain_id)
        if not driver.is_domain_aware():
            user = self._clear_domain_id(user)
        ref = driver.create_user(user_id, user)
        if not driver.is_domain_aware():
            ref = self._set_domain_id(ref, domain_id)
        return ref

    def _clear_domain_id(self, ref):
        # Clear the domain_id, and then check to ensure that if this
        # was not the default domain, it is being handled by its own
        # backend driver.
        ref = ref.copy()
        domain_id = ref.pop('domain_id', CONF.identity.default_domain_id)
        if (domain_id != CONF.identity.default_domain_id and
                domain_id not in self.domain_configs):
                    raise exception.DomainNotFound(domain_id=domain_id)
        return ref

Revision history for this message
Rodrigo Duarte (rodrigodsousa) wrote :

AFAIK, LDAP backend doesn't support domains (doesn't store the domain reference), that's why eveything stored there needs to point to the "default"domain (you can check the "gets" methods, where everything is retrieved and a reference to the default domain is added).

Revision history for this message
Mahesh Sawaiker (mahesh-sawaiker) wrote :

Defect seems to have been caused by bug https://bugs.launchpad.net/keystone/+bug/1293698.
Problem is heat needs a separate domain on its own, and a heat domain admin, which kind of conflicts with making the ldap driver domain unaware.

Revision history for this message
Dolph Mathews (dolph) wrote :

There's not really a bug report here -- what's the misbehavior you're seeing after step 3? The bug description jumps straight into a solution/analysis without identifying the problem.

I suspect Rodrigo is correct though; if you're getting a 4xx error (IIRC), then the LDAP driver is behaving as intended.

Changed in keystone:
status: New → Incomplete
Revision history for this message
Mahesh Sawaiker (mahesh-sawaiker) wrote :

I am getting a 404 domain not found raise exception.DomainNotFound(domain_id=domain_id).
But clearly the domain exists when I do a check as per step 3.

We either need to change behavior or change the exception message to be more useful.
"Domain not Found" when i try to add a user to a domain that is otherwise visible to me, is not very useful.

Revision history for this message
Mahesh Sawaiker (mahesh-sawaiker) wrote :

Correction to above comment, its step 2 (not step 3) in the description where the domain is visible to me.

Revision history for this message
Morgan Fainberg (mdrnstm) wrote :

The LDAP driver is marked as domain aware = false meaning that the users within a given domain backend are not "owned" by another domain. This is primarily a choice because of the complexity with mapping the domain in a clean way within the LDAP identity backend and the already limited number of attributes that are available in a standard LDAP schema. This all stems from using the same backend driver for read-only LDAP and read-write LDAP. In almost every case the LDAP administrators in the read-only case would not use a custom schema. In a read-write case we (in theory) could demand it as Keystone is managing the data.

The only way to have LDAP users belong to another domain (e.g. created "in" that domain) would be to use the per-domain-identity driver functionality.

The specific 404 error you're seeing has been resolved in the Juno release by the full implementation (no longer experimental) of the per-domain identity backends the code no longer raises the 404, but still users *must* be part of the default domain in this case (LDAP identity configured as you've outlined):

   def _clear_domain_id_if_domain_unaware(self, driver, ref):
        """Clear domain_id details if driver is not domain aware."""
        if not driver.is_domain_aware() and 'domain_id' in ref:
            ref = ref.copy()
            ref.pop('domain_id')
        return ref

I'm marking this as "won't fix" since the bug is mostly reporting that the LDAP Identity backend should be made domain aware, which is an explicit design choice to not implement.

Changed in keystone:
status: Incomplete → Won't Fix
Revision history for this message
Mahesh Sawaiker (mahesh-sawaiker) wrote :

All makes sense until you start to wonder why users from different domains can be stored in the same db if one is using the sql driver.
If LDAP driver is not domain aware, why is the database?

May not be right place to ask this question, but it would be good to have an answer :)
What happens if I configure domain specific drivers, and i have two domains pointing to two different LDAPs, where is the domain id stored in that case, how does the keystone driver know which user belongs to which domain. How can an admin get a list of users in all domains?

To post a comment you must log in.
This report contains Public information  
Everyone can see this information.

Other bug subscribers

Remote bug watches

Bug watches keep track of this bug in other bug trackers.