by HEIG-Cloud
Posted on Thu, Dec 17, 2015
LDAP is a protocole used to create a directory, we often speak of LDAP directories. For those who are more familiar with Microsoft’s world, you’ve probably already heard about Active Directory. This is “nothing more” than a special implementation of LDAP made by Microsoft. Of course that’s not true, but it’s possible to get both to work together. It’s not the aim of this post though ;-) (Even if we use Active Directory, or AD for short, and not another LDAP implementation).
Well, why do we all have an annuary on our celle phones for instance? Because it’s not easy to remember and manage all the contacts we have. It’s also possible to groupe people (familiy, friends, job, ennemies?). Well LDAP servers are here to provide that same kind of service but for an institution.
Well, pretty much everything to be honest. Usually we’ll find:
So yes, it’s possible to store in a lot of information.
So, why are we talking about LDAP, AD and all that on this blog? Quite simple, we’ve added a domain that makes use of AD to authentificate users.
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:
Both these points may sound like they are the same but they are not. The first part is authentification (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.
In this case, Keystone is responsible for authentificating and authorizing the users of the door. Keystone knows Bob, because they are buddies, so he lets him through.
Now let’s say that Carl wants to go through, Keystone does not know him.
The thing is, Carl can authentificate himslef differently. If keystone accepts authentification from that other medium (let’s say a LDAP server for example), it can work.
So here, Carl was granted the authorization by Keystone after LDAP vouched for him (authentification part).
So in the end, it’s possible to have 2 different kind of systems:
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).
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:
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 authentificated 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.
The possibility of having multiple domains came with the v3 of the Keystone API. By default, there is only one domain called “default”. It contains the admin user and the 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 2 domains earlier, the truth is we can separate the users from the services and we also don’t need to manually add the users to the authentification pool. 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:
So what do we have?
This domain contains 1 project. There is one group, called group 1 that has rights on this project. There are also 2 users who are presently not linked to any project.
This domains contains 2 projects. Each project has a group associated.
What we wanted to show here is, it’s possible to manage users by groups or individually. You can say, all the people in this group can work on this project or for instance chose to associate group 1 to the proj 1 but also authorize Carl to work on it.
When we talk about groups and users, we are talking about authentification accounts that you’ll find on your AD or LDAP server. However, Roles are managed by Keystone. Usually there are 2 roles (you can obviously create more but you’ll need to change the policy.json file):
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.
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 conf files. Now you can also create this directory
$ sudo mkdir /etc/keystone/domains
Next step is to create the conf file for your domain. Name it like:
keystone.domain_name.conf
In our case it’s > keystone.heig-vd.conf
The content of this file is the configuration of your LDAP server. It’s a good idea to create an user that has read-only rights on the LDAP server that you’ll use for your authentification process. 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 not use an user if you LDAP directory is open (which is not really good but well…).
The last step is to enable multi-domain login on horizon, it will add a “domain” line that you’ll have to fill when logging on the dashboard.
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 curious. 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.
Enabling a LDAP-backend for authentification 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.).