Installing and Configuring the Identity Service Install the Identity service on any server that is accessible to the other servers you intend to use for OpenStack services, as root: # apt-get install keystone python-keystone python-keystoneclient $ yum install openstack-utils openstack-keystone python-keystoneclient $ zypper install openstack-utils openstack-keystone python-keystoneclient After installing, you need to delete the sqlite database it creates, then change the configuration to point to a MySQL database. This configuration enables easier scaling scenarios since you can bring up multiple Keystone front ends when needed, and configure them all to point back to the same database. Plus a database backend has built-in data replication features and documentation surrounding high availability and data redundancy configurations. Delete the keystone.db file created in the /var/lib/keystone directory.# rm /var/lib/keystone/keystone.db Delete the keystone.db file created in the /var/lib/keystone directory.$ sudo rm /var/lib/keystone/keystone.db Configure the production-ready backend data store rather than using the catalog supplied by default for the ability to back up the service and endpoint data. This example shows MySQL. The following sequence of commands will create a MySQL database named "keystone" and a MySQL user named "keystone" with full access to the "keystone" MySQL database. On Fedora, RHEL, CentOS, and openSUSE, you can configure the Keystone database with the openstack-db command.$ sudo openstack-db --init --service keystone To manually create the database, start the mysql command line client by running: $ mysql -u root -p Enter the mysql root user's password when prompted. To configure the MySQL database, create the keystone database. mysql> CREATE DATABASE keystone; Create a MySQL user for the newly-created keystone database that has full control of the keystone database. Note Choose a secure password for the keystone user and replace all references to [YOUR_KEYSTONEDB_PASSWORD] with this password. mysql> GRANT ALL ON keystone.* TO 'keystone'@'%' IDENTIFIED BY '[YOUR_KEYSTONEDB_PASSWORD]'; mysql> GRANT ALL ON keystone.* TO 'keystone'@'localhost' IDENTIFIED BY '[YOUR_KEYSTONEDB_PASSWORD]'; In the above commands, even though the 'keystone'@'%' also matches 'keystone'@'localhost', you must explicitly specify the 'keystone'@'localhost' entry. By default, MySQL will create entries in the user table with User='' and Host='localhost'. The User='' acts as a wildcard, matching all users. If you do not have the 'keystone'@'localhost' account, and you try to log in as the keystone user, the precedence rules of MySQL will match against the User='' Host='localhost' account before it matches against the User='keystone' Host='%' account. This will result in an error message that looks like: ERROR 1045 (28000): Access denied for user 'keystone'@'localhost' (using password: YES) Thus, we create a separate User='keystone' Host='localhost' entry that will match with higher precedence. See the MySQL documentation on connection verification for more details on how MySQL determines which row in the user table it uses when authenticating connections. Enter quit at the mysql> prompt to exit MySQL. mysql> quit Reminder Recall that this document assumes the Cloud Controller node has an IP address of 192.168.206.130. Once Keystone is installed, it is configured via a primary configuration file (/etc/keystone/keystone.conf), a PasteDeploy configuration file (/etc/keystone/keystone-paste.ini) and by initializing data into keystone using the command line client. By default, Keystone's data store is sqlite. To change the data store to mysql, change the line defining connection in /etc/keystone/keystone.conf like so: connection = mysql://keystone:[YOUR_KEYSTONEDB_PASSWORD]@192.168.206.130/keystone Also, ensure that the proper service token is used in the keystone.conf file. An example is provided in the Appendix or you can generate a random string. The sample token is: admin_token = 012345SECRET99TOKEN012345 $ export ADMIN_TOKEN=$(openssl rand -hex 10) $ sudo openstack-config --set /etc/keystone/keystone.conf DEFAULT admin_token $ADMIN_TOKEN By default Keystone will use PKI tokens. To create the signing keys and certificates run: $ sudo keystone-manage pki_setup $ sudo chown -R keystone:keystone /etc/keystone/* /var/log/keystone/keystone.log # keystone-manage pki_setup # chown -R keystone:keystone /etc/keystone/* /var/log/keystone/keystone.log # keystone-manage pki_setup # chown -R keystone:keystone /etc/keystone/* /var/log/keystone/keystone.log In Ubuntu, keystone.conf is shipped as root:root 644, but /etc/keystone has permissions for keystone:keystone 700 so the files under it are protected from unauthorized users. Next, restart the keystone service so that it picks up the new database configuration. # sudo service keystone restart $ sudo service openstack-keystone start && sudo chkconfig openstack-keystone on # systemctl restart openstack-keystone.service # systemctl enable openstack-keystone.service Lastly, initialize the new keystone database, as root: # keystone-manage db_sync
Configuring Services to work with Keystone Once Keystone is installed and running, you set up users and tenants and services to be configured to work with it. You can either follow the manual steps or use a script.
Setting up tenants, users, and roles - manually You need to minimally define a tenant, user, and role to link the tenant and user as the most basic set of details to get other services authenticating and authorizing with the Identity service. Scripted method available These are the manual, unscripted steps using the keystone client. A scripted method is available at Setting up tenants, users, and roles - scripted. Typically, you would use a username and password to authenticate with the Identity service. However, at this point in the install, we have not yet created a user. Instead, we use the service token to authenticate against the Identity service. With the keystone command-line, you can specify the token and the endpoint as arguments, as follows:$ keystone --token 012345SECRET99TOKEN012345 --endpoint http://192.168.206.130:35357/v2.0 <command parameters> You can also specify the token and endpoint as environment variables, so they do not need to be explicitly specified each time. If you are using the bash shell, the following commands will set these variables in your current session so you don't have to pass them to the client each time. Best practice for bootstrapping the first administrative user is to use the OS_SERVICE_ENDPOINT and OS_SERVICE_TOKEN together as environment variables.$ export OS_SERVICE_TOKEN=012345SECRET99TOKEN012345 $ export OS_SERVICE_ENDPOINT=http://192.168.206.130:35357/v2.0 In the remaining examples, we will assume you have set the above environment variables. Because it is more secure to use a username and password to authenticate rather than the service token, when you use the token the keystone client may output the following warning, depending on the version of python-keystoneclient you are running:WARNING: Bypassing authentication using a token & endpoint (authentication credentials are being ignored). First, create a default tenant. We'll name it demo in this example. There is an --enabled parameter available for tenant-create and user-create that defaults to true. Refer to the help in keystone help user-create and keystone help user-update for more details. $ keystone tenant-create --name demo --description "Default Tenant" +-------------+----------------------------------+ | Property | Value | +-------------+----------------------------------+ | description | Default Tenant | | enabled | True | | id | b5815b046cfe47bb891a7b64119e7f80 | | name | demo | +-------------+----------------------------------+ Set the id value from previous command as a shell variable. $ export TENANT_ID=b5815b046cfe47bb891a7b64119e7f80 Create a default user named admin. $ keystone user-create --tenant-id $TENANT_ID --name admin --pass secrete +----------+----------------------------------+ | Property | Value | +----------+----------------------------------+ | email | | | enabled | True | | id | a4c2d43f80a549a19864c89d759bb3fe | | name | admin | | tenantId | b5815b046cfe47bb891a7b64119e7f80 | +----------+----------------------------------+ Set the admin id value from previous command's output as a shell variable. $ export ADMIN_USER_ID=a4c2d43f80a549a19864c89d759bb3fe Create an administrative role based on keystone's default policy.json file, admin. $ keystone role-create --name admin +----------+----------------------------------+ | Property | Value | +----------+----------------------------------+ | id | e3d9d157cc95410ea45d23bbbc2e5c10 | | name | admin | +----------+----------------------------------+ Set the role id value from previous command's output as a shell variable. $ export ROLE_ID=e3d9d157cc95410ea45d23bbbc2e5c10 Grant the admin role to the admin user in the demo tenant with "user-role-add". $ keystone user-role-add --user-id $ADMIN_USER_ID --tenant-id $TENANT_ID --role-id $ROLE_ID Create a service tenant named service. This tenant contains all the services that we make known to the service catalog. $ keystone tenant-create --name service --description "Service Tenant" +-------------+----------------------------------+ | Property | Value | +-------------+----------------------------------+ | description | Service Tenant | | enabled | True | | id | eb7e0c10a99446cfa14c244374549e9d | | name | service | +-------------+----------------------------------+ Set the tenant id value from previous command's output as a shell variable. $ export SERVICE_TENANT_ID=eb7e0c10a99446cfa14c244374549e9d Create a glance service user in the service tenant. You'll do this for any service you add to be in the Identity service catalog. $ keystone user-create --tenant-id $SERVICE_TENANT_ID --name glance --pass glance WARNING: Bypassing authentication using a token & endpoint (authentication credentials are being ignored). +----------+----------------------------------+ | Property | Value | +----------+----------------------------------+ | email | | | enabled | True | | id | 46b2667a7807483d983e0b4037a1623b | | name | glance | | tenantId | eb7e0c10a99446cfa14c244374549e9d | +----------+----------------------------------+ Set the id value from previous command as a shell variable. $ export GLANCE_USER_ID=46b2667a7807483d983e0b4037a1623b Grant the admin role to the glance user in the service tenant. $ keystone user-role-add --user-id $GLANCE_USER_ID --tenant-id $SERVICE_TENANT_ID --role-id $ROLE_ID Create a nova service user in the service tenant. $ keystone user-create --tenant-id $SERVICE_TENANT_ID --name nova --pass nova WARNING: Bypassing authentication using a token & endpoint (authentication credentials are being ignored). +----------+----------------------------------+ | Property | Value | +----------+----------------------------------+ | email | | | enabled | True | | id | 54b3776a8707834d983e0b4037b1345c | | name | nova | | tenantId | eb7e0c10a99446cfa14c244374549e9d | +----------+----------------------------------+ Set the nova user's id value from previous command's output as a shell variable. $ export NOVA_USER_ID=54b3776a8707834d983e0b4037b1345c Grant the admin role to the nova user in the service tenant. $ keystone user-role-add --user-id $NOVA_USER_ID --tenant-id $SERVICE_TENANT_ID --role-id $ROLE_ID Create a cinder service user in the service tenant. $ keystone user-create --tenant-id $SERVICE_TENANT_ID --name cinder --pass openstack WARNING: Bypassing authentication using a token & endpoint (authentication credentials are being ignored). +----------+----------------------------------+ | Property | Value | +----------+----------------------------------+ | email | | | enabled | True | | id | c95bf79153874ac69b4758ebf75498a6 | | name | cinder | | tenantId | eb7e0c10a99446cfa14c244374549e9d | +----------+----------------------------------+ Set the cinder user's id value from previous command's output as a shell variable. $ export CINDER_USER_ID=c95bf79153874ac69b4758ebf75498a6 Grant the admin role to the cinder user in the service tenant. $ keystone user-role-add --user-id $CINDER_USER_ID --tenant-id $SERVICE_TENANT_ID --role-id $ROLE_ID Create an ec2 service user in the service tenant. $ keystone user-create --tenant-id $SERVICE_TENANT_ID --name ec2 --pass ec2 +----------+----------------------------------+ | Property | Value | +----------+----------------------------------+ | email | | | enabled | True | | id | 32e7668b8707834d983e0b4037b1345c | | name | ec2 | | tenantId | eb7e0c10a99446cfa14c244374549e9d | +----------+----------------------------------+ Set the ec2 user's id value from previous command's output as a shell variable. $ export EC2_USER_ID=32e7668b8707834d983e0b4037b1345c Grant the admin role to the ec2 user in the service tenant. $ keystone user-role-add --user-id $EC2_USER_ID --tenant-id $SERVICE_TENANT_ID --role-id $ROLE_ID Create an Object Storage service user in the service tenant. $ keystone user-create --tenant-id $SERVICE_TENANT_ID --name swift --pass swiftpass +----------+----------------------------------+ | Property | Value | +----------+----------------------------------+ | email | | | enabled | True | | id | 4346677b8909823e389f0b4037b1246e | | name | swift | | tenantId | eb7e0c10a99446cfa14c244374549e9d | +----------+----------------------------------+ Set the swift user's id value from previous command's output as a shell variable. $ export SWIFT_USER_ID=4346677b8909823e389f0b4037b1246e Grant the admin role to the swift user in the service tenant. $ keystone user-role-add --user-id $SWIFT_USER_ID --tenant-id $SERVICE_TENANT_ID --role-id $ROLE_ID Next you create definitions for the services.
Defining Services Keystone also acts as a service catalog to let other OpenStack systems know where relevant API endpoints exist for OpenStack Services. The OpenStack Dashboard, in particular, uses the service catalog heavily. This must be configured for the OpenStack Dashboard to properly function. There are two alternative ways of defining services with keystone: Using a template file Using a database backend While using a template file is simpler, it is not recommended except for development environments such as DevStack. The template file does not enable CRUD operations on the service catalog through keystone commands, but you can use the service-list command when using the template catalog. A database backend can provide better reliability, availability, and data redundancy. This section describes how to populate the Keystone service catalog using the database backend. Your /etc/keystone/keystone.conf file should contain the following lines if it is properly configured to use the database backend. [catalog] driver = keystone.catalog.backends.sql.Catalog
Elements of a Keystone service catalog entry For each service in the catalog, you must perform two keystone operations: Use the keystone service-create command to create a database entry for the service, with the following attributes: --name Name of the service (e.g., nova, ec2, glance, keystone) --type Type of service (e.g., compute, ec2, image, identity) --description A description of the service, (e.g., "Nova Compute Service") Use the keystone endpoint-create command to create a database entry that describes how different types of clients can connect to the service, with the following attributes: --region the region name you've given to the OpenStack cloud you are deploying (e.g., RegionOne) --service-id The ID field returned by the keystone service-create (e.g., 935fd37b6fa74b2f9fba6d907fa95825) --publicurl The URL of the public-facing endpoint for the service (e.g., http://192.168.206.130:9292 or http://192.168.206.130:8774/v2/%(tenant_id)s) --internalurl The URL of an internal-facing endpoint for the service. This typically has the same value as publicurl. --adminurl The URL for the admin endpoint for the service. The Keystone and EC2 services use different endpoints for adminurl and publicurl, but for other services these endpoints will be the same. Keystone allows some URLs to contain special variables, which are automatically substituted with the correct value at runtime. Some examples in this document employ the tenant_id variable, which we use when specifying the Volume and Compute service endpoints. Variables can be specified using either %(varname)s or $(varname)s notation. In this document, we always use the %(varname)s notation (e.g., %(tenant_id)s) since $ is interpreted as a special character by Unix shells.
Creating keystone services and service endpoints Here we define the services and their endpoints. Recall that you must have the following environment variables set.$ export OS_SERVICE_TOKEN=012345SECRET99TOKEN012345 $ export OS_SERVICE_ENDPOINT=http://192.168.206.130:35357/v2.0 Define the Identity service: $ keystone service-create --name=keystone --type=identity --description="Identity Service" +-------------+----------------------------------+ | Property | Value | +-------------+----------------------------------+ | description | Identity Service | | id | 15c11a23667e427e91bc31335b45f4bd | | name | keystone | | type | identity | +-------------+----------------------------------+ $ keystone endpoint-create \ --region RegionOne \ --service-id=15c11a23667e427e91bc31335b45f4bd \ --publicurl=http://192.168.206.130:5000/v2.0 \ --internalurl=http://192.168.206.130:5000/v2.0 \ --adminurl=http://192.168.206.130:35357/v2.0 +-------------+-----------------------------------+ | Property | Value | +-------------+-----------------------------------+ | adminurl | http://192.168.206.130:35357/v2.0 | | id | 11f9c625a3b94a3f8e66bf4e5de2679f | | internalurl | http://192.168.206.130:5000/v2.0 | | publicurl | http://192.168.206.130:5000/v2.0 | | region | RegionOne | | service_id | 15c11a23667e427e91bc31335b45f4bd | +-------------+-----------------------------------+ Define the Compute service, which requires a separate endpoint for each tenant. Here we use the service tenant from the previous section. The %(tenant_id)s and single quotes around the publicurl, internalurl, and adminurl must be typed exactly as shown for both the Compute endpoint and the Volume endpoint. $ keystone service-create --name=nova --type=compute --description="Compute Service" +-------------+----------------------------------+ | Property | Value | +-------------+----------------------------------+ | description | Compute Service | | id | abc0f03c02904c24abdcc3b7910e2eed | | name | nova | | type | compute | +-------------+----------------------------------+ $ keystone endpoint-create \ --region RegionOne \ --service-id=abc0f03c02904c24abdcc3b7910e2eed \ --publicurl='http://192.168.206.130:8774/v2/%(tenant_id)s' \ --internalurl='http://192.168.206.130:8774/v2/%(tenant_id)s' \ --adminurl='http://192.168.206.130:8774/v2/%(tenant_id)s' +-------------+----------------------------------------------+ | Property | Value | +-------------+----------------------------------------------+ | adminurl | http://192.168.206.130:8774/v2/%(tenant_id)s | | id | 935fd37b6fa74b2f9fba6d907fa95825 | | internalurl | http://192.168.206.130:8774/v2/%(tenant_id)s | | publicurl | http://192.168.206.130:8774/v2/%(tenant_id)s | | region | RegionOne | | service_id | abc0f03c02904c24abdcc3b7910e2eed | +-------------+----------------------------------------------+ Define the Volume service, which also requires a separate endpoint for each tenant. $ keystone service-create --name=cinder --type=volume --description="Volume Service" +-------------+----------------------------------+ | Property | Value | +-------------+----------------------------------+ | description | Volume Service | | id | 1ff4ece13c3e48d8a6461faebd9cd38f | | name | volume | | type | volume | +-------------+----------------------------------+ $ keystone endpoint-create \ --region RegionOne \ --service-id=1ff4ece13c3e48d8a6461faebd9cd38f \ --publicurl='http://192.168.206.130:8776/v1/%(tenant_id)s' \ --internalurl='http://192.168.206.130:8776/v1/%(tenant_id)s' \ --adminurl='http://192.168.206.130:8776/v1/%(tenant_id)s' +-------------+----------------------------------------------+ | Property | Value | +-------------+----------------------------------------------+ | adminurl | http://192.168.206.130:8776/v1/%(tenant_id)s | | id | 1ff4ece13c3e48d8a6461faebd9cd38f | | internalurl | http://192.168.206.130:8776/v1/%(tenant_id)s | | publicurl | http://192.168.206.130:8776/v1/%(tenant_id)s | | region | RegionOne | | service_id | 8a70cd235c7d4a05b43b2dffb9942cc0 | +-------------+----------------------------------------------+ Define the Image service: $ keystone service-create --name=glance --type=image --description="Image Service" +-------------+----------------------------------+ | Property | Value | +-------------+----------------------------------+ | description | Image Service | | id | 7d5258c490144c8c92505267785327c1 | | name | glance | | type | image | +-------------+----------------------------------+ $ keystone endpoint-create \ --region RegionOne \ --service-id=7d5258c490144c8c92505267785327c1 \ --publicurl=http://192.168.206.130:9292 \ --internalurl=http://192.168.206.130:9292 \ --adminurl=http://192.168.206.130:9292 +-------------+-----------------------------------+ | Property | Value | +-------------+-----------------------------------+ | adminurl | http://192.168.206.130:9292 | | id | 3c8c0d749f21490b90163bfaed9befe7 | | internalurl | http://192.168.206.130:9292 | | publicurl | http://192.168.206.130:9292 | | region | RegionOne | | service_id | 7d5258c490144c8c92505267785327c1 | +-------------+-----------------------------------+ Define the EC2 compatibility service: $ keystone service-create --name=ec2 --type=ec2 --description="EC2 Compatibility Layer" +-------------+----------------------------------+ | Property | Value | +-------------+----------------------------------+ | description | EC2 Compatibility Layer | | id | 181cdad1d1264387bcc411e1c6a6a5fd | | name | ec2 | | type | ec2 | +-------------+----------------------------------+ $ keystone endpoint-create \ --region RegionOne \ --service-id=181cdad1d1264387bcc411e1c6a6a5fd \ --publicurl=http://192.168.206.130:8773/services/Cloud \ --internalurl=http://192.168.206.130:8773/services/Cloud \ --adminurl=http://192.168.206.130:8773/services/Admin +-------------+--------------------------------------------+ | Property | Value | +-------------+--------------------------------------------+ | adminurl | http://192.168.206.130:8773/services/Admin | | id | d2a3d7490c61442f9b2c8c8a2083c4b6 | | internalurl | http://192.168.206.130:8773/services/Cloud | | publicurl | http://192.168.206.130:8773/services/Cloud | | region | RegionOne | | service_id | 181cdad1d1264387bcc411e1c6a6a5fd | +-------------+--------------------------------------------+ Define the Object Storage service: $ keystone service-create --name=swift --type=object-store --description="Object Storage Service" +-------------+---------------------------------+ | Property | Value | +-------------+----------------------------------+ | description | Object Storage Service | | id | 272efad2d1234376cbb911c1e5a5a6ed | | name | swift | | type | object-store | +-------------+----------------------------------+ $ keystone endpoint-create \ --region RegionOne \ --service-id=272efad2d1234376cbb911c1e5a5a6ed \ --publicurl 'http://192.168.206.130:8888/v1/AUTH_%(tenant_id)s' \ --internalurl 'http://192.168.206.130:8888/v1/AUTH_%(tenant_id)s' \ --adminurl 'http://192.168.206.130:8888/v1' +-------------+---------------------------------------------------+ | Property | Value | +-------------+---------------------------------------------------+ | adminurl | http://192.168.206.130:8888/v1 | | id | e32b3c4780e51332f9c128a8c208a5a4 | | internalurl | http://192.168.206.130:8888/v1/AUTH_%(tenant_id)s | | publicurl | http://192.168.206.130:8888/v1/AUTH_%(tenant_id)s | | region | RegionOne | | service_id | 272efad2d1234376cbb911c1e5a5a6ed | +-------------+---------------------------------------------------+
Setting up Tenants, Users, Roles, and Services - Scripted The Keystone project offers a bash script for populating tenants, users, roles and services at http://git.openstack.org/cgit/openstack/keystone/plain/tools/sample_data.sh with sample data. This script uses 127.0.0.1 for all endpoint IP addresses. This script also defines services for you.