LDAP and multi-domain Keystone

by HEIG-Cloud

Tags:

Posted on Thu, Dec 17, 2015


What is LDAP?

LDAP is a protocol used to talk to a directory, one often hears of an “LDAP directory” when the directory supports LDAP (which almost all do). A directory is a specialized database for storing information about users, like their userid, password, name, email address, location, and so on (it can also be used to store info about machines or services). For those who are more familiar with Microsoft’s world, you’ve probably already heard about Active Directory. This is “nothing more” than a particular implementation of a directory made by Microsoft which happens to support LDAP.

Why do I need a directory?

Well, why do we all have a contact app on our mobile phones for instance? Because it’s not easy to remember and manage all the contacts we have. It’s also possible to put people into groups (familiy, friends, job, ennemies?). Well LDAP servers are here to provide a similar kind of service but for an organization (company, university, association, and so on).

What can I store in a directory?

Well, pretty much everything if you want. But usually we’ll find information about:

  • People
    • Userid
    • Password
    • Surname, family name
    • Email address
    • Location (office)
  • Groups
    • Name of the group
    • Which people are members of the group
  • Personal computers and servers
    • Machine id
    • Machine name
    • Users allowed to login
  • Rooms
    • Room number

So yes, it’s possible to store in it a lot of different information.

For us the most important information is going to be the userid and password of a user. When that information is stored on a directory, one says that directory contains accounts.

Why do I need a directory in OpenStack?

First, let’s see what Keystone does before we can answer that question. Keystone is one of the main parts of the OpenStack project. It has two main jobs:

  • To authenticate users
  • To authorize users

Both these points may sound like they are the same but they are not. The first part is authentication (warning: this will be very brief, naive and incomplete, but as always, it should be enough, you can always find more information about this on the internet). To explain this, let’s make an easy scenario. We have two people and a door. One of them is a guard whose name is Keystone. he is posted in front of the door leading to the wonderful world of OpenStack. The other one wants to go through, that’s Bob, a simple user.

Bob and Keystone

In this case, Keystone is responsible for authenticating and authorizing the users of the door. Keystone knows Bob, because they are buddies, so he lets him through.

Why are Keystone and Bob buddies? Because Bob has an entry in Keystone’s directory where his userid and password are stored.

Even OpenStack internal components need to authenticate with Keystone

We have pictured Keystone as the guard who checks people who want to enter the world of OpenStack from outside. But even the internal components of OpenStack (Nova, Swift, Neutron, etc.) need to authenticate with Keystoneto do internal stuff. They do this by providing a password, exactly like the external users do. Keystone’s directory has an account for each of the internal components with a userid and password. These are called service accounts.

LDAP and Keystone

So, why are we talking about LDAP, AD and all that on this blog? In a nutshell, we’ve added a domain to Keystone that delegates the authentication of users to the Active Directory of our organization.

Why would you do that?

To answer that question let’s return to our guard Keystone who stands at the door of OpenStack. Now let’s say that Carl wants to go through, and Keystone does not know him (Carl is not in Keystone’s directory).

Bob and Keystone

The thing is, Carl can authenticate himself in a different way. If Keystone trusts somebody else and accepts an authentication make with that somebody else (let’s say an LDAP server for example), it can work.

Bob and Keystone

So here, Carl was granted the authorization by Keystone after LDAP vouched for him (authentication part).

So in the end, it’s possible to have 2 different kind of systems:

  • Keystone authenticates and authorizes an user.
  • Another service authenticates an user and Keystone authorizes him.

No matter the situation, Keystone has the final saying as to the permissions given to the users but will recognize the identity of the users if given by a trusted source (LDAP, AD, or other).

Domains

In Keystone, it’s possible to define domains. Domains contain users, projects, groups, etc. The cool thing about them is the fact that it’s possible to have different sources of users for each domain. For example, we have two domains in our setup:

  • default domain, that contains the OS services
  • heig-vd domain, that links to our AD, used for authentication of our users.

It allows us to give access to our cloud to all the users already managed in the AD without having to manage them ourselves. The other cool thing is, Keystone is still responsible of authorizing the users, so once a user is authenticated with LDAP/AD, he will follow keystone’s instructions. By default, a user has “user” permissions, which basically allows him to create instances. He does not have access to the management interface and can only do limited operations. That’s why we have a multi-domain setup.

Keystone multidomain configuration

Multi-domain

The possibility of having multiple domains came with version 3 of the Keystone API. By default, there is only one domain called default. It contains the admin user account and service accounts for each of the OpenStack services (Glance, Nova, Neutron, etc.). The cloud admin can then add some projects, users or groups to this domain. It means that the admin needs to add the users and manage them. That’s not exactly nice. That’s why it’s now possible to have multiple domains. We already explained earlier that we have two domains. The great thing about that is that it allows us to separate the users from the services and we also don’t need to manually add the users Keystone’s directory. All we have to do is give the users the right permissions.

The following image shows you what it’s possible to achieve with multi-domain Keystone:

Multi-domain Keystone

So what do we have?

Domain 1

This domain contains one project Proj 1. There is one group, called Group 1 that has rights on this project. There are also two users Admin and Carl who are presently not linked to any project.

Domain 2

This domains contains two projects. Each project has a group associated to it.

So?

What we wanted to show here is, it’s possible to manage users by groups or individually. You can say for example, all the people in this group can work on this project. Or you can choose to associate Group 1 to Proj 1 but also authorize Carl to work on it.

Groups != roles

When we talk about groups and users, we are talking about authentication accounts that you’ll find on your AD or LDAP server. However, roles are managed by Keystone. Usually there are two roles (you can obviously create more but you’ll need to change the policy.json file):

  • admin, which is pretty much self-explanatory
  • user (sometimes _member_), no administration rights.

Be careful, the old policy file does not manage domains, it means that someone who is an admin can manage all domains. To prevent that, you need to update the policies, you can find it here. Depending on your configuration, if you only plan to have a domain for users working with LDAP and one admin to manage all of that, the old policy file can be acceptable.

Enable multi-domain Keystone

There are only a few operations you need to do to enable multi-domain Keystone:

$ sudo nano /etc/keystone/keystone.conf

and add the following lines:

domain_specific_drivers_enabled = True 
domain_config_dir = /etc/keystone/domains

It will tell keystone to look in the /etc/keystone/domains/ directory for domain-specific configuration files. Now you can also create this directory

$ sudo mkdir /etc/keystone/domains

Next step is to create the configuration file for your domain. Name it following this pattern:

keystone.<domain_name>.conf

In our case it’s

keystone.heig-vd.conf

The content of this file is the configuration that tells Keystone how to talk to your LDAP server. It’s a good idea to create on the LADP server a user that has read-only rights that Keystone can use to authenticate itself with the LDAP server. To create this file, you can use this link, it provides some good information. Or try to complete the following:

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

[ldap]
url = ldap://localhost
suffix = DC=mysite,DC=com
query_scope = sub # Means that you want to check sub-trees
user = CN=openstackuser,OU=users,DC=mysite,DC=com
password = pa$$word
use_dumb_member = False

user_tree_dn = OU=users,dc=mysite,dc=com

user_objectclass = person

user_id_attribute = cn
#user_id_attribute = uidNumber
user_name_attribute = sAMAccountName
user_mail_attribute = mail
user_pass_attribute = password
user_enabled_attribute = userAccountControl

group_tree_dn = OU=groups,dc=mysite,dc=com
group_objectclass = organizationalUnit 
group_id_attribute = name
group_name_attribute = name
#group_member_attribute = member
#group_desc_attribute = description

user_allow_create = false
user_allow_update = false
user_allow_delete = false
project_allow_create = false
project_allow_update = false
project_allow_delete = false
role_allow_create = false
role_allow_update = false
role_allow_delete = false
group_allow_create = false
group_allow_update = false
group_allow_delete = false

This configuration should work for Active Directory. It’s also possible to skip the part where you create a new user account for Keystone in case your LDAP directory is open for everyone to read (which is not really recommended, but well…).

The last step is to enable multi-domain login on Horizon. When you do that, Horizon will show an extended login page on its web UI. It will add a “domain” line where users have to say in which domain they want to login:

Multi-domain Keystone

The line to change is here:

$ sudo nano /etc/openstack-dashboard/local_settings.py
# Overrides for OpenStack API versions. Use this setting to force the
# OpenStack dashboard to use a specific API version for a given service API.
# Versions specified here should be integers or floats, not strings.
# NOTE: The version should be formatted as it appears in the URL for the
# service API. For example, The identity service APIs have inconsistent
# use of the decimal point, so valid options would be 2.0 or 3.
OPENSTACK_API_VERSIONS = {
    "data-processing": 1.1,
    "identity": 3,
    "volume": 2,
}

# Set this to True if running on multi-domain model. When this is enabled, it
# will require user to enter the Domain name in addition to username for login.
OPENSTACK_KEYSTONE_MULTIDOMAIN_SUPPORT = True

Here the important things are:

identity: 3 # It tells horizon to use the V3 of Keystone

OPENSTACK_KEYSTONE_MULTIDOMAIN_SUPPORT = True #This one is pretty easy to understand ;-)

There is an other thing to change in this file (and that made us waste a lot of time so you’ll thank us one day), here it is:

# We recommend you use memcached for development; otherwise after every reload
# of the django development server, you will have to login again. To use
# memcached set CACHES to something like
SESSION_ENGINE = 'django.contrib.sessions.backends.cache'
CACHES = {
    'default': {
        'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
        'LOCATION': '127.0.0.1:11211',
    }
}

What is that? This is where the sessions are stored. By default, they are not stored on memcached. What is the problem? There is a size limit! It works fine without multi-domain but once you enable it, you can have some problems that are very bizarre. In our case, before we changed the sessions engine, we could not switch between projects. Let’s say user A has access to the projects P1 and P2, he could not change from one to the other. This was not easy to find, so we are writing it down hoping it will help some people :)

Note: obvioulsy, we presume that you have memcached installed, which should be the case if you followed the official installation guide for OS Kilo.

Conclusion

Enabling a LDAP-backend for authentication is not hard on OpenStack, the problems you may encounter are the creation of the config file for your domain, the fact that you may be using the V2 of Keystone (which does not know about domains at all), the sessions engine not configured on memcached and that’s pretty much all. If you followed the guide, it already makes you work with the V3 when it’s possible.

Also, note that when you use the CLI or the API, you also need to specifiy the region, the id of the project’s domain and the id of the user’s domain (in addition to all the other options that were already asked by the v2 of Keystone, like the username, password, project, etc.).