Libcloud now supports OpenStack Identity (Keystone) API v3
I have recently pushed support for OpenStack Identity API v3 to Libcloud trunk. In this blog post I’m going to have a look at the motivation for that, changes which were involved and show some examples of how you can utilize those changes and newly available features.
What is OpenStack Keystone / Identity service?
OpenStack Keystone is an OpenStack project that provides identity and authentication related features to OpenStack projects such as Nova.
The project started as a simple service which only provided basic authentication features, but it has since grown into a fully fledged and powerful identity management service.
The latest version supports advanced user management, multiple projects, complex ACLs and more.
Future release will also include a Keystone to Keystone federation feature which will makes things such as a seamless cross-cloud authorizations possible.
Motivation
Support for OpenStack Nova was first added to Libcloud back in 2011. First version only included support for a simple token based authentication.
Since then a lot has changed and new (and more flexible) OpenStack Keystone versions have been released. We have been pretty good at following those changes and support for authenticating against Keystone API v2.0 has been available in Libcloud for a long time.
Those changes worked fine, but the problem was that not much thinking went into them and support for multiple Keystone versions was added after the fact. This means that the code was hacky, inflexible, hard to re-use and extend.
Luckily, those things were (mostly) hidden from the end user who just wanted to connect to the OpenStack installation. They only became apparent if you wanted to talk directly to the Keystone service or do anything more complex with it.
For one of the features we are working on at DivvyCloud, we needed support authenticating and talking to OpenStack Keystone API v3. Since Libcloud didn’t include support for this version yet, I decide to go ahead and add it.
All of the “hackiness” of the existing code also became very apparent when I wanted to add support for API v3. Because of that, I have decided to spend more time on it, do it “the right way” and refactor the existing code to make it more re-usable, extensible and maintainable.
Refactoring the existing code
Before my changes, all of the logic for talking to Keystone, handling of the
token expiration, re-authentication, etc. was contained in a single class
(OpenStackAuthConnection
).
To authenticate, there was one method per Keystone API version (authenticate_1_0
,
authenticate_1_1
, authenticate_2_0_with_apikey
,
authenticate_2_0_with_password
). This means there was a lot of duplicated
code, the code was hard to extend, etc.
I went ahead and moved to a “base class with common functionality” + “one class per Keystone API version” model. This approach has multiple advantages over the old one:
- the code is easier to re-use, maintain and extend
- version specific functionality is available via methods on the version specific class
- less coupling
Some other notable changes are described bellow.
Identity related code has been moved to a separate (independent) module
All of the identity related code has been moved from libcloud.common.openstack
to
a new libcloud.common.openstack_identity
module.
This module reduces coupling between general OpenStack and Identity related code and makes code re-use and other things easier.
Improvements in the service catalog related code
Before my changes, parsed service catalog entries were stored in an
unstructured dictionary on the OpenStackServiceCatalog
class. To make
things even worse, the structure and the contents of the dictionary differed
based on the Keystone API version.
Dynamic nature of Python can be a huge asset and can make development and prototyping faster and easier. The problem is that when it’s abused / overused it makes code hard to use, maintain and reason about. Sadly, that’s pretty common in the Python world and many times, people tend to over-use dictionaries and base their APIs around passing around unstructured dictionaries.
I refactored the code to store service catalog entries in a structured format
(a list of OpenStackServiceCatalogEntry
and
OpenStackServiceCatalogEntryEndpoint
objects).
Now only the code which parses service catalog responses needs to know about the response structure. The user itself doesn’t need to know anything about the internal structure and the code for retrieving entries from the service catalog is API version agnostic.
Addition of the administrative related functionality
In addition to the changes mentioned above, OpenStackIdentity_3_0_Connection
class now also contains methods for performing different administrative related
tasks such as user, role, domain and project management.
Examples
This section includes some examples which show how to use the newly available functionality. For more information, please refer to the docstrings in the openstack_identity module.
Authenticating against Keystone API v3 using the OpenStack compute driver
This example shows how to authenticate against Keystone API v3 using the OpenStack compute driver (for the time being, default auth version used by the compute driver is 2.0).
Obtaining auth token scoped to the domain
This example show how to obtain a token which is scoped to a domain and not to a project / tenant which is a default.
Keep in mind that most of the OpenStack services don’t yet support tokens which are scoped to a domain, so such tokens are of a limited use right now.
Talking directly to the OpenStack Keystone API v3
This example shows how to talk directly to OpenStack Keystone API v3 and perform administrative tasks such as listing users and roles.
A quick note on backward compatibility
If you only use OpenStack compute driver, those changes are fully backward compatible and you aren’t affected.
If you use OpenStackAuthConnection
class to talk directly to the Keystone
installation, you need to update your code to either use the new
OpenStackIdentityConnection
class or a version specific class since
OpenStackAuthConnection
class has been removed.