Chapter 1. Fundamental Keystone Topics

In this chapter we provide an introduction to the basic foundations of Keystone. We start with an overview of Keystone Projects and Domains, which are abstractions used to group and isolate resources. We then discuss how Keystone supports Users and User Groups and how Roles can be assigned to Users and User Groups on both a Project and Domain basis. We then introduce how Keystone utilizes Tokens and provides Service Catalogs. Next, we describe Keystone’s Identity service and the types of Identity backends that can be leveraged by Keystone. We then conclude this chapter with in-depth descriptions of Keystone’s Authentication and Access Management (Authorization) capabilities.

1.1 Keystone Concepts

Keystone itself has several concepts that are specific to its model and how it relates to OpenStack as a whole. These are Identity and Authorization related concepts, but their focus is on how Keystone implements Authorization, Access Management, and Discovery.

1.1.1 What’s a Project?

In Keystone, a Project is an abstraction used by other OpenStack services to group and isolate resources (e.g., servers, images, etc.). In the early days of OpenStack, Keystone Projects were originally referred to as Tenants but this was changed to Projects, a more intuitive name for this concept. It is probably fair to say that the most fundamental purpose of Keystone is to be the registry of Projects and to be able to articulate who should have access to those Projects. Projects themselves don’t own Users, but Users or User Groups are given access to a Project using the concept of Role Assignments. Having a Role assigned to a User or User Group on a Project denotes that the User or User Group has some kind of access to resources in the Project, and the specific Role selected determines the type of access and capabilities the User or User Group is entitled to have. Assigning a Role to a User is sometimes referred to as a “grant” in OpenStack documentation. Roles, Users, and User Groups are more thoroughly described in later sections of this chapter.

1.1.2 What’s a Domain?

In the early days of OpenStack, there was no mechanism to limit the visibility of Projects to different user organizations. This could result in unintentional collisions on Project names by different organizations. User names also had global visibility and could also result in undesired collisions on user names if two different organizations both used the same user name. In order for OpenStack clouds to more cleanly support multiple user organizations at the same time, Keystone added a new abstraction, called a Domain, that could provide the ability to isolate the visibility of a set of Projects and Users (and User Groups) to a specific organization. A Domain is formally defined as a collection of users, groups, and projects. Domains enable you to divide the resources in your cloud into silos that are for use by specific organizations. A domain can serve as a logical division between different portions of an enterprise, or each domain can represent completely separate enterprises.

For example, a cloud could have two domains, IBM and Acme Inc. IBM has their own collection of groups, users, and projects and so does Acme Inc.

1.1.3 Users and User Groups (Actors)

In the Keystone realm, Users and User Groups are the entities given access to resources that are isolated in Domains and Projects. Groups are a collection of Users. Users are individuals who will end up using your cloud. We refer to Users and Groups as Actors since, when assigning a role, these are the entities to which the role is “assigned to.”

1.1.3.1 Graphical representation

The relationship between domains, projects, users, and groups is shown below. Users, groups, and projects will always be “domain scoped,” meaning that a name for a user, group, and project may be common across domains. Think of this as having a user “Jim” or group “administrators” at both IBM and Acme Inc. However, each entity is guaranteed to have a universally unique identifier (UUID). This implies that trying to find a resource with just the ID will work. However, since names are not guaranteed to be unique, providing the domain is essential to find the resource. As of Liberty, roles are not domain scoped, but this could change in the future.

Figure 1-1. Domains are a collection of Users, Groups, and Projects. Roles are globally unique. Users may have membership in many Groups.

1.1.4 Roles

Roles are used in Keystone to convey a sense of Authorization. An actor may have numerous roles on a target. How the roles are used to determine authorization is covered in “1.4 Access Management and Authorization”. For example, the role of admin is “assigned to” the user “bob” and it is “assigned on” the project “development.”

1.1.5 Assignment

A role assignment is a ternary (or triple): the combination of an actor, a target, and a role. Role assignments are granted and revoked, and may be inherited between groups and users and domains and projects.

1.1.6 Targets

Projects and Domains are very similar in that both are entities where the role is “assigned on.” In other words, a User or User Group is given access to either a Project or Domain by assigning a particular Role value for that User or User Group for a specific Project or Domain. Because Projects and Domains have such similar characteristics, when we need to refer to both entities collectively we refer to them as Targets.

1.1.7 What’s a Token?

In order for a user to call any OpenStack API they need to (a) prove who they are, and (b) that they should be allowed to call the API in question. The way they achieve that is by passing an OpenStack token into the API call—and Keystone is the OpenStack service responsible for generating these tokens. A user receives this token upon successful authentication against Keystone. The token also carries with it authorization. It contains the authorization a user has on the cloud. A token has both an ID and a payload. The ID of a token is guaranteed to be unique per cloud, and the payload contains data about the user.

The payload can be seen below:

Example 1-1. An Identity V3 Scoped Token consists of many fields that indicate Identity and Authorization attributes about the user on a project
{
    "token": {
        "issued_at": "201406-10T20:55:16.806027Z",
        "expires_at": "2014-06-10T2:55:16.806001Z",
        "roles": [{
                "id": "c703057be878458588961ce9a0ce686b",
                "name": "admin"}
        ],
        "project": {
            "domain": { "id": "default",
                        "name": "Default" },
            "id": "8538a3f13f9541b28c2620eb19065e45",
            "name": "admin"
        },
        "user": {
            "domain": { "id": "default",
                        "name": "Default" },
            "id": "3ec3164f750146be97f21559ee4d9c51",
            "name": "admin"
        },
        "catalog": [
            {
                "endpoints": [...],
                "type": "identity",
                "id": "bd73972c0e14fb69bae8ff76e112a90",
                "name": "keystone"
            }
        ]
    }
}

As you can tell, the token payload contains information about when it was created, when it will expire, which user authenticated—and thus is allowed to use the token—which project the token is valid on, and finally, the catalog, which brings us to our next point. Tokens will be discussed in detail in Chapter 3.

1.1.8 What’s a Catalog?

The service catalog is essential for an OpenStack cloud. It contains the URLs and endpoints of the different Cloud services. Without the catalog, users and applications would not know where to route requests to create VMs or store objects. The service catalog is broken up into a list of endpoints, and each endpoint is broken down into an admin URL, internal URL, and public URL, which may be the same.

Example 1-2. A simple Catalog of just two services, Identity and Object Storage. Endpoints are essential to allow the user to discover where different services are hosted.
{
    "serviceCatalog": [
        {
            "endpoints": [
                {
                    "adminURL": "http: //swift.admin-nets.local: 8080/",
                    "region": "RegionOne",
                    "internalURL": "http: //127.0.0.1: 8080/v1/AUTH_1",
                    "publicURL": "http: //swift.publicinternets.com/v1/AUTH_1"
                }
            ],
            "type": "object-store",
            "name": "swift"
        },
        {
            "endpoints": [
                {
                    "adminURL": "http: //cdn.admin-nets.local:35357/v2.0",
                    "region": "RegionOne",
                    "internalURL": " http: //cdn.admin-nets.local:5000/v2.0 ",
                    "publicURL": " http: //cdn.admin-nets.local:5000/v2.0 "
                }
            ],
            "type": "identity",
            "name": "keystone"
        }
    ]
}

1.2 Identity

The Identity Service in Keystone provides the Actors. Identities in the Cloud may come from various locations, including but not limited to SQL, LDAP, and Federated Identity Providers.

1.2.1 SQL

Keystone includes the option to store your actors (Users and Groups) in SQL; supported databases include MySQL, PostgreSQL, and DB2. Keystone will store information such as name, password, and description. The settings for the database must be specified in Keystone’s configuration file. Essentially, Keystone is acting as an Identity Provider, which may not be the best case for everyone, and certainly not the best case for enterprise customers. The following provides a brief summary of the advantages and disadvantages of using the SQL Identity option.

Pros:

  • Easy to set up
  • Management of users and groups through OpenStack APIs

Cons:

  • Keystone should not be an Identity Provider
  • Weak password support
    • No password rotation
    • No password recovery
  • Most enterprises have an LDAP server they want to use
  • Identity silo: yet another username and password users must remember

1.2.2 LDAP

Keystone also has the option to retrieve and store your actors (Users and Groups) in Lightweight Directory Access Protocol (LDAP). Keystone will access the LDAP just like any other application that uses the LDAP (System Login, Email, Web Application, etc.). The settings for connecting to the LDAP are specified in Keystone’s configuration file. These options also include whether Keystone is able write to LDAP or simply read the LDAP data. Ideally, the LDAP should perform only read operations, such as user and group lookup (via search) and authentication (via bind). If using LDAP as a read-only Identity backend, Keystone should need a minimal amount of privilege to use the LDAP. For instance, it needs read access to the user and group attributes defined in keystone.conf, an unprivileged account (anonymous access is preferred), and it does not require access to password hashes. The advantages and disadvantages of the LDAP Identity option are shown below.

Figure 1-2. Keystone should use an internal LDAP just like any other application

Pros:

  • No longer need to maintain copies of user accounts.
  • Keystone does not act as an Identity Provider.

Cons:

  • Service accounts still need to be stored somewhere, and the LDAP admin may not want these accounts in LDAP.
  • Keystone is still “seeing” user passwords, since the passwords are in the authentication request. Keystone simply forwards these requests, but ideally Keystone does not want to see a user’s password, ever!

 

1.2.3 Multiple Backends

As of the Juno release, Keystone supports multiple Identity backends for the V3 Identity API. The impact of this is that a deployment may have one identity source (backend) per Keystone domain. The default domain is usually an SQL backend, as it is used to host service accounts. Service accounts are the accounts that the different OpenStack services use to interact with Keystone. Any additional LDAP backends may be hosted in their own domain. The motivation for supporting multiple Identity backends is that in an enterprise setting, LDAP administrators may not be the same organization as the OpenStack deployment team, so creating service accounts in LDAP is highly unlikely. LDAP is typically restricted to be used only for employee information. Another benefit of a logical split between Identity backends and domains is that now multiple LDAPs can be used. So, in the case of a company merger or different departments having different LDAPs, the same enterprise can still be represented. The advantages and disadvantages of multiple backends are as follows.

Figure 1-3. The Identity service may have multiple backends per domain. LDAPs for both Domains A and B, and an SQL-based backend for the service accounts is usual. The Assignment service is also shown to remind readers that the assignment, resource, and identity service may all be backed by various stores.

Pros:

  • Able to simultaneously support multiple LDAPs for various user accounts and SQL backends for service accounts
  • Leverage existing identity LDAP while not impacting it

Cons:

  • Slightly more complex to set up
  • Authentication for user accounts must be domain scoped

1.2.4 Identity Providers

As of the Icehouse release, Keystone is able to consume federated authentication via Apache modules for multiple trusted Identity Providers. These users are not stored in Keystone, and are treated as ephemeral. The federated users will have their attributes mapped into group-based role assignments. From a Keystone perspective, an identity provider is a source for identities; it may refer to software that is backed by various backends (LDAP, AD, MongoDB) or Social Logins (Google, Facebook, Twitter). Essentially, it is software (IBM’s Tivoli Federated Identity Manager, for instance) that abstracts out the backend and translates user attributes to a standard federated identity protocol format (SAML, OpenID Connect). This fits well in Keystone’s greater plan to offload the authentication and identity related portions to a service that already does this in an enterprise. The Identity Provider approach has lots of advantages and few disadvantages.

Pros:

  • Able to leverage existing infrastructure and software to authenticate users and retrieve information about users
  • Further separation between Keystone and handling identity information
  • Opens the door for new possibilities in the federation realm, such as single sign-on and hybrid cloud
  • Keystone does not see any user passwords
  • Identity provider handles authentication completely, so whether it is password, certificate, or two-factor based is irrelevant to Keystone

Cons:

  • Most complex set up of the identity sources

1.2.5 Use Cases for Identity Backends

The use cases for the different identity backends are organized in Table 1-1.

Table 1-1. List of identity sources and their most common use case

Identity Source

Use Cases

SQL

  • Use this if you’re testing or developing with OpenStack
  • Small set of users
  • OpenStack-specific accounts (service users)

LDAP

  • Use this if it’s already in place in your business
  • Use only LDAP if you are able to create the service accounts necessary in the LDAP

Multiple Backends

  • Preferred approach for most enterprises
  • Use if service users are not allowed in LDAP

Identity Provider

  • You want to take advantage of the new Federated Identity mechanisms
  • Use this if an identity provider already exists (for single sign-on)
  • Keystone is unable to access LDAP
  • Non-LDAP identity source
  • Use if LDAP interaction is offloaded to underlying platform and Web server (SSSD)

1.3 Authentication

There are various ways to authenticate with the Keystone service—by far the two most common are by supplying a password or by using a token. In this section we will be highlighting those two methods of authentication by showing the data required in a POST request to Keystone and their usual flow between the User, Keystone, and other OpenStack services.

1.3.1 Password

The most common way for a user or service to authenticate is to supply a password. The payload shown below is a sample POST request to Keystone. It is helpful to show the entire payload so the reader recognizes the information that is necessary to authenticate.

Example 1-3. An example of an authentication payload request that contains a scope.
{
    "auth": {
        "identity": {
            "methods": [
                "password"
            ],
            "password": {
                "user": {
                    "domain": {
                        "name": "example.com"
                    },
                    "name": "Joe",
                    "password": "secretsecret"
                }
            }
        },
        "scope": {
            "project": {
                "domain": {
                    "name": "example.com"
                },
                "name": "project-x"
            }
        }
    }
}

About the payload, and a note about domains

The payload of the request must contain enough information to find where the user exists, authenticate the user, and optionally, retrieve a service catalog based on the user’s permissions on a scope (project).

The user section that identifies the incoming user should have domain information (either the domain name or ID), unless a user’s globally unique ID is used, in which case that is sufficient to identify the user. This is because in a multi-domain deployment, there may be multiple users with the same name, so proper scoping is necessary to determine which user is authenticating.

The scope section is optional but is often used, since without a scope a user will not be able to retrieve a service catalog. The scope is used to indicate which project the user wishes to work against. If a user does not have a role on that project, then the request will be rejected. Similar to the user section, the scope section must have enough information about the project to find it, so the owning domain must be specified. As in the case of users and groups, project names may also conflict across domains. The project ID, however, is guaranteed to be unique and if specified, no domain information is necessary.

Figure 1-4. A user requests a token by using their username, password, and project scope. The resultant token may then be used at other OpenStack services (such as Compute or Object Storage).

1.3.2 Token

Similar to above, a user may also request a new token by providing a current token. The payload of this POST request is significantly less code than its password counterpart. There are many reasons why a token will be used to retrieve another, such as refreshing a token that will soon expire or to change an unscoped token to a scoped token.

{
    "auth": {
        "identity": {
            "methods": [
                "token"
            ],
            "token": {
                "id": "e80b74"
            }
        }
    }
}
Figure 1-5. A user requests a token by using an existing token. The resultant token will have the same scope and roles as the initial token.

1.4 Access Management and Authorization

Managing access and authorizing what APIs a user can use is one of the key reasons Keystone is essential to OpenStack. Keystone’s approach to this problem is to create a Role-Based Access Control (RBAC) policy that is enforced on each public API endpoint. These policies are stored in a file on disk, commonly named policy.json. To better understand this concept, it’s best to jump right into an example.

The following is a brief example of Keystone’s policy.json file, which is comprised of targets and rules.

Targets refer to the left-hand key, and rules refer to the right-hand value. At the top of the file, targets are established that can be used for evaluation of other targets. It is here that we define what it means to be an admin, an owner, or either.

Example 1-4. Snippet of Keystone’s policy.json file
{
    "admin_required": "role:admin or is_admin:1",
    "owner" : "user_id:%(user_id)s",
    "admin_or_owner": "rule:admin_required or rule:owner",
 
    "identity:list_projects": "rule:admin_required",
    "identity:create_project": "rule:admin_required",
    "identity:delete_project": "rule:admin_required",
 
    "identity:list_user_projects": "rule:admin_or_owner"
}

Each rule that begins with identity: and specifies a protected controller that manages an API. We use the already established targets to protect these new targets. The table below outlines which target protects which API. The full 1:1 mapping for this information can be found in Keystone’s documentation.

Table 1-2. A brief mapping of policy targets and APIs

Policy Target

API

identity:list_projects GET /v3/projects
identity:create_project POST /v3/projects
identity:delete_project DELETE /v3/projects/{project_id}
identity:list_user_projects GET /v3/users/{user_id}/projects

It’s important to note the subtle difference between listing all projects and listing a user’s projects. Listing all projects should be an admin-only operation, and its policy is written as such. Listing all projects a user has access to should not only be restricted to admins, but also to the user that has a role on that project.

1.5 Backends and Services

It’s worth summarizing backends and services into a handy picture. The green portions indicate backends that are usually SQL, the pink portions indicate backends that are usually LDAP or SQL, the blue indicates SQL or Memcache, and finally, policy is serviced from a file. There are other Keystone services; however, these are by far the most commonly used.

Figure 1-6. An overview of the different services and backends Keystone supports

1.6 FAQs

What’s the difference between a Domain and a Region?

These terms are often used interchangeably in the OpenStack world, but are very different concepts. A region is intended to be a geographical representation: an enterprise may have a US-West region and a US-East region. A domain is a logical split between ownership of projects and identity sources.

Can users exist in multiple domains?

In short, no. Each user is owned by a domain. A major point of confusion is that user names may be the same across domains. Meaning there can be a stevemar at the IBM domain and a stevemar at the Acme Inc. domain. Each would have their own unique ID because each stevemar is owned by a different domain, and is considered by Keystone to be a different user.

Why does OpenStack documentation sometimes mention tenants and other times mention projects? Why mention both? Is there a difference?

In the early days of OpenStack, the term tenant was used by OpenStack services to be the entity for grouping and isolating resources. Over time it was decided that project was a more intuitive term for this. Unfortunately, not all of the projects have fully migrated over from tenant to project. Therefore, in some OpenStack services and documentation you may still run into the term tenant.

What is the difference between a scoped and unscoped token?

An unscoped token is one where the user is authenticated but not for a specific project or domain. This type of token is useful for making queries such as determining what projects a user has access to. A scoped token is created when the user is authenticated for a specific project or domain. Scoped tokens have role information associated with them and are the types of tokens used by the other OpenStack services to determine what types of operations are permitted.

I just authenticated and received a token back but the token doesn’t have any roles in it. Is this a bug? Why are there no roles in the token?

If this happens it is because a user has not submitted a scope in their authentication request. As such, the user gets back an unscoped token, which will not contain any roles, since it does not carry any authorization on a project. So until you authenticate and specify a scope (project or domain) you will not see role information in the token.

What about Active Directory support?

It’s there! Keystone’s LDAP support extends to Active Directory. In its earlier releases, there were bugs in the LDAP backend that were related to AD, but since then multiple enterprises have been able to configure Keystone to communicate with their AD.

What are the other authentication methods?

Keystone also provides support for authenticating through a certificate. The only caveat here is that the user name associated with the certificate must exist in an Identity backend.

Get Identity, Authentication, and Access Management in OpenStack now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.