{"id":340,"date":"2016-02-19T08:51:15","date_gmt":"2016-02-19T08:51:15","guid":{"rendered":"http:\/\/tuxlabs.com\/?p=340"},"modified":"2016-03-01T23:27:09","modified_gmt":"2016-03-01T23:27:09","slug":"how-to-curl-the-openstack-apis-v3-keystone-auth","status":"publish","type":"post","link":"https:\/\/tuxlabs.com\/?p=340","title":{"rendered":"How To: curl the Openstack API&#8217;s (v3 Keystone Auth)"},"content":{"rendered":"<blockquote><p>While Openstack provides a python client(s) for interactions&#8230;.<\/p><\/blockquote>\n<pre class=\"lang:sh decode:true\">[root@diamond ~]# source keystonerc_tuxninja\r\n[root@diamond ~(keystone_tuxninja)]# openstack server list\r\n+--------------------------------------+-------+--------+----------------------------------------+\r\n| ID                                   | Name  | Status | Networks                               |\r\n+--------------------------------------+-------+--------+----------------------------------------+\r\n| e5b35d6a-a9ba-4714-a9e1-6361706bd047 | spin1 | ACTIVE | private_tuxlabs=10.0.0.8, 192.168.1.52 |\r\n+--------------------------------------+-------+--------+----------------------------------------+\r\n[root@diamond ~(keystone_tuxninja)]#<\/pre>\n<p>I frequently, finding myself needing to get data out of it without the pain of awk\/sed&#8217;ing out the ASCII art.<\/p>\n<p>Thus to quickly access the raw data, we can directly query the API&#8217;s using curl &amp; parsing JSON instead, which is much better \ud83d\ude42<\/p>\n<h2>Authentication<\/h2>\n<p>Before we can interact with the other Openstack API&#8217;s we need to authenticate to Keystone openstack&#8217;s identity service. After authenticating we receive a token to use with our subequent API requests. So step 1 we are going to create a JSON object with the required authentication details.<\/p>\n<p>Create a file called &#8216;token-request.json&#8217; with an object that looks like this.<\/p>\n<pre class=\"lang:js decode:true\">{\r\n    \"auth\": {\r\n        \"identity\": {\r\n            \"methods\": [\r\n                \"password\"\r\n            ],\r\n            \"password\": {\r\n                \"user\": {\r\n                    \"domain\": {\r\n                        \"id\": \"default\"\r\n                    },\r\n                    \"name\": \"tuxninja\",\r\n                    \"password\": \"put_your_openstack_pass\"\r\n                }\r\n            }\r\n        }\r\n    }\r\n}<\/pre>\n<blockquote><p>Btw, if you followed my tutorial on how to install <a href=\"http:\/\/tuxlabs.com\/?p=322\">Openstack Kilo<\/a>, your authentication details for &#8216;admin&#8217; is in your keystonerc_admin file.<\/p><\/blockquote>\n<p>Now we can use this file to authenticate like so:<\/p>\n<pre class=\"lang:default decode:true \">export TOKEN=`curl -si -d @token-request.json -H \"Content-type: application\/json\" http:\/\/localhost:35357\/v3\/auth\/tokens | awk '\/X-Subject-Token\/ {print $2}'`<\/pre>\n<p>The token is actually returned in the header of the HTTP response, so this is why we need &#8216;-i&#8217; when curling. Notice we are parsing out the token and returning the value to an environment variable $TOKEN.<\/p>\n<p>Now we can include this $TOKEN and run whatever API commands we want (assuming admin privileges for the tenant\/project)<\/p>\n<h2>Curl Commands (Numerous Examples!)<\/h2>\n<pre class=\"lang:default decode:true \"># list domains\r\ncurl -si -H\"X-Auth-Token:$TOKEN\" -H \"Content-type: application\/json\" http:\/\/localhost:35357\/v3\/domains\r\n\r\n# create a domain\r\ncurl  -H\"X-Auth-Token:$TOKEN\" -H \"Content-type: application\/json\" -d '{\"domain\": {\"description\": \"--optional--\", \"enabled\": true, \"name\": \"dom1\"}}'  http:\/\/localhost:35357\/v3\/domains\r\n\r\n\r\n# list users\r\ncurl -si -H\"X-Auth-Token:$TOKEN\" -H \"Content-type: application\/json\" http:\/\/localhost:35357\/v3\/users\r\n\r\n# To create a users, create file named create_user.json file like this:\r\n\r\n{\r\n    \"user\": {\r\n           \"default_project_id\": \"18ed894bb8b84a5b9144c129fc754722\",\r\n            \"description\": \"Description\",\r\n            \"domain_id\": \"default\",\r\n            \"email\": \"tuxninja@tuxlabs.com\",\r\n            \"enabled\": true,\r\n            \"name\": \"tuxninja\",\r\n            \"password\": \"changeme\" }\r\n}\r\n\r\n# then run\r\ncurl -si -H\"X-Auth-Token:$TOKEN\" -H \"Content-type: application\/json\" http:\/\/localhost:35357\/v3\/users -d @create_user.json\r\n\r\n\r\n# list images in nova\r\n                                                                                             &lt;tenant_id&gt;\r\ncurl -s -H\"X-Auth-Token:$TOKEN\" -H \"Content-type: application\/json\" http:\/\/localhost:8774\/v2\/18ed894bb8b84a5b9144c129fc754722\/images | python -m json.tool\r\n\r\n# list servers (vms)\r\n\r\ncurl -s -H\"X-Auth-Token:$TOKEN\" -H \"Content-type: application\/json\" http:\/\/localhost:8774\/v2\/18ed894bb8b84a5b9144c129fc754722\/servers | python -m json.tool\r\n\r\n# neutron networks\r\n\r\ncurl -s -H\"X-Auth-Token:$TOKEN\" -H \"Content-type: application\/json\" http:\/\/localhost:9696\/v2.0\/networks | python -m json.tool\r\n\r\n# neutron subnets\r\n\r\ncurl -s -H\"X-Auth-Token:$TOKEN\" -H \"Content-type: application\/json\" http:\/\/localhost:9696\/v2.0\/networks | python -m json.tool<\/pre>\n<blockquote><p>I sometimes pipe the output to python -m json.tool, which provides formatting for JSON. Lets take a closer look at an example.<\/p><\/blockquote>\n<h3><strong>Listing servers (vm&#8217;s) <\/strong><\/h3>\n<pre class=\"lang:default decode:true \">[root@diamond ~(keystone_tuxninja)]# curl -s -H\"X-Auth-Token:$TOKEN\" -H \"Content-type: application\/json\" http:\/\/localhost:8774\/v2\/18ed894bb8b84a5b9144c129fc754722\/servers | python -m json.tool\r\n{\r\n    \"servers\": [\r\n        {\r\n            \"id\": \"e5b35d6a-a9ba-4714-a9e1-6361706bd047\",\r\n            \"links\": [\r\n                {\r\n                    \"href\": \"http:\/\/localhost:8774\/v2\/18ed894bb8b84a5b9144c129fc754722\/servers\/e5b35d6a-a9ba-4714-a9e1-6361706bd047\",\r\n                    \"rel\": \"self\"\r\n                },\r\n                {\r\n                    \"href\": \"http:\/\/localhost:8774\/18ed894bb8b84a5b9144c129fc754722\/servers\/e5b35d6a-a9ba-4714-a9e1-6361706bd047\",\r\n                    \"rel\": \"bookmark\"\r\n                }\r\n            ],\r\n            \"name\": \"spin1\"\r\n        }\r\n    ]\r\n}\r\n[root@diamond ~(keystone_tuxninja)]#<\/pre>\n<p>I only have 1 VM currently called spin1, but for the tutorials sake, if I had ten&#8217;s or hundred&#8217;s of VM&#8217;s and all I cared about was the VM name or ID, I would still need to parse this JSON object to avoid getting all this other meta-data.<\/p>\n<blockquote><p>My favorite command line way to do that without going full Python is using the handy <a href=\"https:\/\/stedolan.github.io\/jq\/\">JQ tool<\/a>.<\/p><\/blockquote>\n<p>Here is how to use it !<\/p>\n<pre class=\"lang:sh decode:true \">[root@diamond ~(keystone_tuxninja)]# curl -s -H\"X-Auth-Token:$TOKEN\" -H \"Content-type: application\/json\" http:\/\/localhost:8774\/v2\/18ed894bb8b84a5b9144c129fc754722\/servers | jq .\r\n{\r\n  \"servers\": [\r\n    {\r\n      \"name\": \"spin1\",\r\n      \"links\": [\r\n        {\r\n          \"rel\": \"self\",\r\n          \"href\": \"http:\/\/localhost:8774\/v2\/18ed894bb8b84a5b9144c129fc754722\/servers\/e5b35d6a-a9ba-4714-a9e1-6361706bd047\"\r\n        },\r\n        {\r\n          \"rel\": \"bookmark\",\r\n          \"href\": \"http:\/\/localhost:8774\/18ed894bb8b84a5b9144c129fc754722\/servers\/e5b35d6a-a9ba-4714-a9e1-6361706bd047\"\r\n        }\r\n      ],\r\n      \"id\": \"e5b35d6a-a9ba-4714-a9e1-6361706bd047\"\r\n    }\r\n  ]\r\n}\r\n[root@diamond ~(keystone_tuxninja)]#\r\n[root@diamond ~(keystone_tuxninja)]# curl -s -H\"X-Auth-Token:$TOKEN\" -H \"Content-type: application\/json\" http:\/\/localhost:8774\/v2\/18ed894bb8b84a5b9144c129fc754722\/servers | jq .servers[0].name -r\r\nspin1\r\n[root@diamond ~(keystone_tuxninja)]#<\/pre>\n<p>The first command just takes whatever the STDOUT from curl is and indent&#8217;s and color&#8217;s the JSON making it pretty (colors gives it +1 vs. python -m json.tool).<\/p>\n<p>The second example we actually parse what were after. As you can see it is pretty simple, but jq&#8217;s query language may not be 100% intuitive at first, but I promise it is pretty easy to understand if you have ever parsed JSON before. Read up more on JQ @ <a href=\"https:\/\/stedolan.github.io\/jq\/\">https:\/\/stedolan.github.io\/jq\/<\/a> &amp; check out the Openstack docs for more API commands <a href=\"http:\/\/developer.openstack.org\/api-ref.html\">http:\/\/developer.openstack.org\/api-ref.html<\/a><\/p>\n<p>Hope you enjoyed this post ! Until next time.<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<a href=\"https:\/\/tuxlabs.com\/?p=340\" rel=\"bookmark\" title=\"Permalink to How To: curl the Openstack API&#8217;s (v3 Keystone Auth)\"><p>While Openstack provides a python client(s) for interactions&#8230;. [root@diamond ~]# source keystonerc_tuxninja [root@diamond ~(keystone_tuxninja)]# openstack server list +&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;+&#8212;&#8212;-+&#8212;&#8212;&#8211;+&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-+ | ID | Name | Status | Networks | +&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;+&#8212;&#8212;-+&#8212;&#8212;&#8211;+&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-+ | e5b35d6a-a9ba-4714-a9e1-6361706bd047 | spin1 | ACTIVE | private_tuxlabs=10.0.0.8, 192.168.1.52 | +&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;+&#8212;&#8212;-+&#8212;&#8212;&#8211;+&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-+ [root@diamond ~(keystone_tuxninja)]# I frequently, finding myself needing to get data out of it without the pain [&hellip;]<\/p>\n<\/a>","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[130,1,28,12],"tags":[126,127,20,128,129,19,18,17,13,55],"class_list":{"0":"post-340","1":"post","2":"type-post","3":"status-publish","4":"format-standard","6":"category-cloud","7":"category-howtos","8":"category-openstack-howtos","9":"category-systems-administration","10":"tag-api","11":"tag-curl","12":"tag-glance","13":"tag-jq","14":"tag-json","15":"tag-keystone","16":"tag-neutron","17":"tag-nova","18":"tag-openstack","19":"tag-python","20":"h-entry","21":"hentry"},"_links":{"self":[{"href":"https:\/\/tuxlabs.com\/index.php?rest_route=\/wp\/v2\/posts\/340","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/tuxlabs.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/tuxlabs.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/tuxlabs.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/tuxlabs.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=340"}],"version-history":[{"count":4,"href":"https:\/\/tuxlabs.com\/index.php?rest_route=\/wp\/v2\/posts\/340\/revisions"}],"predecessor-version":[{"id":346,"href":"https:\/\/tuxlabs.com\/index.php?rest_route=\/wp\/v2\/posts\/340\/revisions\/346"}],"wp:attachment":[{"href":"https:\/\/tuxlabs.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=340"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/tuxlabs.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=340"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/tuxlabs.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=340"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}