Note: This article has been superseded by a new article: OpenStack Juno – Active Directory Integration
Updated for OpenStack Icehouse: I’ve successfully configured the OpenStack Keystone identity service to authenticate against Active Directory. The idea is to use a centralized identity service (namely Active Directory) to store and manage your user accounts, roles and projects that would otherwise be managed within OpenStack. Many enterprises prefer to maintain a central directory service and not have islands of identity within their environment. Active Directory is widely used in the corporate world, so it’s essential to be able to integrate platforms with Active Directory.
The good news is that OpenStack Keystone includes an LDAP identity provider, that can be configured to perform LDAP calls to Active Directory. We’ll need to create (or point to existing) user accounts, and create objects for roles and tenants in Active Directory. Then we’ll configure keystone to find and use those objects.
Creating the Active Directory Objects
The Keystone LDAP provider uses object classes that (though they may be considered standard in the Linux/LDAP world) are not widely used in Active Directory. These classes include organizationalRole and groupOfNames. The classes do exist in the AD schema, but the familiar graphical administration tool (Active Directory Users and Computers) does not provide dialogs for managing these object types.
So, in order to create these objects, we’ll need to use an alternative tool. For this post, I’ll use ADSIEDIT.msc, which can create and modify just about any object type. However, for day-to-day administration, I may develop a custom GUI, web-based tool, or a handful of scripts.
But first, in the familiar Active Directory Users and Computers tool, I’ll create my OU structure. From the root of my domain, I’ll create an OpenStack OU, and beneath that, I’ll create a Projects OU and a Roles OU. Finally, below Projects, I’ll create an admin OU and a service OU. The resulting OU structure is shown below.
Next, I’ll launch ADSIEDIT.msc and create two organizationalRole objects in the Roles OU. The first one will be for the admin role. In ADSIEDIT, right click the Roles OU and select new – object. Select OrganizationalRole and click next. Enter the name admin and click next. Click the More Attributes button, select the optional property roleOccupant, and enter the distringuishedName of a user that you want to grant admin rights in OpenStack. For example, if you have a user called admin in the Users container, the dn is cn=admin,cn=Users,dc=mydomain,dc=net
OK, now we also need to create a Member role, so create another organizationalRole object for that. We don’t need to add any users to this role right now.
Now on to the Projects OU. We’ve already created a sub-OU called admin. Here we’ll create two objects, another organizationalRole object called admin, and a groupOfNames object called adminUsers. Clarification here, this whole sub-OU represents the admin tenant, the admin role gives us admin access to OpenStack, and membership in the groupOfNames gives us use of the admin project.
To create these objects, in ADSIEDIT, as above, but this time under the admin OU, create an organizationalRole object, name: admin, roleOccupant: dn of our admin user. Next create a groupOfNames object, name: adminUsers, member: dn of our admin user. OK, now we have enough objects created to test authentication with our admin user.
Finally, we should enable the project OU’s (admin and service) by setting the attribute called extensionName to TRUE.
In summary, we created the OU structure, two role objects in our Roles OU, and a role object and a groupOfNAmes object in our admin project OU.
Now we can modify our keystone config to point to Active Directory. On the keystone server, edit /etc/keystone/keystone.conf. First, we change the identity provider as follows. Disable the SQL provider and add the line for the LDAP provider:
Then we configure the LDAP section to point to our OU structure in Active Directory:
Now restart the keystone service (service keystone restart or service openstack-keystone restart). Now to test authentication, type keystone user-list. Assuming that you’ve got the user name (samAccountName) and password of your Active Directory user exported in your bash session, or pasted on the end of the command, you should get back a user list from Active Directory.
Things to Note
Of course, your keystone server must be able to resolve the DNS name of your Active Directory domain, so make sure /etc/resolv.conf points to a DNS server that can resolve your domain. Also note that the user_id_attribute should be set to cn. The attribute that you use for user_name_attribute is what you may want to change depending on what your users use to logon to Windows, either sAMAccountName or userPrincipalName. Note that these are case sensitive!
The caveat, which I’ve already mentioned, is that the standard graphical tool Active Directory Users and Computers can’t be used to create and manage the objects. This is perhaps not such a big deal if your AD admins are savvy, but may be a drag for the average administrator.
Next we need to add the service tenant, user accounts for the services, and add the service accounts to the required roles. Let’s take care of glance.
First, in Active Directory Users and Computers, create a user object for glance (cn=glance) and set the password. The username and password would match what you’ve got in the keystone_authentication section of your glance-api.conf and glance-registry.conf.
Next, in ADSIEDIT, our Roles OU, edit the admin role object, edit the roleOccupant attribute, and add the dn of the glance user to the list (our admin user is already in there as well). Then in our Projects/service OU, create an organizationalRole object and add our glance user’s dn as a roleOccupant, and create a groupOfNames object, name: serviceUsers, and add the glance user dn as a member.
Now, we can test glance.
Notice that instead of displaying the uuid of the owner, the user’s Active Directory cn is displayed. I’m not sure if there are any negative implications of this within OpenStack or not. Certainly, the cn in Active Directory is not assured to be unique, although it would be advisable to make sure it is. Only distinguishedName, samAccountName and userPrincipalName is guaranteed to be unique. So there’s the potential for permissions conflicts to occur if you’re not careful.
If I lost you while creating objects. Here’s an LDAP dump of the objects I created in Active Directory:
To add the other services to AD, simply create AD user accounts for them, add them to the organizationalRole object and the groupOfNames object in the service project OU, and add them to the admin organizationalRole object as well. Here’s a link to another LDAP export where I’ve added Cinder, Nova and Swift.
I know it’s a lot of objects to manage by hand. I’m currently working on an admin GUI to make things easier. Stay tuned…
Configuring the Horizon Dashboard
If you’ve gotten to this point, you should be able to logon to the dashboard without any trouble, assuming that you added yourself an account to at least one project and role (preferably admin). However, if you now try to do anything with projects, such as modify memberships or quotas, you’ll get an error, This seems to be due to the version 3 of the identity API missing some calls that haven’t been implemented yet. However, we can configure the dashboard to use version 2 of the API and this will enable some of the functionality.
In reality, now that our objects are in Active Directory, we should use AD to manage projects and roles, at least from a membership perspective. However, project quota settings are not stored in AD, and using the version 3 API, the quota controls seem to be broken in the dashboard. The only way I’ve found to manage quotas outside the dashboard is to use the nova command line.
So, we should use the version 2 API in the dashboard for now, until the missing calls have been implemented (hopefully in the icehouse release?). To configure the dashboard, edit the /etc/openstack-dashboard/local_settings.py file, and find the following lines. Uncomment the lines and change the version from 3 to 2.0 as shown.
Next find the following lines and change the name to ldap and the can_edit_user to False as shown
Now restart the web server (service apache2 restart on Ubuntu), and now the dashboard should be able to manage project quotas. Note that if you want to manage project memberships from within the dashboard, then the ldap bind user specified in keystone.conf should be granted read/write permissions to the projects OU tree and the roles OU tree in AD, but you might consider this a security risk, as any user granted admin rights in OpenStack will then be able to modify these objects in AD via the bind user.
Good luck with your installation! I know this is complicated, but I think AD authentication is critical for mainstream enterprise adoption of OpenStack.