Thursday, March 27, 2014

Something I learned Integrating OpenStack with Active Directory

So during last couple of weeks, I've been testing and migrating my OpenStack environment to use Active Directory as the backend identity provider for Keystone (the identity component of OpenStack). The process itself, is actually fairly simple and well documented in the OpenStack documentation. But there are a bit of gotchas that took me a little head scratching and googling before I figured them out. Here is what I learned in this process. Maybe this could be useful for somebody who's trying to do the same:

Havana vs Grizzly

If you're still running Grizzly release or older, you probably want to get to Havana before trying to integrating your system with Active Directory or LDAP in general, due to the fact before Havana, there's no separation between identity (authentication) and authorization (project and group memberships and roles). So you either have to enable keystone to update to LDAP server or manage all the OpenStack related information through LDAP server. Basically, what it mounts to is that you can't just "plug-and-play" your AD server to keystone--you'll need to do some schema planning before it can be used.

In Havana release, you can use separate backends for identity and authorization, meaning you can plug your keystone right into AD without any modification to AD's schema (well, just a little bit, see the service account section below), and still use your SQL server for authorization.

If you have been use SQL backend for authentication

If you have already setup your environment to use SQL backend, probably due to the limitation of LDAP backend in releases prior to Havana, there's a couple of things you might want to watch out switching to LDAP backend:

While there is no problem leaving your old SQL backend based user in your project/tenant as members, they do not resolve once your identity is switched, unless the value in your user id field of your LDAP backend user matches exactly with ones inside your SQL database. It normally wouldn't cause any problem unless you're trying to list membership for project/tenant, which I believe that's what the dashboard does when you try to modify projects/tenants.

My recommendation would be either record what you have in project/tenant and role assignment and remove existing entries prior to switching identity backend, or, if you feel adventures, go find out the corresponding entries for all users_id field currently exists in SQL backend, and swap them out in the "user_project_metadata" table in Keystone database.

Setup your service users

Switching identity backend means ditching your existing backends, which means all your existing useres are no longer accessible, INCLUDING YOUR SERVICE USERS!
You'll need to setup your existing service users (nova, glance, cinder, swift, etc.) on your LDAP server before you switch your identity backend, otherwise you'll run into some strange problems due to OpenStack services couldn't talk to identity service to confirm authorizations for operations.

Use Active Directory Global Catalog

If your Active Directory or LDAP server sends out referral references, python-ldap put them in the search results as a tuple in form of (None, ['referral_uri']).

In Havana, Keystone does not take this into consideration, and will fail with a message

AttributeError: 'list' object has no attribute 'iteritems'

because it's expecting the second value in the tuple to be a dictionary. This problem will be fixed in the next (Icehouse) release as seen from this github commit. But if you're using Havana, you either have to patch it yourself, (line 602-604 in core.py in that github commit), or if you're using Active Directory, instead of talking to standard LDAP ports (389/636), use Global Catalog ports (3268/3269) where it will not send out referral references.

Set page_size

If you have enough user in your LDAP/AD, non-paged LDAP call will get a 'Size limit exceeded' error. You'll need to set your "page_size" option in your Keystone's [ldap] section to make sure you don't run into the problem.

Make sure your python-ldap is version 2.3

Due to the change in python-ldap, paged query has a different API in version 2.4 and is not backward compatible. If for any weird reason (you probably wouldn't, I only stumbled upon it because of some bizarre case with my test environment) your python-ldap is version 2.4 or above (check it with 'pip show python-ldap'), you would want to downgrade it to version 2.3. Otherwise you'd be seeing a "AttributeError: 'module' object has no attribute 'LDAP_CONTROL_PAGE_OID'" showing up in your logs.