mirror of https://github.com/apache/cloudstack.git
102 lines
5.5 KiB
XML
102 lines
5.5 KiB
XML
<?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":"joe@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":"gIsgmi8C5YwxMHjX5o51pSe0kqs6JnKriw0jJBLceY5bgnfzKjL4aM6ctJX-i1ddQIHJLbLJDK9MRzsKk6xZ_w","accountid":"7548ac03-af1d-4c1c-9064-2f3e2c0eda0d"}, {"id":"52f65396-183c-4473-883f-a37e7bb93967","username":"toto","firstname":"john","lastname":"smith","email":"john@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>
|