Keystone is the OpenStack identity service, and is the most foundational Python-based component of OpenStack (that is, ignoring RabbitMQ and any SQL databases you might need). There is a server and client part of Keystone. Typically, Keystone is installed on a server, and the client can be installed anywhere (including the server) and is used to interact with Keystone using the OpenStack Identity API, which uses Web-based protocols as a means of client-server communication. The various components of OpenStack can be configured to connect to Keystone using service users so that they in turn can authenticate and authorize requests.
This section describes the various concepts and definitions that are part of Keystone.
- In Keystone, "tenants" represent logical groups of users to which resources are assigned. Virtual machines (Nova) and containers (Swift) are assigned to tenants, not to users directly. Keystone users can be part of more than one tenant, and can have different types of roles defined for each tenant that they're a part of. Think of tenants as a logical way to organize computing and storage resources without assigning them to user accounts directly. Keystone allows you to create and delete tenants, and also enable and disable them.
- A role is a common security concept, where a user is assigned a certain set of privileges. This set of privileges is called a role, has a name, and can be managed independently of the specific user account(s) that are part of the role. Keystone allows you to create and delete roles, add a user to a role for a specific tenant, remove a user from a role for a specific tenant, and of course list all the roles that have been defined.
- Keystone is used to define users. Users are accounts for specific individuals, and typically have a password and email associated with them. Keystone allows you to list, create, delete, enable/disable, update email addresses, and change passwords of Users.
- Service Users
- A service User is a user account created specifically for a component of OpenStack. Service users are typically added to the services tenant with the Admin role. For example, for Nova, you would create a service User nova. Then you would configure Nova to use this Service User to connect to Keystone so that it can authenticate and authorize requests that it receives. See OpenStack Documentation on Configuring Services for more information.
- Keystone allows you to define services, which are logical names for parts of OpenStack that provide internal or external capabilities, for things such as identity services, as well as compute and storage services.
- Service Endpoints
- These are URLs that define where particular services can be accessed. Various parts of OpenStack will query Keystone for service endpoints that they require. Service endpoints can be created and deleted, and you can "get" a handle (URL) to a service that has been defined. You can also define region-specific service endpoints, so that different regions will be serviced differently.
- Service Catalog
- Taken as a whole, all the service endpoints defined in Keystone are the service catalog, defining all services available to OpenStack.
In Funtoo Linux, Keystone can be merged by typing:
# emerge sys-auth/keystone
Emerging Keystone will also pull in sys-auth/keystone-client as a runtime dependency. keystone-client (which provides the keystone executable) is now maintained in a separate GitHub repository, and connects to Keystone using the OpenStack identity API. Once setting up /etc/keystone/keystone.conf and starting the Keystone service, you will use the keystone command to define tenants, users, roles, services and service endpoints.
The configuration file for the Keystone service is located at /etc/keystone/keystone.conf. In this section, we will review important configuration file lines, some of which you will need to modify.
- This is the TCP port that non-administrators should access, and defaults to 5000. A number of Keystone commands will be disabled by default on this port, including those related to roles, services and endpoints.
- This is the TCP port that administrators will connect to perform regular (identical to public port) as well as administration tasks. All functionality is enabled on this port, and you can access this port without a user, by using the admin token.
- This setting is a literal string that serves as the master password when connecting to the administration port.
- This is an SQLAlchemy connection string specifying what back-end SQL database to use for the Keystone database. A reasonable initial default is sqlite:////etc/keystone/keystone.db.
Initial Server Configuration
Here are the steps you can use to get the Keystone service up and running:
- Copy /etc/keystone/keystone.conf.sample to /etc/keystone/keystone.conf.
- Change the config line connection = to read sqlite:////etc/keystone/keystone.db (four slashes after the colon)
- If desired, change the admin_token so that it is difficult to guess (especially important for production deployments). The examples below will use the default of 'ADMIN'.
- Type rc-update add keystone default to add Keystone to the default runlevel, if desired.
- Type /etc/init.d/keystone start to start the Keystone service so that you can perform further configuration.
Using SQLite as the database back-end like this is not a great idea for production deployment, but for learning about Keystone it works just fine.
Now, initialize the Keystone database:
# keystone-manage db_sync
The command above will initialize all necessary tables so that they are ready to store data.
To perform further configuration of the Keystone service, as well as to query Keystone, we will need to connect to the Keystone service using the keystone client, called keystone. Initially, you won't have any users, tenants, roles, or anything else set up, and this creates a chicken-and-egg authentication problem. How do you authenticate with Keystone before you have your own user account?
We get around this problem by having the admin_token = ADMIN (or other string you specified) setting in /etc/keystone/keystone.conf configuration file. This defines a special administration token that is the literal string 'ADMIN', which can be used like a master password to get full remote control of Keystone so that you can configure it, when you are connecting to the admin port. As long as you know the admin_token, you will be able to administrate Keystone from any system that can connect to Keystone's admin port (which defaults to 35357).
It is not a good idea to have an admin_token defined on a production Keystone installation. Use it for initial setup, and then disable it, and restart Keystone. Then use a user in the 'admin' role for administration via the admin port.
Let's see how this works in practice. First, we will want to define these environment variables in our shell:
$ export SERVICE_ENDPOINT=http://127.0.0.1:35357/v2.0/ $ export SERVICE_TOKEN=ADMIN
Above, we are authenticating against the admin port (35357) using the admin token we defined in /etc/keystone/keystone.conf. This grants us full access to the Keystone API so we can perform initial configuration. Let's run a sample command:
$ keystone tenant-list +----+------+---------+ | id | name | enabled | +----+------+---------+ +----+------+---------+
Above, we ran the keystone tenant-list command, at which point our client used both environment variables to connect to the Keystone service, query for all tenants, and successfully returned an empty list, because we haven't created any tenants yet. If you see this output, then keystone used SERVICE_ENDPOINT and SERVICE_TOKEN environment variables to connect and successfully query Keystone for tenants. This means that Keystone is working properly and ready to be configured further.
Note: To debug authentication issues, type export KEYSTONECLIENT_DEBUG=1 and retry your attempt.
BETA user creation steps:
$ keystone role-create --name admin $ keystone tenant-create --name admin $ keystone user-create --name admin --pass 'mySekr1t' --email 'firstname.lastname@example.org' --tenant_id admin $ keystone user-role-add --user 0c4a78317f234333a9a1116be1c7b022 --role 805d60f51e03478bbc2cf79ef2d42135 --tenant_id f988b76e5fe546f1a18c08c4d26bcb89
I need to expand on the above commands, but basically what we are doing is creating a role named admin, a tenant named admin, a user named admin (with a password), and then we are adding the admin user to the admin role for the admin tenant. The last command references the user, role and tenant by ID rather than name. This is one of the tricky aspects of the Keystone API -- sometimes you will need to use numeric IDs rather than logical names for some API commands. You can grab the proper ID by issuing user-list, tenant-list, or role-list keystone commands.
Once you have a user named admin created, here is how you will use keystone to connect to the Keystone service. First, we will want to define these environment variables, and it's a good idea to put these in ~/.bashrc or ~/.bash_profile:
SERVICE_ENDPOINT and SERVICE_TOKEN must be unset in order to force the client to use user-based authentication. Otherwise it will assume that you are attempting to perform token-based authentication.
$ unset SERVICE_ENDPOINT $ unset SERVICE_TOKEN $ export OS_AUTH_URL=http://127.0.0.1:35357/v2.0/
If you specify port 5000 instead of 35357 in the OS_AUTH_URL above, you will be connecting to the public port, and some administration functions will be unavailable. Using port 35357 will allow you to access the full functionality of the API.
Note that we no longer need to define SERVICE_TOKEN, because we're not using it anymore. Now, here's how we run a Keystone-related query:
$ keystone --os_username='admin' --os_password 'mySekr1t' user-list +----------------------------------+---------+---------------------+-------+ | id | enabled | email | name | +----------------------------------+---------+---------------------+-------+ | 0c4a78317f234333a9a1116be1c7b022 | True | email@example.com | admin | +----------------------------------+---------+---------------------+-------+
If you get tired of specifying the two extra command-line arguments above, you can export the environment variables OS_USERNAME and OS_PASSWORD and Keystone will use them if defined. Note that it is not a good idea to store your plain-text password in any file.
Also note that when calling keystone, specify --os_username and --os_password first, before the command you are calling, such as service-create. Then, after service-create, you would specify any options related to service creation, such as --region.
The service catalog is an important concept for Keystone and OpenStack, because this is where you knit all of the various parts of your OpenStack deployment into a coherent whole that works together. So we are going to explore service catalog configuration in detail. There are two ways to set up a service catalog. One is to use a plain-text configuration file, and the other is to store your service catalog in a SQL back-end by using keystone service-create commands. The latter is recommended, but we will cover both approaches:
In older versions of OpenStack, the service catalog was defined using a plain-text catalog file. This method is still supported by OpenStack, but I think it's a bit confusing and using the SQL method documented in the next section is recommended. However, I am including documentation on the plain-text catalog because it shows up in a lot of OpenStack documentation so it's helpful to be familiar with how it works.
To enable the plain-text catalog, you would add the following settings to /etc/keystone/keystone.conf:
[catalog] driver = keystone.catalog.backends.templated.TemplatedCatalog template_file = /etc/keystone/service_catalog
You would then define a plain-text catalog at /etc/keystone/service_catalog. An example service catalog is installed at /usr/share/doc/keystone-9999/etc/default_catalog.templates.bz2
Once this is enabled in your configuration, and keystone is restarted, then the service catalog will be defined in Keystone. At this point, it will not be possible to define any services using the SQL method, via keystone service-create.
The SQL-based service catalog does not require any additional configuration besides ensuring that a SQL backend is configured for Keystone, which is a typical part of the install process.
To create a service endpoint, you would first define the service, using a command like this:
$ keystone service-create --name=nova --type=compute --description="Nova Compute Service" +-------------+----------------------------------+ | Property | Value | +-------------+----------------------------------+ | description | Nova Compute Service | | id | c3600f9e26be495f9b0ed1328c33a436 | | name | nova | | type | compute | +-------------+----------------------------------+
Now that the service is defined, we can define an endpoint for this service, for region RegionOne:
$ keystone endpoint-create --region RegionOne --service_id c3600f9e26be495f9b0ed1328c33a436 \ --publicurl 'http://127.0.0.1:$(compute_port)s/v1.1/$(tenant_id)s' \ --adminurl 'http://127.0.0.1:$(compute_port)s/v1.1/$(tenant_id)s' \ --internalurl 'http://127.0.0.1:$(compute_port)s/v1.1/$(tenant_id)s'
OpenStack Identity Service: