Packstack to LDAP

While Packstack makes it easy to get OpenStack up and running, it does not (yet) support joining to an existing Directory (LDAP) server. I went through this recently and here are the steps I followed.

Overview

To start, note that I already had LDAP configured to work as a backend for OpenStack due to a Devstack setup I already had. I’m not going to go through setting that up here. But here are the broad steps that a Packstack deployment performs for you.

  • Install LDAP
  • Configure LDAP to act as a Keystone Identity Backend
  • Create the service users in Keystone

I’d highly recommend doing LDAP configuration on a separate machine from the Packstack deployment. You want Packstack to run on a clean System.

The steps to make use of the LDAP deployment from Keystone in a Packstack deployment are:

  • Install Packstack
  • Modify the Passwords for each Service users in the config files and in the SQL Backend
  • Change the Keystone configuration File to use the LDAP server as the Identity backend
  • Modify the User IDs in the role assignments

Sanity Check

Once I had a successful Packstack run, I did a quick sanity check of the services. This involved running a simple command that hit each service. Examples;

. ./keystonerc_admin
keystone token-get
nova list
glance image-list
neutron net-list
cinder list
heat list

Modifying Passwords

The first service user I modified was glance.

keystone user-password-update glance

There is no way to query the Passwords from the LDAP server. If you do not happen to know them before hand, you will have to reset them at this point. In that case, it probably makes sense to read the passwords out of the service files. In the case of glance, that value can be found with

sudo grep admin_password /etc/glance/glance-api.conf

This should match the value you get with:

sudo grep admin_password /etc/glance/glance-registry.conf

In my case, since I had defaulted the values in LDAP with the Devstack run, I set them both to “freeipa4all”.

Once I changed both the password for the service user and the values in the config files, I reran the glance sanity check.

The same general process repeats for each of the services. I left Keystone to last to avoid locking myself out. However, if that happens, there is the admin_token authentication mechanism, and I ended up using that in the next step.

Switch To LDAP

I copied the packstack generated file /etc/keystone/keystone.conf to /etc/keystone/keystone.conf.orig and modified it. Below you can see the diff. Don’t be put off by the size of this diff. The number of changes are relatively small. I just wanted to give the context so you can find where to make the appropriate changes for yourself.

$ sudo diff -u /etc/keystone/keystone.conf.orig /etc/keystone/keystone.conf
--- /etc/keystone/keystone.conf.orig 2014-04-23 20:41:11.145950013 +0000
+++ /etc/keystone/keystone.conf 2014-04-24 02:50:13.449960016 +0000
@@ -11,7 +11,7 @@
# paste application pipelines (for example, in keystone-
# paste.ini). (string value)
#admin_token=ADMIN
-admin_token=651f895f0e3b4000a8305ccf22770a29
+admin_token=freeipa4all

# The IP Address of the network interface to for the public
# service to listen on. (string value)
@@ -776,6 +776,7 @@

# Keystone Identity backend driver. (string value)
#driver=keystone.identity.backends.sql.Identity
+driver = keystone.identity.backends.ldap.Identity

# Maximum supported length for user passwords; decrease to
# improve performance. (integer value)
@@ -821,6 +822,7 @@

# URL for connecting to the LDAP server. (string value)
#url=ldap://localhost
+url=ldap://ipa.cloudlab.freeipa.org

# User BindDN to query the LDAP server. (string value)
#user=<None>
@@ -865,6 +867,7 @@

# Search base for users. (string value)
#user_tree_dn=<None>
+user_tree_dn=cn=users,cn=accounts,dc=ipa,dc=cloudlab,dc=freeipa,dc=org

# LDAP search filter for users. (string value)
#user_filter=<None>
@@ -874,9 +877,11 @@

# LDAP attribute mapped to user id. (string value)
#user_id_attribute=cn
+user_id_attribute=uid

# LDAP attribute mapped to user name. (string value)
#user_name_attribute=sn
+user_name_attribute=uid

# LDAP attribute mapped to user email. (string value)
#user_mail_attribute=email
@@ -1032,6 +1037,7 @@

# Search base for groups. (string value)
#group_tree_dn=<None>
+group_tree_dn=cn=groups,cn=accounts,dc=ipa,dc=cloudlab,dc=freeipa,dc=org

# LDAP search filter for groups. (string value)
#group_filter=<None>

I had to disable SELinux. This is not a permanent change, but the default policy does not allow keystone_t to reach the socket needed for LDAP (TCP 389). There is a ticket open in the Fedora Bugzilla to create a Boolean value much like the HTTPD one.

If you restart Keystone, none of your services will work. That is because the existing role assignments are for the old user_ids. There are many ways to fix it, but I tackled it at the database level:

sudo grep mysql /etc/keystone/keystone.conf

connection=mysql://keystone_admin:641932c83f4d48fb@192.168.187.13/keystone

mysql keystone –user keystone_admin –password=641932c83f4d48fb

Now you can update each of the existing roles as below. Note that ‘cinder’ in the first portion of the sql statement is the new user_id: My approach is for userid and username to use the same value, and treat LDAP as read-only from Keystone.

update assignment set actor_id = 'cinder'  where actor_id = (select id from user where name = 'cinder');
update assignment set actor_id = 'neutron'  where actor_id = (select id from user where name = 'neutron');
update assignment set actor_id = 'glance'  where actor_id = (select id from user where name = 'glance');
update assignment set actor_id = 'nova'  where actor_id = (select id from user where name = 'nova');
 update assignment set actor_id = 'keystone'  where actor_id = (select id from user where name = 'keystone');

Restart the openstack-keystone service and you should be able to run the sanity checks successfully.

Once this runs, you should probably delete all values from these user and group tables in SQL: they will only mislead someone that looked at the database.

A couple debugging note:

When I first tried creating a token in Keystone, I was getting 403 responses.  It turned out I had not set the user_id field for the user.  The default is ‘cn’ which means that a user-list looked correct, but that was coincidental.  Turning on debugging in keystone.conf showed the actual LDAP search.

I don’t tend to user ‘admin’ as the user name for Keystone, as it conflicts with users created elsewhere.  I tend to make the Keystone user named keystone.  Once I converted the configuration file over to LDAP, I could no longer do admin operations as keystone.  Instead, I used the admin_token.  To log in with admin_token, make sure that value is uncommented in keystone.conf, and then create a config file like this:

export OS_SERVICE_ENDPOINT=http://127.0.0.1:35357/v2.0
export OS_SERVICE_TOKEN=freeipa4all

Source that file and you can perform a limited set of administrative actions, to include listing users and assigning roles. Before you attempt to test a user, make sure that the environment variables OS_SERVICE_TOKEN and OS_SERVICE_ENDPOINT are unset:

unset OS_SERVICE_TOKEN
unset OS_SERVICE_ENDPOINT

2 thoughts on “Packstack to LDAP

  1. This is cool!! i’ve always been very fond of LDAP but unfortunately is out of the scope of packstack use cases. Anyway this is a useful guide for using packstack as starting point and then personalize the configurations 🙂

  2. One more change – I had to explicitly set the assignment driver to use sql, otherwise, it was attempting to use ldap (in Havana, anyway):

    [assignment]
    -# driver =
    +driver = keystone.assignment.backends.sql.Assignment

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.