CLOUDSTACK-2338: Adding example of how to sign api requests in python
Project: http://git-wip-us.apache.org/repos/asf/cloudstack/repo Commit: http://git-wip-us.apache.org/repos/asf/cloudstack/commit/5bb760f2 Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/5bb760f2 Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/5bb760f2 Branch: refs/heads/ui-cisco-asa1000v-support Commit: 5bb760f2ed0f753a008e1fd414c081c2ea5e00cc Parents: f0749ce Author: Sebastien Goasguen <run...@gmail.com> Authored: Mon May 6 05:35:19 2013 -0400 Committer: Sebastien Goasguen <run...@gmail.com> Committed: Mon May 6 05:37:21 2013 -0400 ---------------------------------------------------------------------- docs/en-US/signing-api-calls-python.xml | 101 ++++++++++++++++++++++++++ docs/en-US/signing-api-requests.xml | 3 + docs/en-US/tools.xml | 1 + 3 files changed, 105 insertions(+), 0 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cloudstack/blob/5bb760f2/docs/en-US/signing-api-calls-python.xml ---------------------------------------------------------------------- diff --git a/docs/en-US/signing-api-calls-python.xml b/docs/en-US/signing-api-calls-python.xml new file mode 100644 index 0000000..a2f897f --- /dev/null +++ b/docs/en-US/signing-api-calls-python.xml @@ -0,0 +1,101 @@ +<?xml version='1.0' encoding='utf-8' ?> +<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [ +<!ENTITY % BOOK_ENTITIES SYSTEM "cloudstack.ent"> +%BOOK_ENTITIES; +]> + +<!-- Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. +--> + +<section id="signing-api-calls-python"> + <title>How to sign an API call with Python</title> + <para>To illustrate the procedure used to sign API calls we present a step by step interactive session + using Python.</para> + + <para>First import the required modules:</para> + <programlisting> + + <![CDATA[ +$python +Python 2.7.3 (default, Nov 17 2012, 19:54:34) +[GCC 4.2.1 Compatible Apple Clang 4.1 ((tags/Apple/clang-421.11.66))] on darwin +Type "help", "copyright", "credits" or "license" for more information. +>>> import urllib2 +>>> import urllib +>>> import hashlib +>>> import hmac +>>> import base64 + ]]> + </programlisting> + + <para>Define the endpoint of the Cloud, the command that you want to execute and the keys of the user.</para> + <programlisting> + <![CDATA[ + +>>> baseurl='http://localhost:8080/client/api?' +>>> request={} +>>> request['command']='listUsers' +>>> request['response']='json' +>>> request['apikey']='plgWJfZK4gyS3mOMTVmjUVg-X-jlWlnfaUJ9GAbBbf9EdM-kAYMmAiLqzzq1ElZLYq_u38zCm0bewzGUdP66mg' +>>> secretkey='VDaACYb0LV9eNjTetIOElcVQkvJck_J_QljX_FcHRj87ZKiy0z0ty0ZsYBkoXkY9b7eq1EhwJaw7FF3akA3KBQ' + ]]> + </programlisting> + <para>Build the request string:</para> + <programlisting> + <![CDATA[ +>>> request_str='&'.join(['='.join([k,urllib.quote_plus(request[k])]) for k in request.keys()]) +>>> request_str +'apikey=plgWJfZK4gyS3mOMTVmjUVg-X-jlWlnfaUJ9GAbBbf9EdM-kAYMmAiLqzzq1ElZLYq_u38zCm0bewzGUdP66mg&command=listUsers&response=json' + ]]> + </programlisting> + + <para>Compute the signature with hmac, do a 64 bit encoding and a url encoding: </para> + <programlisting> + <![CDATA[ +>>> sig_str='&'.join(['='.join([k.lower(),urllib.quote_plus(request[k].lower().replace('+','%20'))])for k in sorted(request.iterkeys())]) +>>> sig_str +'apikey=plgwjfzk4gys3momtvmjuvg-x-jlwlnfauj9gabbbf9edm-kaymmailqzzq1elzlyq_u38zcm0bewzgudp66mg&command=listusers&response=json' +>>> sig=hmac.new(secretkey,sig_str,hashlib.sha1) +>>> sig +<hmac.HMAC instance at 0x10d91d680> +>>> sig=hmac.new(secretkey,sig_str,hashlib.sha1).digest() +>>> sig +'M:]\x0e\xaf\xfb\x8f\xf2y\xf1p\x91\x1e\x89\x8a\xa1\x05\xc4A\xdb' +>>> sig=base64.encodestring(hmac.new(secretkey,sig_str,hashlib.sha1).digest()) +>>> sig +'TTpdDq/7j/J58XCRHomKoQXEQds=\n' +>>> sig=base64.encodestring(hmac.new(secretkey,sig_str,hashlib.sha1).digest()).strip() +>>> sig +'TTpdDq/7j/J58XCRHomKoQXEQds=' +>>> sig=urllib.quote_plus(base64.encodestring(hmac.new(secretkey,sig_str,hashlib.sha1).digest()).strip()) + ]]> + </programlisting> + + <para>Finally, build the entire string and do an http GET:</para> + <programlisting> + <![CDATA[ +>>> req=baseurl+request_str+'&signature='+sig +>>> req +'http://localhost:8080/client/api?apikey=plgWJfZK4gyS3mOMTVmjUVg-X-jlWlnfaUJ9GAbBbf9EdM-kAYMmAiLqzzq1ElZLYq_u38zCm0bewzGUdP66mg&command=listUsers&response=json&signature=TTpdDq%2F7j%2FJ58XCRHomKoQXEQds%3D' +>>> res=urllib2.urlopen(req) +>>> res.read() +'{ "listusersresponse" : { "count":3 ,"user" : [ {"id":"7ed6d5da-93b2-4545-a502-23d20b48ef2a","username":"admin","firstname":"admin","lastname":"cloud","created":"2012-07-05T12:18:27-0700","state":"enabled","account":"admin","accounttype":1,"domainid":"8a111e58-e155-4482-93ce-84efff3c7c77","domain":"ROOT","apikey":"plgWJfZK4gyS3mOMTVmjUVg-X-jlWlnfaUJ9GAbBbf9EdM-kAYMmAiLqzzq1ElZLYq_u38zCm0bewzGUdP66mg","secretkey":"VDaACYb0LV9eNjTetIOElcVQkvJck_J_QljX_FcHRj87ZKiy0z0ty0ZsYBkoXkY9b7eq1EhwJaw7FF3akA3KBQ","accountid":"7548ac03-af1d-4c1c-9064-2f3e2c0eda0d"}, {"id":"1fea6418-5576-4989-a21e-4790787bbee3","username":"runseb","firstname":"foobar","lastname":"goa","email":"j...@smith.com","created":"2013-04-10T16:52:06-0700","state":"enabled","account":"admin","accounttype":1,"domainid":"8a111e58-e155-4482-93ce-84efff3c7c77","domain":"ROOT","apikey":"Xhsb3MewjJQaXXMszRcLvQI9_NPy_UcbDj1QXikkVbDC9MDSPwWdtZ1bUY1H7JBEYTtDDLY3yuchCeW778GkBA","secretkey":"gIsgmi8C5YwxMHjX5o51pSe0kqs6JnKriw0jJBLceY5b gnfzKjL4aM6ctJX-i1ddQIHJLbLJDK9MRzsKk6xZ_w","accountid":"7548ac03-af1d-4c1c-9064-2f3e2c0eda0d"}, {"id":"52f65396-183c-4473-883f-a37e7bb93967","username":"toto","firstname":"john","lastname":"smith","email":"j...@smith.com","created":"2013-04-23T04:27:22-0700","state":"enabled","account":"admin","accounttype":1,"domainid":"8a111e58-e155-4482-93ce-84efff3c7c77","domain":"ROOT","apikey":"THaA6fFWS_OmvU8od201omxFC8yKNL_Hc5ZCS77LFCJsRzSx48JyZucbUul6XYbEg-ZyXMl_wuEpECzK-wKnow","secretkey":"O5ywpqJorAsEBKR_5jEvrtGHfWL1Y_j1E4Z_iCr8OKCYcsPIOdVcfzjJQ8YqK0a5EzSpoRrjOFiLsG0hQrYnDA","accountid":"7548ac03-af1d-4c1c-9064-2f3e2c0eda0d"} ] } }' + ]]> + </programlisting> + + </section> http://git-wip-us.apache.org/repos/asf/cloudstack/blob/5bb760f2/docs/en-US/signing-api-requests.xml ---------------------------------------------------------------------- diff --git a/docs/en-US/signing-api-requests.xml b/docs/en-US/signing-api-requests.xml index 581b32a..fc8773b 100644 --- a/docs/en-US/signing-api-requests.xml +++ b/docs/en-US/signing-api-requests.xml @@ -57,4 +57,7 @@ <programlisting>http://localhost:8080/client/api?command=deployVirtualMachine&serviceOfferingId=1&diskOfferingId=1&templateId=2&zoneId=4&apiKey=miVr6X7u6bN_sdahOBpjNejPgEsT35eXq-jB8CG20YI3yaxXcgpyuaIRmFI_EJTVwZ0nUkkJbPmY3y2bciKwFQ&signature=Lxx1DM40AjcXU%2FcaiK8RAP0O1hU%3D</programlisting> </listitem> </orderedlist> + + <xi:include href="signing-api-calls-python.xml" xmlns:xi="http://www.w3.org/2001/XInclude" /> + </section> http://git-wip-us.apache.org/repos/asf/cloudstack/blob/5bb760f2/docs/en-US/tools.xml ---------------------------------------------------------------------- diff --git a/docs/en-US/tools.xml b/docs/en-US/tools.xml index db6a510..8cddf28 100644 --- a/docs/en-US/tools.xml +++ b/docs/en-US/tools.xml @@ -27,4 +27,5 @@ <xi:include href="devcloud.xml" xmlns:xi="http://www.w3.org/2001/XInclude" /> <xi:include href="marvin.xml" xmlns:xi="http://www.w3.org/2001/XInclude" /> <xi:include href="cloudmonkey.xml" xmlns:xi="http://www.w3.org/2001/XInclude" /> + <xi:include href="libcloud-examples.xml" xmlns:xi="http://www.w3.org/2001/XInclude" /> </chapter>