<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><title>5.2. Signing API Requests</title><link rel="stylesheet" type="text/css" href="Common_Content/css/default.css" /><link rel="stylesheet" media="print" href="Common_Content/css/print.css" type="text/css" /><meta name="generator" content="publican 2.8" /><meta name="package" content="Apache_CloudStack-Developers_Guide-4.1.0-it-IT-1-" /><script type="text/javascript" src="../../../../../toc.js"></script><script type="text/javascript">
              addID('Apache_CloudStack');
              
	      addID('Apache_CloudStack.4.1.0');
              
              addID('Apache_CloudStack.4.1.0.books');
	      addID('Apache_CloudStack.4.1.0.Developers_Guide');
              </script><link rel="home" href="index.html" title="Manuale dello Sviluppatore CloudStack" /><link rel="up" href="api-calls.html" title="Capitolo 5. Calling the CloudStack API" /><link rel="prev" href="making-api-request.html" title="5.1. Making API Requests" /><link rel="next" href="enabling-api-call-expiration.html" title="5.3. Enabling API Call Expiration" /></head><body class="toc_embeded "><div id="tocdiv" class="toc"><iframe id="tocframe" class="toc" src="../../../../toc.html">This is an iframe, to view it upgrade your browser or enable iframe display.</iframe></div><p id="title"><a class="left" href="http://cloudstack.apache.org"><img src="Common_Content/images/image_left.png" alt="Product Site" /></a><a class="right" href="http://cloudstack.apache.org/docs"><img src="Common_Content/images/image_right.png" alt="Documentation Site" /></a></p><ul class="docnav"><li class="previous"><a accesskey="p" href="making-api-request.html"><strong>Indietro</strong></a></li><li class="next"><a accesskey="n" href="enabling-api-call-expiration.html"><strong>Avanti</strong></a></li></ul><div xml:lang="it-IT" class="section" id="signing-api-requests" lang="it-IT"><div class="titlepage"><div><div><h2 class="title" id="signing-api-requests">5.2. Signing API Requests</h2></div></div></div><div class="para">
		Whether you access the CloudStack API with HTTP or HTTPS, it must still be signed so that CloudStack can verify the caller has been authenticated and authorized to execute the command. Make sure that you have both the API Key and Secret Key provided by the CloudStack administrator for your account before proceeding with the signing process.
	</div><div class="para">
		To show how to sign a request, we will re-use the previous example.
	</div><pre class="programlisting">http://http://localhost:8080/client/api?command=deployVirtualMachine&amp;serviceOfferingId=1&amp;diskOfferingId=1&amp;templateId=2&amp;zoneId=4&amp;apiKey=miVr6X7u6bN_sdahOBpjNejPgEsT35eXq-jB8CG20YI3yaxXcgpyuaIRmFI_EJTVwZ0nUkkJbPmY3y2bciKwFQ&amp;signature=Lxx1DM40AjcXU%2FcaiK8RAP0O1hU%3D</pre><div class="para">
		Breaking this down, we have several distinct parts to this URL.
	</div><div class="itemizedlist"><ul><li class="listitem"><div class="para">
				Base URL: This is the base URL to the CloudStack Management Server.
			</div><pre class="programlisting">http://localhost:8080</pre></li><li class="listitem"><div class="para">
				API Path: This is the path to the API Servlet that processes the incoming requests.
			</div><pre class="programlisting">/client/api?</pre></li><li class="listitem"><div class="para">
				Command String: This part of the query string comprises of the command, its parameters, and the API Key that identifies the account.
			</div><div class="note"><div class="admonition_header"><h2>Nota</h2></div><div class="admonition"><div class="para">
					As with all query string parameters of field-value pairs, the "field" component is case insensitive while all "value" values are case sensitive.
				</div></div></div><pre class="programlisting">command=deployVirtualMachine&amp;serviceOfferingId=1&amp;diskOfferingId=1&amp;templateId=2&amp;zoneId=4&amp;apiKey=miVr6X7u6bN_sdahOBpjNejPgEsT35eXq-jB8CG20YI3yaxXcgpyuaIRmFI_EJTVwZ0nUkkJbPmY3y2bciKwFQ</pre></li><li class="listitem"><div class="para">
				Signature: This is the hashed signature of the Base URL that is generated using a combination of the user’s Secret Key and the HMAC SHA-1 hashing algorithm.
			</div><div class="para">
				&amp;signature=Lxx1DM40AjcXU%2FcaiK8RAP0O1hU%3D
			</div></li></ul></div><div class="para">
		Every API request has the format Base URL+API Path+Command String+Signature.
	</div><div class="para">
		To generate the signature.
	</div><div class="orderedlist"><ol><li class="listitem"><div class="para">
				For each field-value pair (as separated by a '&amp;') in the Command String, URL encode each value so that it can be safely sent via HTTP GET.
			</div><div class="note"><div class="admonition_header"><h2>Nota</h2></div><div class="admonition"><div class="para">
					Make sure all spaces are encoded as "%20" rather than "+".
				</div></div></div></li><li class="listitem"><div class="para">
				Lower case the entire Command String and sort it alphabetically via the field for each field-value pair. The result of this step would look like the following.
			</div><pre class="programlisting">apikey=mivr6x7u6bn_sdahobpjnejpgest35exq-jb8cg20yi3yaxxcgpyuairmfi_ejtvwz0nukkjbpmy3y2bcikwfq&amp;command=deployvirtualmachine&amp;diskofferingid=1&amp;serviceofferingid=1&amp;templateid=2&amp;zoneid=4</pre></li><li class="listitem"><div class="para">
				Take the sorted Command String and run it through the HMAC SHA-1 hashing algorithm (most programming languages offer a utility method to do this) with the user’s Secret Key. Base64 encode the resulting byte array in UTF-8 so that it can be safely transmitted via HTTP. The final string produced after Base64 encoding should be "Lxx1DM40AjcXU%2FcaiK8RAP0O1hU%3D".
			</div><div class="para">
				By reconstructing the final URL in the format Base URL+API Path+Command String+Signature, the final URL should look like:
			</div><pre class="programlisting">http://localhost:8080/client/api?command=deployVirtualMachine&amp;serviceOfferingId=1&amp;diskOfferingId=1&amp;templateId=2&amp;zoneId=4&amp;apiKey=miVr6X7u6bN_sdahOBpjNejPgEsT35eXq-jB8CG20YI3yaxXcgpyuaIRmFI_EJTVwZ0nUkkJbPmY3y2bciKwFQ&amp;signature=Lxx1DM40AjcXU%2FcaiK8RAP0O1hU%3D</pre></li></ol></div><div xml:lang="it-IT" class="section" id="signing-api-calls-python" lang="it-IT"><div class="titlepage"><div><div><h3 class="title" id="signing-api-calls-python">5.2.1. How to sign an API call with Python</h3></div></div></div><div class="para">
		To illustrate the procedure used to sign API calls we present a step by step interactive session using Python.
	</div><div class="para">
		First import the required modules:
	</div><pre class="programlisting">

 
$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.
&gt;&gt;&gt; import urllib2
&gt;&gt;&gt; import urllib
&gt;&gt;&gt; import hashlib
&gt;&gt;&gt; import hmac
&gt;&gt;&gt; import base64
 
</pre><div class="para">
		Define the endpoint of the Cloud, the command that you want to execute and the keys of the user.
	</div><pre class="programlisting">
 

&gt;&gt;&gt; baseurl='http://localhost:8080/client/api?'
&gt;&gt;&gt; request={}
&gt;&gt;&gt; request['command']='listUsers'
&gt;&gt;&gt; request['response']='json'
&gt;&gt;&gt; request['apikey']='plgWJfZK4gyS3mOMTVmjUVg-X-jlWlnfaUJ9GAbBbf9EdM-kAYMmAiLqzzq1ElZLYq_u38zCm0bewzGUdP66mg'
&gt;&gt;&gt; secretkey='VDaACYb0LV9eNjTetIOElcVQkvJck_J_QljX_FcHRj87ZKiy0z0ty0ZsYBkoXkY9b7eq1EhwJaw7FF3akA3KBQ'
  
</pre><div class="para">
		Build the request string:
	</div><pre class="programlisting">
 
&gt;&gt;&gt; request_str='&amp;'.join(['='.join([k,urllib.quote_plus(request[k])]) for k in request.keys()])
&gt;&gt;&gt; request_str
'apikey=plgWJfZK4gyS3mOMTVmjUVg-X-jlWlnfaUJ9GAbBbf9EdM-kAYMmAiLqzzq1ElZLYq_u38zCm0bewzGUdP66mg&amp;command=listUsers&amp;response=json'
  
</pre><div class="para">
		Compute the signature with hmac, do a 64 bit encoding and a url encoding:
	</div><pre class="programlisting">
  
&gt;&gt;&gt; sig_str='&amp;'.join(['='.join([k.lower(),urllib.quote_plus(request[k].lower().replace('+','%20'))])for k in sorted(request.iterkeys())]) 
&gt;&gt;&gt; sig_str
'apikey=plgwjfzk4gys3momtvmjuvg-x-jlwlnfauj9gabbbf9edm-kaymmailqzzq1elzlyq_u38zcm0bewzgudp66mg&amp;command=listusers&amp;response=json'
&gt;&gt;&gt; sig=hmac.new(secretkey,sig_str,hashlib.sha1)
&gt;&gt;&gt; sig
&lt;hmac.HMAC instance at 0x10d91d680&gt;
&gt;&gt;&gt; sig=hmac.new(secretkey,sig_str,hashlib.sha1).digest()
&gt;&gt;&gt; sig
'M:]\x0e\xaf\xfb\x8f\xf2y\xf1p\x91\x1e\x89\x8a\xa1\x05\xc4A\xdb'
&gt;&gt;&gt; sig=base64.encodestring(hmac.new(secretkey,sig_str,hashlib.sha1).digest())
&gt;&gt;&gt; sig
'TTpdDq/7j/J58XCRHomKoQXEQds=\n'
&gt;&gt;&gt; sig=base64.encodestring(hmac.new(secretkey,sig_str,hashlib.sha1).digest()).strip()
&gt;&gt;&gt; sig
'TTpdDq/7j/J58XCRHomKoQXEQds='
&gt;&gt;&gt; sig=urllib.quote_plus(base64.encodestring(hmac.new(secretkey,sig_str,hashlib.sha1).digest()).strip())
  
</pre><div class="para">
		Finally, build the entire string and do an http GET:
	</div><pre class="programlisting">
  
&gt;&gt;&gt; req=baseurl+request_str+'&amp;signature='+sig
&gt;&gt;&gt; req
'http://localhost:8080/client/api?apikey=plgWJfZK4gyS3mOMTVmjUVg-X-jlWlnfaUJ9GAbBbf9EdM-kAYMmAiLqzzq1ElZLYq_u38zCm0bewzGUdP66mg&amp;command=listUsers&amp;response=json&amp;signature=TTpdDq%2F7j%2FJ58XCRHomKoQXEQds%3D'
&gt;&gt;&gt; res=urllib2.urlopen(req)
&gt;&gt;&gt; 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"} ] } }'
  
</pre></div></div><ul class="docnav"><li class="previous"><a accesskey="p" href="making-api-request.html"><strong>Indietro</strong>5.1. Making API Requests</a></li><li class="up"><a accesskey="u" href="#"><strong>Risali</strong></a></li><li class="home"><a accesskey="h" href="index.html"><strong>Partenza</strong></a></li><li class="next"><a accesskey="n" href="enabling-api-call-expiration.html"><strong>Avanti</strong>5.3. Enabling API Call Expiration</a></li></ul></body></html>
