date | draft | weight | title |
---|---|---|---|
2016-05-09 |
false |
4 |
Lab 04 - Keystone |
Mon | Mon | Mon | Mon | Tue | Tue | Tue | Tue | Wed | Wed | Wed | Thur | Thur | Thur | Thur |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
00 | 01 | 02 | 03 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 | 13 | 14 |
The objective of this lab is to further your understanding of OpenStack Identity service (Keystone). Having appropriate credentials is required if you wish to use any CLI tools to query on the OpenStack services.
To use an OpenStack cloud, you need to authenticate against the Identity service Keystone (which returns a Token and the Service Catalog). To request an authentication token, you must supply a payload of credentials in the authentication request. Credentials are usually a combination of your user name and password, and optionally, the name or ID of the tenant in which your cloud runs. When you send API requests, you include the token in an HTTP header called the "X-Auth-Token" header.
If you access multiple OpenStack services, you must get a token for each service. A token is valid for a limited time before it expires. A token can also become invalid for other reasons. For example, if the roles for a user change, existing tokens for that user are invalid. Credentials allow OpenStack services to determine where your service endpoints and your authentication information are located.
-
SSH to your controller as root
-
Once logged into the controller, type the following command (it won't work!):
[root@controller ~]#
nova flavor-list
ERROR (CommandError): You must provide a username or user id via --os-username, --os-user-id, env[OS_USERNAME] or env[OS_USER_ID]
This command results in an error because Nova doesn't know who you are.
- Q1: When you issued the nova flavor-list command at the CLI, did you identify yourself?
- A1: No. We did not identify ourselves to any OpenStack service at the CLI. The root user (root@controller) is a user within the Ubuntu OS, and has nothing to do with OpenStack users, projects, or permissions.
- Q2: When you issue commands through Horizon, do you first need to identify yourself?
- A2: Yes. Before you can do anything in Horizon, you must first login as a user (admin, aliceanderson, bobbarker, etc.), that identity is cached for the remainder of the session (until you log out of the dashboard). Therefore, if we plan to issue commands at the CLI, we'll need to learn how to pass permissions at the CLI.
- Q1: When you issued the nova flavor-list command at the CLI, did you identify yourself?
-
Let's try another command that won't work!
[root@controller ~]#
keystone tenant-list
Another error!? That's alright... Keystone doesn't know who you are. Do you have permissions to view the current tenants?
-
We focusing on the permissions required to issue a command successfully without an error. We only chose flavor-list as a example.
[root@controller ~]#
nova --os-auth-url=http://192.168.0.10:5000/v2.0 --os-tenant-name=admin --os-user-name=admin --os-password=alta3 flavor-list
+----+----------------+-----------+------+-----------+------+-------+-------------+-----------+ | ID | Name | Memory_MB | Disk | Ephemeral | Swap | VCPUs | RXTX_Factor | Is_Public | +----+----------------+-----------+------+-----------+------+-------+-------------+-----------+ | 1 | m1.tiny | 512 | 1 | 0 | | 1 | 1.0 | True | | 2 | m1.small | 2048 | 20 | 0 | | 1 | 1.0 | True | | 3 | m1.medium | 4096 | 40 | 0 | | 2 | 1.0 | True | | 4 | m1.large | 8192 | 80 | 0 | | 4 | 1.0 | True | | 5 | m1.xlarge | 16384 | 160 | 0 | | 8 | 1.0 | True | +----+----------------+-----------+------+-----------+------+-------+-------------+-----------+
Now the flavors are displayed. This is because you issued a command that included values of variables that disclose your permissions (os-tenant-name, os-user-name, os-password, os-auth-url). Nova can use this information to make an API call to the Keystone service and determine if you (admin) have sufficient permissions to execute the command (flavor-list) ID: Unique ID (integer or UUID) for the flavor.
Name: A descriptive name, such as xx.size_name, is conventional but not required, though some third-party tools may rely on it.
Memory_MB: Virtual machine memory in megabytes.
Disk: Virtual root disk size in gigabytes. This is an ephemeral disk the base image is copied into. You don't use it when you boot from a persistent volume. The "0" size is a special case that uses the native base image size as the size of the ephemeral root volume.
Ephemeral: Specifies the size of a secondary ephemeral data disk. This is an empty, unformatted disk and exists only for the life of the instance.
Swap: Optional swap space allocation for the instance.
VCPUs: Number of virtual CPUs presented to the instance.
RXTX_Factor: Optional property that allows created servers to have a different bandwidth cap from that defined in the network they are attached to. This factor is multiplied by the rxtx_base property of the network. Default value is 1.0 (that is, the same as the attached network).
Is_Public: Boolean value that indicates whether the flavor is available to all users or private. Private flavors do not get the current tenant assigned to them. Defaults to True.
extra_specs: Additional optional restrictions on which compute nodes the flavor can run on. This is implemented as key-value pairs that must match against the corresponding key-value pairs on compute nodes. Can be used to implement things like special resources (such as flavors that can run only on compute nodes with GPU hardware). -
So it worked, but we had to include a long list of credentials. If you'd like, trying using just Nova flavor-list again (without the --flags).
[root@controller ~]#
nova flavor-list
Once again, it didn't work. Clearly the credentials are required every time you issue commands to manipulate your OpenStack cloud.
-
Use the nova help commands to better understand the credentials:
"nova -h" will display help for the nova command "grep" means "display only these lines that contain the following search string" Therefore, "nova -h | grep os-auth-url" means display help, and only display the lines that contain os-auth-url
[root@controller ~]#
nova -h
[root@controller ~]#
nova -h | grep os-auth-url
[root@controller ~]#
nova -h | grep os-tenant-name
[root@controller ~]#
nova -h | grep os-user-name
[root@controller ~]#
nova -h | grep os-password
The purpose of issuing these commands is so that you know what the flags are that you are setting
-
Let's go a step further and issue the same command, but this time include a debug flag and see if we can deep dive into what is going on!
[root@controller ~]#
nova --os-auth-url=http://192.168.0.10:5000/v2.0 --os-tenant-name=admin --os-user-name=admin --os-password=alta3 --debug flavor-list
Debug attempts to display the processes that are going on in the background to make this possible. We'll spend some more time checking out some of the returned information in the next lab, for now, we just wanted you to be aware that it was possible.
DEBUG (v2:76) Making authentication request to http://192.168.0.10:5000/v2.0/tokens | INFO (connectionpool:238) Resetting dropped connection: 192.168.0.10 | DEBUG (connectionpool:383) "POST /v2.0/tokens HTTP/1.1" 200 3974 | DEBUG (iso8601:184) Parsed 2015-10-21T04:27:26Z into {'tz_sign': None, 'second_fraction': None, 'hour': u'04', 'daydash': u'21', 'tz_hour': None, 'month': Non| e, 'timezone': u'Z', 'second': u'26', 'tz_minute': None, 'year': u'2015', 'separator': u'T', 'monthdash': u'10', 'day': None, 'minute': u'27'} with default ti| mezone <iso8601.iso8601.Utc object at 0x22229d0> | DEBUG (iso8601:140) Got u'2015' for 'year' with default None | DEBUG (iso8601:140) Got u'10' for 'monthdash' with default 1 | DEBUG (iso8601:140) Got 10 for 'month' with default 10 | DEBUG (iso8601:140) Got u'21' for 'daydash' with default 1 | DEBUG (iso8601:140) Got 21 for 'day' with default 21 | DEBUG (iso8601:140) Got u'04' for 'hour' with default None | DEBUG (iso8601:140) Got u'27' for 'minute' with default None | DEBUG (iso8601:140) Got u'26' for 'second' with default None | DEBUG (session:195) REQ: curl -g -i -X GET http://192.168.0.10:8774/v2/300b2cc45c3846939e589310ae714e46/flavors/detail -H "User-Agent: python-novaclient" -H "| Accept: application/json" -H "X-Auth-Token: {SHA1}914b01c69b7491be6cd35d89a3f7c55e90603dfe" | INFO (connectionpool:203) Starting new HTTP connection (1): 192.168.0.10 | DEBUG (connectionpool:383) "GET /v2/300b2cc45c3846939e589310ae714e46/flavors/detail HTTP/1.1" 200 2089 | DEBUG (session:224) RESP: [200] date: Wed, 21 Oct 2015 03:27:27 GMT connection: keep-alive content-type: application/json content-length: 2089 x-compute-reque| st-id: req-980927ce-3964-441f-bb9a-58437a05b130 | RESP BODY: {"flavors": [{"name": "m1.tiny", "links": [{"href": "http://192.168.0.10:8774/v2/300b2cc45c3846939e589310ae714e46/flavors/1", "rel": "self"}, {"hre| f": "http://192.168.0.10:8774/300b2cc45c3846939e589310ae714e46/flavors/1", "rel": "bookmark"}], "ram": 512, "OS-FLV-DISABLED:disabled": false, "vcpus": 1, "sw| ap": "", "os-flavor-access:is_public": true, "rxtx_factor": 1.0, "OS-FLV-EXT-DATA:ephemeral": 0, "disk": 1, "id": "1"}, {"name": "m1.small", "links": [{"href"| : "http://192.168.0.10:8774/v2/300b2cc45c3846939e589310ae714e46/flavors/2", "rel": "self"}, {"href": "http://192.168.0.10:8774/300b2cc45c3846939e589310ae714e4| 6/flavors/2", "rel": "bookmark"}], "ram": 2048, "OS-FLV-DISABLED:disabled": false, "vcpus": 1, "swap": "", "os-flavor-access:is_public": true, "rxtx_factor": | 1.0, "OS-FLV-EXT-DATA:ephemeral": 0, "disk": 20, "id": "2"}, {"name": "m1.medium", "links": [{"href": "http://192.168.0.10:8774/v2/300b2cc45c3846939e589310ae7| 14e46/flavors/3", "rel": "self"}, {"href": "http://192.168.0.10:8774/300b2cc45c3846939e589310ae714e46/flavors/3", "rel": "bookmark"}], "ram": 4096, "OS-FLV-DI| SABLED:disabled": false, "vcpus": 2, "swap": "", "os-flavor-access:is_public": true, "rxtx_factor": 1.0, "OS-FLV-EXT-DATA:ephemeral": 0, "disk": 40, "id": "3"| }, {"name": "m1.large", "links": [{"href": "http://192.168.0.10:8774/v2/300b2cc45c3846939e589310ae714e46/flavors/4", "rel": "self"}, {"href": "http://192.168.| 0.10:8774/300b2cc45c3846939e589310ae714e46/flavors/4", "rel": "bookmark"}], "ram": 8192, "OS-FLV-DISABLED:disabled": false, "vcpus": 4, "swap": "", "os-flavor| -access:is_public": true, "rxtx_factor": 1.0, "OS-FLV-EXT-DATA:ephemeral": 0, "disk": 80, "id": "4"}, {"name": "m1.xlarge", "links": [{"href": "http://192.168| .0.10:8774/v2/300b2cc45c3846939e589310ae714e46/flavors/5", "rel": "self"}, {"href": "http://192.168.0.10:8774/300b2cc45c3846939e589310ae714e46/flavors/5", "re| l": "bookmark"}], "ram": 16384, "OS-FLV-DISABLED:disabled": false, "vcpus": 8, "swap": "", "os-flavor-access:is_public": true, "rxtx_factor": 1.0, "OS-FLV-EXT| -DATA:ephemeral": 0, "disk": 160, "id": "5"}]} | +----+-----------+-----------+------+-----------+------+-------+-------------+-----------+ | ID | Name | Memory_MB | Disk | Ephemeral | Swap | VCPUs | RXTX_Factor | Is_Public | +----+-----------+-----------+------+-----------+------+-------+-------------+-----------+ | 1 | m1.tiny | 512 | 1 | 0 | | 1 | 1.0 | True | | 2 | m1.small | 2048 | 20 | 0 | | 1 | 1.0 | True | | 3 | m1.medium | 4096 | 40 | 0 | | 2 | 1.0 | True | | 4 | m1.large | 8192 | 80 | 0 | | 4 | 1.0 | True | | 5 | m1.xlarge | 16384 | 160 | 0 | | 8 | 1.0 | True | +----+-----------+-----------+------+-----------+------+-------+-------------+-----------+
So what we've all figured out by this point, is that setting flag on every CLI command involves far too much typing. Let's make our commands easier to issue by setting some environmental variables for our current bash session. NOTE: If environmental vs shell variables, and parent vs child sessions are new terms for you, that is OK. There is a small section at the conclusion of this lab that will make it more clear.
-
Display the contents of the
keystonerc_admin
file[root@controller ~]#
cat keystonerc_admin
Comments have been added to the output, your output will lack the comments (lines that begin with #).
# This is the user name export OS_USERNAME=admin # This is the tenant, or project export OS_TENANT_NAME=admin # Password for the above user export OS_PASSWORD=alta3 # The Identity API served through Keystone export OS_AUTH_URL=http://192.168.0.10:5000/v2.0/ # The OpenStack Region export OS_REGION_NAME=RegionOne # Appends the CLI prompt with keystone_admin export PS1='[\u@\h \W(keystone_admin)]\$ '
The export commands within this file will mark each VAR for automatic export to the environment of subsequently executed commands (i.e. make the local shell variable VAR global). Essentially, we can set all of our permissions in this file, source this file, and then not have to ever type our permissions again as they'll always be available to the bash environment.
NOTE: The name of this file may change slightly depending on your environment. RDO deployments use the formatting structure keystonerc_$USER
For more info on regions: http://docs.openstack.org/openstack-ops/content/scaling.html#segregate_cloud
-
Display a list of the environmental variables currently set
[root@controller ~]#
printenv | sort
Look over the displayed entries. Do you see any mention of the aforementioned credentials, such as
OS_TENANT_NAME
orOS_USERNAME
? (Feel free to use grep if you'd like.)XDG_SESSION_ID=16 HOSTNAME=controller.localdomain SELINUX_ROLE_REQUESTED= TERM=screen SHELL=/bin/bash HISTSIZE=1000 SSH_CLIENT=71.251.147.235 52298 22 SELINUX_USE_CURRENT_RANGE= SSH_TTY=/dev/pts/0 USER=root LS_COLORS=rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:mi=01;05;37;41:su=37;41:sg=3 ;43:ca=30;41:tw=30;42:ow=34 ;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arc=01;31:*.arj=01;31:*.taz=01;31:*.lha=01;31:*.lz4=01;31:*.lzh=01;31:*.lzma=01;31:*.tlz=01;31:*.txz=01;31:*.t zo=01;31:*.t7z=01;31:*.zip=01;31:*.z=01;31:*.Z=01;31:*.dz=01;31:*.gz=01;31:*.lrz=01;31:*.lz=01;31:*.lzo=01;31:*.xz=01;31:*.bz2=01;31:*.bz=01;31:*.tbz=01;31:*. tbz2=01;31:*.tz=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.war=01;31:*.ear=01;31:*.sar=01;31:*.rar=01;31:*.alz=01;31:*.ace=01;31:*.zoo=01;31:*.cpio=01;31:*.7 z=01;31:*.rz=01;31:*.cab=01;31:*.jpg=01;35:*.jpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif= 01;35:*.tiff=01;35:*.png=01;35:*.svg=01;35:*.svgz=01;35:*.mng=01;35:*.pcx=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.m2v=01;35:*.mkv=01;35:*.webm=01;35:*.og m=01;35:*.mp4=01;35:*.m4v=01;35:*.mp4v=01;35:*.vob=01;35:*.qt=01;35:*.nuv=01;35:*.wmv=01;35:*.asf=01;35:*.rm=01;35:*.rmvb=01;35:*.flc=01;35:*.avi=01;35:*.fli= 01;35:*.flv=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.yuv=01;35:*.cgm=01;35:*.emf=01;35:*.axv=01;35:*.anx=01;35:*.ogv=01;35:*.ogx=01;35:*.aac=01;3 6:*.au=01;36:*.flac=01;36:*.mid=01;36:*.midi=01;36:*.mka=01;36:*.mp3=01;36:*.mpc=01;36:*.ogg=01;36:*.ra=01;36:*.wav=01;36:*.axa=01;36:*.oga=01;36:*.spx=01;36: *.xspf=01;36: MAIL=/var/spool/mail/root PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin PWD=/root LANG=en_US.UTF-8 SELINUX_LEVEL_REQUESTED= HISTCONTROL=ignoredups SHLVL=1 HOME=/root LOGNAME=root SSH_CONNECTION=71.251.147.235 52298 192.168.0.10 22 LESSOPEN=||/usr/bin/lesspipe.sh %s XDG_RUNTIME_DIR=/run/user/0 _=/usr/bin/printenv
-
Set the environmental variables found in keystonerc_admin
[root@controller ~]#
source keystonerc_admin
This is a bash shell built-in command that executes the content of the file passed as a argument in the current shell. It is synonymous with ' . ' (period). After executing the above command, the CLI line will change. This is just a reminder that you are now passing commands to the OpenStack services as some user (in this case admin).
Notice that your CLI prompt has changed to indicate that you are now 'sourced' with admin permissions
[root@controller ~(keystone_admin)]#
-
Once again, display a list of the environmental variables currently set.
[root@controller ~(keystone_admin)]#
printenv
Look over the displayed entries. Now you will see a listing for the variables contained within
keystonerc_admin
, such asOS_TENANT_NAME
andOS_USERNAME
. Just for your understanding, these entries are only set for this current bash session. If you type exit, then reconnect as root, these variables will unset themselves. If you want to remove them manually, use theunset
command. For fun, try runningprintenv | grep OS_
XDG_SESSION_ID=16 HOSTNAME=controller.localdomain SELINUX_ROLE_REQUESTED= TERM=screen SHELL=/bin/bash HISTSIZE=1000 SSH_CLIENT=71.251.147.235 52298 22 OS_REGION_NAME=RegionOne <------------------- SELINUX_USE_CURRENT_RANGE= SSH_TTY=/dev/pts/0 USER=root LS_COLORS=rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:mi=01;05;37;41:su=37;41:sg=30;43:ca=30;41:tw=30;42:ow=34 ;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arc=01;31:*.arj=01;31:*.taz=01;31:*.lha=01;31:*.lz4=01;31:*.lzh=01;31:*.lzma=01;31:*.tlz=01;31:*.txz=01;31:*.t zo=01;31:*.t7z=01;31:*.zip=01;31:*.z=01;31:*.Z=01;31:*.dz=01;31:*.gz=01;31:*.lrz=01;31:*.lz=01;31:*.lzo=01;31:*.xz=01;31:*.bz2=01;31:*.bz=01;31:*.tbz=01;31:*. tbz2=01;31:*.tz=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.war=01;31:*.ear=01;31:*.sar=01;31:*.rar=01;31:*.alz=01;31:*.ace=01;31:*.zoo=01;31:*.cpio=01;31:*.7 z=01;31:*.rz=01;31:*.cab=01;31:*.jpg=01;35:*.jpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif= 01;35:*.tiff=01;35:*.png=01;35:*.svg=01;35:*.svgz=01;35:*.mng=01;35:*.pcx=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.m2v=01;35:*.mkv=01;35:*.webm=01;35:*.og m=01;35:*.mp4=01;35:*.m4v=01;35:*.mp4v=01;35:*.vob=01;35:*.qt=01;35:*.nuv=01;35:*.wmv=01;35:*.asf=01;35:*.rm=01;35:*.rmvb=01;35:*.flc=01;35:*.avi=01;35:*.fli= 01;35:*.flv=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.yuv=01;35:*.cgm=01;35:*.emf=01;35:*.axv=01;35:*.anx=01;35:*.ogv=01;35:*.ogx=01;35:*.aac=01;3 6:*.au=01;36:*.flac=01;36:*.mid=01;36:*.midi=01;36:*.mka=01;36:*.mp3=01;36:*.mpc=01;36:*.ogg=01;36:*.ra=01;36:*.wav=01;36:*.axa=01;36:*.oga=01;36:*.spx=01;36: *.xspf=01;36: MAIL=/var/spool/mail/root PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin PWD=/root OS_PASSWORD=alta3 <----------------- LANG=en_US.UTF-8 PS1=[\u@\h \W(keystone_admin)]\$ SELINUX_LEVEL_REQUESTED= OS_AUTH_URL=http://192.168.0.10:5000/v2.0/ HISTCONTROL=ignoredups OS_USERNAME=admin <------------------- SHLVL=1 HOME=/root OS_TENANT_NAME=admin <---------------------- LOGNAME=root SSH_CONNECTION=71.251.147.235 52298 192.168.0.10 22 LESSOPEN=||/usr/bin/lesspipe.sh %s XDG_RUNTIME_DIR=/run/user/0 _=/usr/bin/printenv
-
Flex your new admin environmental-variable-given powers
[root@controller ~(keystone_admin)]#
nova flavor-list
This time it should just work without having to type the extra permissions. Try executing a few more commands to the other OpenStack services as well.
+----+-----------+-----------+------+-----------+------+-------+-------------+-----------+ | ID | Name | Memory_MB | Disk | Ephemeral | Swap | VCPUs | RXTX_Factor | Is_Public | +----+-----------+-----------+------+-----------+------+-------+-------------+-----------+ | 1 | m1.tiny | 512 | 1 | 0 | | 1 | 1.0 | True | | 2 | m1.small | 2048 | 20 | 0 | | 1 | 1.0 | True | | 3 | m1.medium | 4096 | 40 | 0 | | 2 | 1.0 | True | | 4 | m1.large | 8192 | 80 | 0 | | 4 | 1.0 | True | | 5 | m1.xlarge | 16384 | 160 | 0 | | 8 | 1.0 | True | +----+-----------+-----------+------+-----------+------+-------+-------------+-----------+
-
Issue a few more commands.
[root@controller ~(keystone_admin)]#
keystone tenant-create --name temp_tenant
[root@controller ~(keystone_admin)]#
keystone tenant-list
-
Launch and use the python-openstackclient if you're tired of getting the deprecation errors.
OpenStack is attempting to 'unite' all of the OpenStack commands inside of a common python 'wrapper', or a platform that allows you to issue a common set of commands for every OpenStack service. This is why CLI commands issued to the keystone-pythonclient are receiving deprecation warnings. Some people are using the openstack-pythonclient, and some are not, but we think it is important you know it exists.
[root@controller ~(keystone_admin)]#
openstack
(openstack)
help
(openstack)
exit
The permissions still apply! If you have sourced the
keystonerc_admin
file, then launch the python-openstackclient, then you are issuing commands to OpenStack as admin.
Remember our buddy Chester Copperpot of Vault Tek? You should see him when you issued the previous command keystone user-list.
Let's make it easy for us to execute OpenStack commands as Chester Copperpot who is part of the project vault_tek
at the CLI.
-
To make sure we're all on the same page, set the environmental variables found in
keystonerc_admin
[root@controller ~(keystone_admin)]#
source keystonerc_admin
-
List the keystone users
[root@controller ~(keystone_admin)]#
keystone user-list
+----------------------------------+------------------+---------+---------------------------+ | id | name | enabled | email | +----------------------------------+------------------+---------+---------------------------+ | e9483918caa940a48fe882ba092c7e0b | admin | True | root@localhost | | 5bbecabeb2a74aff9dc27f9a8675de45 | aliceanderson | True | | | 641761fe08b74a42b2b3497a38f06020 | bobbarker | True | | | 9b1f9b36d7354b1ea121ccfbae339d8b | ceilometer | True | ceilometer@localhost | | 5b1e70851c2e451c8c0848f60b338e90 | chestercopperpot | True | chester@vault_tek.example | | e96c13b017b341a79808ebc9f04afa98 | cinder | True | cinder@localhost | | 92b130a947e342adb476431b041ed43c | demo | True | | | f02ffa49234a401d8461406c5ef5780d | gandalf | True | [email protected] | | 6146821b56ed4ca18f82b0f90afd278c | glance | True | glance@localhost | | ff5f550ecf064e65bd45d2d0b91bbdab | neutron | True | neutron@localhost | | d3125ab7d2eb4ba0a23d480eee988419 | nova | True | nova@localhost | | 4c8da8951ad34d4498d534e2efb842ec | swift | True | swift@localhost | +----------------------------------+------------------+---------+---------------------------+
-
Look at the user chestercopperpot, and note his tenantID
[root@controller ~(keystone_admin)]#
keystone user-get chestercopperpot
+----------+----------------------------------+ | Property | Value | +----------+----------------------------------+ | email | chester@vault_tek.example | | enabled | True | | id | 5b1e70851c2e451c8c0848f60b338e90 | | name | chestercopperpot | | tenantId | 5ca9bad4f0e94b2eb0fac330dff988d9 | | username | chestercopperpot | +----------+----------------------------------+
-
Find the tenant name for chester's tenantID value by comparing the tenantID above with the id below (should be vault_tek)
[root@controller ~(keystone_admin)]#
keystone tenant-list
+----------------------------------+-------------+---------+ | id | name | enabled | +----------------------------------+-------------+---------+ | edb80920a0e84fbb85372d50a18e8d98 | acme_inc | True | | 300b2cc45c3846939e589310ae714e46 | admin | True | | a9c27d47441e432c8529f8f30ea3261e | demo | True | | 85a11a1515f94848be7aa5b56adec8bf | services | True | | 5e244f171df344cebc2bcce91fc90d96 | temp_tenant | True | | 5005fe4c52144d1299fddb9cfc1f9b48 | the_shire | True | | 5ca9bad4f0e94b2eb0fac330dff988d9 | vault_tek | True | <- UUID of vault_tek +----------------------------------+-------------+---------+
-
While we are on a roll, lets try a few additional commands. Lets use tenant-get to discover the name if we only know the id!
[root@controller ~(keystone_admin)]#
keystone tenant-get 5ca9bad4f0e94b2eb0fac330dff988d9
<-- Put YOUR UUID of vault_tek here!!!+-------------+----------------------------------+ | Property | Value | +-------------+----------------------------------+ | description | | | enabled | True | | id | 5ca9bad4f0e94b2eb0fac330dff988d9 | | name | vault_tek | +-------------+----------------------------------+
-
Yet another way, suppose we only know the tenant name, not the id.
[root@controller ~(keystone_admin)]#
keystone tenant-get vault_tek
+-------------+----------------------------------+ | Property | Value | +-------------+----------------------------------+ | description | | | enabled | True | | id | 5ca9bad4f0e94b2eb0fac330dff988d9 | | name | vault_tek | +-------------+----------------------------------+
-
Make a copy of the keystonerc_admin file, then open it in nano so we can edit it.
(keystone_admin)#
cp keystonerc_admin keystonerc_chestercopperpot
-
Throughout the rest of the lab, you may use either nano or vim.
nano:
(keystone_admin)#
nano keystonerc_chestercopperpot
vim:
(keystone_admin)#
vim keystonerc_chestercopperpot
-
Edit keystonerc_chestercopperpot so it looks like the following.
export OS_USERNAME=chestercopperpot export OS_TENANT_NAME=vault_tek export OS_PASSWORD=fa5tpa55w0rd export OS_AUTH_URL=http://192.168.0.10:5000/v2.0/ export OS_REGION_NAME=RegionOne export PS1='[\u@\h \W(keystone_chestercopperpot)]\$ '
Nano hints:
When you're done editing changes, do the following:
press CTRL + O (to write out aka save)
press ENTER (to confirm save)
press CTRL + X (to exit) -
Display the contents of keystonerc_chestercopperpot and verify that they are correct.
[root@controller ~(keystone_admin)#
cat keystonerc_chestercopperpot
-
Set global variables in the current shell to correspond with the user chestercopperpot, then check the results... notice anything that begins OS_ is now a reflection of chestercopperpot.
[root@controller ~(keystone_admin)#
source keystonerc_chestercopperpot
[root@controller ~(keystone_chestercopperpot)#
printenv | grep OS_
OS_USERNAME=chestercopperpot OS_TENANT_NAME=vault_tek OS_PASSWORD=fa5tpa55w0rd OS_AUTH_URL=http://192.168.0.10:5000/v2.0/ OS_REGION_NAME=RegionOne
-
Note the CLI changed. Run commands and see how the results differ from chester's perspective.
[root@controller ~(keystone_chestercopperpot)#
nova flavor-list
OK, this worked!
[root@controller ~(keystone_chestercopperpot)#
keystone tenant-list
This should result in an HTTP 403 failure, as the user chestercopperpot does not have sufficient permissions to issue this keystone command.
-
Let's repeat the process for the user aliceanderson
[root@controller ~(keystone_chestercopperpot)#
cp keystonerc_admin keystonerc_aliceanderson
Use the editor (nano or vim) of your choice to edit the file.
nano:
[root@controller ~(keystone_chestercopperpot)#
nano keystonerc_aliceanderson
vim:[root@controller ~(keystone_chestercopperpot)#
vim keystonerc_aliceanderson
-
Edit keystonerc_aliceanderson so it looks like the following (or copy and paste is fine):
export OS_USERNAME=aliceanderson export OS_TENANT_NAME=acme_inc export OS_PASSWORD=fa5tpa55w0rd export OS_AUTH_URL=http://192.168.0.10:5000/v2.0/ export OS_REGION_NAME=RegionOne export PS1='[\u@\h \W(keystone_aliceanderson)]\$ '
Nano hints:
When you're done editing changes, do the following:
press CTRL + O (to write out aka save)
press ENTER (to confirm save)
press CTRL + X (to exit) -
Display the contents of keystonerc_aliceanderson and verify that they are correct
[root@controller ~(keystone_chestercopperpot)#
cat keystonerc_aliceanderson
-
Finally, lets repeat the process again for user bobbarker, using the editor of your choice.c
[root@controller ~(keystone_chestercopperpot)#
cp keystonerc_admin keystonerc_bobbarker
nano:
[root@controller ~(keystone_chestercopperpot)#
nano keystonerc_bobbarker
vim:[root@controller ~(keystone_chestercopperpot)#
vim keystonerc_bobbarker
-
Edit keystonerc_bobbarker so it looks like the following (copy and paste is fine):
export OS_USERNAME=bobbarker export OS_TENANT_NAME=acme_inc export OS_PASSWORD=fa5tpa55w0rd export OS_AUTH_URL=http://192.168.0.10:5000/v2.0/ export OS_REGION_NAME=RegionOne export PS1='[\u@\h \W(keystone_bobbarker)]\$ '
Nano hints:
When you're done editing changes, do the following:
press CTRL + O (to write out aka save)
press ENTER (to confirm save)
press CTRL + X (to exit) -
Display the contents of keystonerc_bobbarker and verify that they are correct
[root@controller ~(keystone_chestercopperpot)#
cat keystonerc_bobbarker
4. Using the OpenStack Horizon Dashboard to assist in creating a keystonerc file for new user Doris Day of Vault Tek
-
Log in to the OpenStack Horizon Dashboard as
chestercopperpot
//fa5tpa55w0rd
-
Click on Project > Compute > Access & Security
-
Click on the tab API Access
-
In the upper right corner, click on the button Download OpenStack RC File
-
This file will download to your browser's download folder. This file is just for your own reference, but take a moment to open it in your favorite text editor and read it over. The file you open will look similar to the one shown below. Again, reading over this file is just an FYI / reference step. Just a recommendation, if your "favorite" text editor is Microsoft Notepad or Microsoft Word, then it is recommended you take 2 minutes and go download Notepad++. It is a great utility for quickly editing simple text files.
bash #!/bin/bash # To use an OpenStack cloud you need to authenticate against the Identity # service named keystone, which returns a **Token** and **Service Catalog**. # The catalog contains the endpoints for all services the user/tenant has # access to - such as Compute, Image Service, Identity, Object Storage, Block # Storage, and Networking (code-named nova, glance, keystone, swift, # cinder, and neutron). # # # *NOTE*: Using the 2.0 *Identity API* does not necessarily mean any other # OpenStack API is version 2.0. For example, your cloud provider may implement # Image API v1.1, Block Storage API v2, and Compute API v2.0. OS_AUTH_URL is # only for the Identity API served through keystone. export OS_AUTH_URL=http://192.168.0.10:5000/v2.0 # # # With the addition of Keystone we have standardized on the term **tenant** # as the entity that owns the resources. export OS_TENANT_ID=57dc930957f243438e532163269138d1 export OS_TENANT_NAME="vault_tek" export OS_PROJECT_NAME="vault_tek" # # # In addition to the owning entity (tenant), OpenStack stores the entity # performing the action as the **user**. export OS_USERNAME="chestercopperpot" # # # # # LOOK AT THIS # # # # # With Keystone you pass the keystone password. echo "Please enter your OpenStack Password: " read -sr OS_PASSWORD_INPUT export OS_PASSWORD=$OS_PASSWORD_INPUT # # # # END LOOK AT THIS # # # # # # If your configuration has multiple regions, we set that information here. # OS_REGION_NAME is optional and only valid in certain environments. export OS_REGION_NAME="RegionOne" # # # Don't leave a blank variable, unset it if it was empty if [ -z "$OS_REGION_NAME" ]; then unset OS_REGION_NAME; fi
This file is a bit fancier than the previous one we studied, but it is well commented. There are two key differences between this file and ours:
-
The first is that this file will require the user to enter their password instead of storing it locally as plain-text. In production, this is desirable, as asking users to enter their password will prevent admins from having to manage security and permissions on user files because they contain plain-text passwords.
-
The second difference is that this file also sets some additional environmental variables, which could be problematic, as our other keystonerc_.* files do NOT set these variables. If we source back to another user without first unsetting these variables, we might get ourselves into trouble. So instead of using this file, let's just borrow the piece of code that asks the user for the password. It is shown below for reference:
# With Keystone you pass the keystone password. echo "Please enter your OpenStack Password: " read -sr OS_PASSWORD_INPUT export OS_PASSWORD=$OS_PASSWORD_INPUT
-
-
We're done in Horizon for now. Return to your SSH session with the controller and source keystone_admin
[root@controller ~]#
source keystonerc_admin
-
Let's create a new user (Doris Day) within the vault_tek project (tenant) and then create a source file that prompts for a password.
[root@controller ~(keystone_admin)]#
keystone user-create --name dorisday --tenant vault_tek --pass fa5tpa55w0rd --email dorisday@vault_tek.example
+----------+----------------------------------+ | Property | Value | +----------+----------------------------------+ | email | dorisday@vault_tek.example | | enabled | True | | id | 8086288736dc4147bf38ffaf07acd9b5 | | name | dorisday | | tenantId | 8f6d4710d774466f96858af6fa69aaa3 | | username | dorisday | +----------+----------------------------------+
-
Create a file we can source for Doris Day of Vault Tek.
nano:
[root@controller ~(keystone_admin)]#
nano keystonerc_dorisday
vim[root@controller ~(keystone_admin)]#
vim keystonerc_dorisday
-
Edit
keystonerc_dorisday
so it looks like the following:export OS_USERNAME=dorisday export OS_TENANT_NAME=vault_tek echo "Please enter your OpenStack Password: " read -sr OS_PASSWORD_INPUT export OS_PASSWORD=$OS_PASSWORD_INPUT export OS_AUTH_URL=http://192.168.0.10:5000/v2.0/ export OS_REGION_NAME=RegionOne export PS1='[\u@\h \W(keystone_dorisday)]\$ '
Nano hints:
When you're done editing changes, do the following:
press CTRL + O (to write out aka save)
press ENTER (to confirm save)
press CTRL + X (to exit) -
Confirm that the file was saved correctly, by displaying the output with cat, and then source keystonerc_dorisday
[root@controller ~(keystone_admin)]#
source keystonerc_dorisday
Please enter your OpenStack Password:
fa5tpa55w0rd
- Q1: Is this mechanism, prompting for a password, more secure? Why or why not?
- Q1: In theory, yes. A user being prompted for a password is more secure than letting a password sit in a plain text document where proper read permissions and encryption may or may not be applied. Regardless, anytime the export command is used to set an environmental variable in a linux shell, securing that shell session should be a primary concern.
- Q1: Is this mechanism, prompting for a password, more secure? Why or why not?
-
Make sure the file works. Test by issuing a CLI command requiring authentication.
[root@controller ~(keystone_dorisday)]#
nova flavor-list
If output like this is displayed, then it worked!
+----+-----------+-----------+------+-----------+------+-------+-------------+-----------+ | ID | Name | Memory_MB | Disk | Ephemeral | Swap | VCPUs | RXTX_Factor | Is_Public | +----+-----------+-----------+------+-----------+------+-------+-------------+-----------+ | 1 | m1.tiny | 512 | 1 | 0 | | 1 | 1.0 | True | | 2 | m1.small | 2048 | 20 | 0 | | 1 | 1.0 | True | | 3 | m1.medium | 4096 | 40 | 0 | | 2 | 1.0 | True | | 4 | m1.large | 8192 | 80 | 0 | | 4 | 1.0 | True | | 5 | m1.xlarge | 16384 | 160 | 0 | | 8 | 1.0 | True | +----+-----------+-----------+------+-----------+------+-------+-------------+-----------+
Great job! You are all done with this lab. If you are done early, go onto the next section. It will teach you a little bit more about what is going on when you run the
source
command.
In OpenStack, we learned that we could type out the --os-tenant-name
, --os-user-name
, --os-password
, and --os-auth-url
along with every command, or we could set these values so they persist. If you are not a master of the CLI, you might be curious about how this worked! Understanding how it works might also help you in troubleshooting. After all, what if you ran a source file (set environmental variables), and wish you could un-run that source file (unset environmental variables).
Variables can be of two basic types: shell variables, or environmental variables. Shell variables are only available within the current session, whereas environmental variables are available to the current session, as well as any spawned sessions. What is a session? You're in one right now. The Bash shell that you are sitting at is a 'session'. If you were to type bash
, you'd launch another session that would be considered a 'child' session, where your current session would be the 'parent'.
If a child session is spawned by a parent session, environmental variables will be made available to the child sessions, whereas a shell variable will not. To better understand the difference, perform this quick procedure; define a shell variable, and then an environmental variable within parent and child bash shells.
-
Create a shell variable within the current session. Convention says it should be all caps. Because the string we've defined includes a bang, we are using single quotes to surround 'Hello OpenStack!'.
[root@controller ~]#
LEARNING_VAR='Hello OpenStack!'
-
Great! We can confirm that this is a shell variable that will not be passed down to child processes by grepping within output from set
[root@controller ~]#
set | grep LEARNING_VAR
-
LEARNING_VAR='Hello OpenStack!' should be displayed. Now confirm it is NOT an environmental variable by performing the same procedure with printenv.
[root@controller ~]#
printenv | grep LEARNING_VAR
No output should be returned, as printenv will only print environmental variables.
-
Let's take a moment to demonstrate how to access any shell or environmental variable. When the shell encounters a
$
sign, it takes it to mean that it should substitute the value of the variable when it comes across it. Type the following command.[root@controller ~]#
echo $LEARNING_VAR
The string Hello OpenStack! should be displayed.
-
If you type 'bash', you'll spawn a child shell. Think of this as accessing a 'shell within a shell'. Within this child session our variable,
$LEARNING_VAR
, should not be available.[root@controller ~]#
bash
[root@controller ~]#
echo $LEARNING_VAR
No output should be displayed. Hopefully, why no output was display is clear. This is a child session, and was not passed the previous shell variables. Remember, shell variables are only good for the current shell. Type the following to test this assertion.
-
Type exit to close the child session and return to the original session.
[root@controller ~]#
exit
[root@controller ~]#
echo $LEARNING_VAR
Once again, the string Hello OpenStack! should be displayed, as we have returned to the parent shell (the shell we started in).
-
Okay. So to recap, LEARNING_VAR is currently a shell variable, but we can make it an environmental variable by using the export command. Let's also change the value of $LEARNING_VAR from
Hello OpenStack!
toOpenStack Hello!
.[root@controller ~]#
export LEARNING_VAR='OpenStack Hello!'
[root@controller ~]#
printenv | grep LEARNING_VAR
-
Now, let us run the same experiment and observe our minor change. Once again, spawn a child shell.
[root@controller ~]#
bash
[root@controller ~]#
echo $LEARNING_VAR
OpenStack Hello!
should be displayed. -
Confirm that it is still set as an environmental variable.
[root@controller ~]#
printenv | grep LEARNING_VAR
-
Now let's set an environmental variable from within our current child shell.
[root@controller ~]#
export NEW_LEARNING_VAR='Bonjour OpenStack!'
-
Issue the following commands to confirm that it was indeed set as an environmental variable. Then exit the child session, and return to the parent shell.
[root@controller ~]#
printenv | grep NEW_LEARNING_VAR
[root@controller ~]#
exit
-
Now see if the environmental variable NEW_LEARNING_VAR is still available.
[root@controller ~]#
printenv | grep NEW_LEARNING_VAR
No output is returned. This is because
NEW_LEARNING_VAR
was an environmental variable set in the child shell. Emphasis on the word 'was', because when we exited our child shell, that environmental variable was destroyed. -
The original variable, LEARNING_VAR can be changed back into a shell variable (demoted), by using export and the -n flag.
[root@controller ~]#
export -n LEARNING_VAR
-
Test that it is no longer a global variable, but still a shell variable
[root@controller ~]#
printenv | grep LEARNING_VAR
No output will be shown as LEARNING_VAR is no longer an environmental variable.
[root@controller ~]#
echo $LEARNING_VAR
OpenStack Hello! should be displayed, as LEARNING_VAR is now a shell variable.
[root@controller ~]#
set | grep LEARNING_VAR
LEARNING_VAR='OpenStack Hello!'
will be displayed, confirmingLEARNING_VAR
exists as a shell variable. -
A shell and environmental variable can be completely removed by issuing the unset command.
[root@controller ~]#
unset LEARNING_VAR
[root@controller ~]#
echo $LEARNING_VAR
Nothing will be displayed, as
LEARNING_VAR
has been unset[root@controller ~]#
set | grep LEARNING_VAR
Nothing will be displayed.