Once upon a time OpenStack had one big grouping of users and projects that were managed by a centralized administration group. Nice and simple for small, single organization clouds. As the use of OpenStack expanded there was a need to have multiple different groupings of users and projects (domains) in a single cloud. Some examples include a public cloud hosting multiple customers and a large private cloud wanting to isolate resources by department. This opens up the opportunity for the administration of the domains to be pushed out of the centralized administration group and into the domain itself.

Let’s get a little terminology out of the way. A cloud admin is a cloud user that can perform any operation on a given cloud. A domain admin is a cloud user that can perform operations only within the domain where they have the admin role. A domain member is a regular user that has access to a cloud. This post will focus on the domain admin concept.

Prerequisites

This post was tested against a brand new devstack instance. The easiest way to follow along is to create a devstack instance and execute the commands documented below. This will allow you to try it out and experiment a little before you go and start testing against a real cloud.

All of the commands used in this post will use the OpenStack Client and the os-cloud-config YAML config created by devstack. It’s possible to use the old style environment variables if you are feeling nostalgic.

My devstack instance was created on Fedora by the fedora user (i.e. running stack.sh as the fedora user). When I run the commands below I do it as that user.

You will also need to disable the v2 API in keystone. The v2 API isn’t domain aware and will no longer work with the policy used below.

Setup

Let’s start by setting up some test data:

$ openstack --os-cloud devstack-admin domain create accounting
+-------------+----------------------------------+
| Field       | Value                            |
+-------------+----------------------------------+
| description |                                  |
| enabled     | True                             |
| id          | 3d93bdce22e44d4da6641b68ff0751cb |
| name        | accounting                       |
+-------------+----------------------------------+

$ openstack --os-cloud devstack-admin domain create devops
+-------------+----------------------------------+
| Field       | Value                            |
+-------------+----------------------------------+
| description |                                  |
| enabled     | True                             |
| id          | a3682f37c4a54c4487133928cb61b801 |
| name        | devops                           |
+-------------+----------------------------------+

$ openstack --os-cloud devstack-admin group create --domain devops devops_admins
+-------------+----------------------------------+
| Field       | Value                            |
+-------------+----------------------------------+
| description |                                  |
| domain_id   | a3682f37c4a54c4487133928cb61b801 |
| id          | 795205cec7064786a5d3230654a927a1 |
| name        | devops_admins                    |
+-------------+----------------------------------+

$ openstack --os-cloud devstack-admin user create --domain devops --password password hackstar
+---------------------+----------------------------------+
| Field               | Value                            |
+---------------------+----------------------------------+
| domain_id           | a3682f37c4a54c4487133928cb61b801 |
| enabled             | True                             |
| id                  | 3b85f8774a224c069b1d501a5700adf4 |
| name                | hackstar                         |
| password_expires_at | None                             |
+---------------------+----------------------------------+

$ openstack --os-cloud devstack-admin group add user devops_admins hackstar
hackstar added to group devops_admins

$ openstack --os-cloud devstack-admin role add --group devops_admins --domain devops admin

We’ve now created a simple structure based on two domains accounting and devops. The devops domain is getting a group named devops_admins that has the admin role. A user hackstar was created in the domain and added to the group. So let’s try to get our domain admin working. The accounting domain was created just to prove out our policy.

Policy

The default keystone policy is still enforces that old, crusty single grouping of users. It just distinguishes between admin and member roles. keystone also has a sample policy for that is designed to be used with a domain-based v3 cloud.

We need to use this policy so we’ll just copy it over. In a real cloud this isn’t as easy to do. You’ll want to evaluate the changes to the rules and reconcile them with any changes you’ve made.

$ cp /opt/stack/keystone/etc/policy.v3cloudsample.json /etc/keystone/policy.json
$ sudo systemctl restart httpd.service

If you’re running ubuntu you will use sudo service apache2 restart to restart Apache.

We’re also going to want to use our new hackstar account to query our cloud. Let’s add another entry into /etc/openstack/clouds.yaml to more easily facilitate this.

I added the following section to the bottom of that file. Watch your indentation!

  devops-admin:
    auth:
      auth_url: http://162.209.99.157/identity_admin
      password: password
      domain_name: devops
      user_domain_name: devops
      username: hackstar
    identity_api_version: '3'
    region_name: RegionOne
    volume_api_version: '2'

To test out our new entry we can simply try to get a new token:

$ openstack --os-cloud devops-admin token issue
+---------+---------------------------------------------------------------------------------------------------------------------------------+
| Field   | Value                                                                                                                           |
+---------+---------------------------------------------------------------------------------------------------------------------------------+
| expires | 2016-11-08T16:35:12+0000                                                                                                        |
| id      | gAAAAABYIfCwjDJX-Wd61shlPcUtlR0mgswxjwkiRYhZvQ0ZsXpV7cvASDwAcBdkiMK-xYQMS_DN1h_XUshMabDJT97pm7EX15s--                           |
|         | PfPP4sRyTHBXTwd80EMR7SldzAp1z_bv0UY4CMEIVdsrB4aSOhb2OR9oVaZYw                                                                   |
| user_id | 3b85f8774a224c069b1d501a5700adf4                                                                                                |
+---------+---------------------------------------------------------------------------------------------------------------------------------+

If you get a token then you are in good shape. If not you’ll have to do a little debugging to figure out if you didn’t properly edit the clouds.yaml file or if you didn’t properly setup the organization.

Testing it out

Now that we have this all working we can start administering the domain.

$ openstack --os-cloud devops-admin user list
You are not authorized to perform the requested action: identity:list_users (HTTP 403) (Request-ID: req-8626104f-0501-46a4-b207-93771a83d025)

Whoa, what happened there? It turn out it’s just our policy.json protecting us. To list users you have to either be a cloud admin or you have to have the admin role and be scoped to the domain you want to list.

Let’s specifically ask for a list of users in our domain:

$ openstack --os-cloud devops-admin user list --domain a3682f37c4a54c4487133928cb61b801

+----------------------------------+----------+
| ID                               | Name     |
+----------------------------------+----------+
| 3b85f8774a224c069b1d501a5700adf4 | hackstar |
+----------------------------------+----------+

There we go. You have a domain admin. Let’s do a few more simple tests.

NOTE: We had to specify the domain ID and not the domain name in the command. Since our policy is actually checking the domain ID as passed in through the API you must use the ID.

The policy won’t let us create users in domains where we do not have the admin role.

$ openstack --os-cloud devops-admin user create --domain accounting --password password frank
You are not authorized to perform the requested action: identity:create_user (HTTP 403) (Request-ID: req-46aa043b-a059-4a74-8958-e351da6927eb)

We do, however, have the ability to create our own users.

$ openstack --os-cloud devops-admin user create --domain a3682f37c4a54c4487133928cb61b801 --password password frank
+---------------------+----------------------------------+
| Field               | Value                            |
+---------------------+----------------------------------+
| domain_id           | a3682f37c4a54c4487133928cb61b801 |
| enabled             | True                             |
| id                  | f64fc48a24c743efbe6f3664fc3f2726 |
| name                | frank                            |
| password_expires_at | None                             |
+---------------------+----------------------------------+

NOTE: We had to use the domain ID again.

This should be enough to get you going. Give it a try.