<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">

    <title type="text">Cloud Carpenters News</title>
    <subtitle type="text">Cloud Carpenters News:</subtitle>
    <link rel="alternate" type="text/html" href="http://cloudcarpenters.com/" />
    <link rel="self" type="application/atom+xml" href="http://cloudcarpenters.com/atom/" />
    <updated>2009-09-16T03:41:53Z</updated>
    <rights>Copyright (c) 2009, david</rights>
    <generator uri="http://expressionengine.com/" version="1.6.7">ExpressionEngine</generator>
    <id>tag:cloudcarpenters.com,2009:07:25</id>


    <entry>
      <title>Amazon to Require Signed Requests by August 15th</title>
      <link rel="alternate" type="text/html" href="http://cloudcarpenters.com/site/amazon_to_require_signed_requests_by_august_15th/" />
      <id>tag:cloudcarpenters.com,2009:/2.17</id>
      <published>2009-07-25T18:09:45Z</published>
      <updated>2009-07-25T18:16:46Z</updated>
      <author>
            <name>david</name>
            <email>mumrah@gmail.com</email>
                  </author>

      <category term="News"
        scheme="http://cloudcarpenters.com/site/category/News/"
        label="News" />
      <content type="html"><![CDATA[
        <p>A few months back, <a href="http://affiliate-blog.amazon.com/2009/05/attention-amazon-associates-web-service-developers.html" title="Amazon Associates Blog" target="_blank">Amazon announced</a> that all requests to the Product Advertising API must be signed starting August 15th. We have had several people contact us asking for assistance migrating their applications&#8217; API requests to use the new signing protocol. With the deadline coming up fast, we wanted to remind anyone who hasn&#8217;t modified their application that their requests will be invalid starting August 15th. We are more than happy to assist with the migration, but we have also written up <a href="http://cloudcarpenters.com/blog/amazon_products_api_request_signing/" title="Amazon Products API Request Signing">a tutorial on how to sign your requests</a> that might be useful. </p>

<p>All the Best,<br />
The Cloud Carpenters Team
</p> 
      ]]></content>
    </entry>

    <entry>
      <title>Amazon Products API Request Signing</title>
      <link rel="alternate" type="text/html" href="http://cloudcarpenters.com/site/amazon_products_api_request_signing/" />
      <id>tag:cloudcarpenters.com,2009:/2.16</id>
      <published>2009-07-25T14:34:52Z</published>
      <updated>2009-09-16T03:41:53Z</updated>
      <author>
            <name>david</name>
            <email>mumrah@gmail.com</email>
                  </author>

      <category term="Tutorials"
        scheme="http://cloudcarpenters.com/site/category/Tutorials/"
        label="Tutorials" />
      <content type="html"><![CDATA[
        <p>Anyone using the Amazon Product Advertising API (previously known as the Amazon Associates Web Service) should be aware that on August 15th Amazon will start requiring all incoming requests to be signed in accordance with their API documentation. Subscribers to the service should have received an email from Amazon, but if not let this serve as a PSA as well as a tutorial. So far we have implemented solutions for a handful of clients using a variety of languages, and I wanted to share our results with the hope that it will save some headaches.</p>

<p>In this tutorial, we will cover signing requests using Python, PHP, and Visual Basic. If you look at the Product Advertising API documentation (or any of Amazon&#8217;s APIs really), you will see the details for signing REST requests. The process is straightforward, and more or less easy to implement.
</p><ul>
<li>Add an ISO 8601 timestamp (in GMT) as the Timestamp parameters</li>
<li>Sort all of the URL params</li>
<li>Construct a string to sign</li>
<li>Compute an HMAC signature using the SHA256 hash algorithm</li>
<li>Base64 encode the resulting signature and set it as the Signature parameter</li>
</ul>
<h3>General Disclaimer</h3>
<blockquote><p>The following code snippets are not meant to be ingredients in copy-pasta, they are meant to illustrate the procedure for signing Amazon API requests and show users the appropriate functions/libraries/resources for doing so. None of the following code will run as-is.</p></blockquote> <p>Since the Python implementation is by far the easiest and most readable, it will be useful to demonstrate what is going on. 
</p><h3>Python using built-in libraries: hmac, hashlib, and base64</h3><p>
<pre class="python code_block_class" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">base64</span>,hashlib,<span style="color: #dc143c;">hmac</span>,<span style="color: #dc143c;">time</span>
<span style="color: #ff7700;font-weight:bold;">from</span> <span style="color: #dc143c;">urllib</span> <span style="color: #ff7700;font-weight:bold;">import</span> urlencode
&nbsp;
AWS_ACCESS_KEY_ID = <span style="color: #483d8b;">&quot;Your Access Key ID&quot;</span>
AWS_SECRET_ACCESS_KEY = <span style="color: #483d8b;">&quot;Your Secret Key&quot;</span>
&nbsp;
base_url = <span style="color: #483d8b;">&quot;http://ecs.amazonaws.com/onca/xml&quot;</span>
url_params = <span style="color: black;">&#123;</span><span style="color: #483d8b;">'Operation'</span>:<span style="color: #483d8b;">&quot;ItemSearch&quot;</span>,<span style="color: #483d8b;">'Service'</span>:<span style="color: #483d8b;">&quot;AWSECommerceService&quot;</span>,
 <span style="color: #483d8b;">'AWSAccessKeyId'</span>:AWS_ACCESS_KEY_ID,<span style="color: #483d8b;">'AssociateTag'</span>:<span style="color: #483d8b;">&quot;yourtag-10&quot;</span>,
 <span style="color: #483d8b;">'Version'</span>:<span style="color: #483d8b;">&quot;2006-09-11&quot;</span>,<span style="color: #483d8b;">'Availability'</span>:<span style="color: #483d8b;">&quot;Available&quot;</span>,<span style="color: #483d8b;">'Condition'</span>:<span style="color: #483d8b;">&quot;All&quot;</span>,
 <span style="color: #483d8b;">'ItemPage'</span>:<span style="color: #483d8b;">&quot;1&quot;</span>,<span style="color: #483d8b;">'ResponseGroup'</span>:<span style="color: #483d8b;">&quot;Images,ItemAttributes,EditorialReview&quot;</span>,
 <span style="color: #483d8b;">'Keywords'</span>:<span style="color: #483d8b;">&quot;Amazon&quot;</span><span style="color: black;">&#125;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># Add a ISO 8601 compliant timestamp (in GMT)</span>
url_params<span style="color: black;">&#91;</span><span style="color: #483d8b;">'Timestamp'</span><span style="color: black;">&#93;</span> = <span style="color: #dc143c;">time</span>.<span style="color: black;">strftime</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;%Y-%m-%dT%H:%M:%S&quot;</span>, <span style="color: #dc143c;">time</span>.<span style="color: black;">gmtime</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># Sort the URL parameters by key</span>
keys = url_params.<span style="color: black;">keys</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
keys.<span style="color: black;">sort</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
<span style="color: #808080; font-style: italic;"># Get the values in the same order of the sorted keys</span>
values = <span style="color: #008000;">map</span><span style="color: black;">&#40;</span>url_params.<span style="color: black;">get</span>, keys<span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># Reconstruct the URL paramters and encode them</span>
url_string = urlencode<span style="color: black;">&#40;</span> <span style="color: #008000;">zip</span><span style="color: black;">&#40;</span>keys,values<span style="color: black;">&#41;</span> <span style="color: black;">&#41;</span>
url_string = url_string.<span style="color: black;">replace</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'+'</span>,<span style="color: #483d8b;">&quot; &quot;</span><span style="color: black;">&#41;</span> 
url_string = url_string.<span style="color: black;">replace</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">':'</span>,<span style="color: #483d8b;">&quot;:&quot;</span><span style="color: black;">&#41;</span> 
&nbsp;
<span style="color: #808080; font-style: italic;">#Construct the string to sign</span>
string_to_sign = <span style="color: #483d8b;">&quot;&quot;&quot;GET
ecs.amazonaws.com
/onca/xml
%s&quot;&quot;&quot;</span> <span style="color: #66cc66;">%</span> url_string
&nbsp;
<span style="color: #808080; font-style: italic;"># Sign the request</span>
signature = <span style="color: #dc143c;">hmac</span>.<span style="color: #dc143c;">new</span><span style="color: black;">&#40;</span>
    key=AWS_SECRET_ACCESS_KEY,
    msg=string_to_sign,
    digestmod=hashlib.<span style="color: black;">sha256</span><span style="color: black;">&#41;</span>.<span style="color: black;">digest</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># Base64 encode the signature</span>
signature = <span style="color: #dc143c;">base64</span>.<span style="color: black;">encodestring</span><span style="color: black;">&#40;</span> signature <span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># Make the signature URL safe</span>
signature = signature.<span style="color: black;">replace</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'+'</span>,<span style="color: #483d8b;">'+'</span><span style="color: black;">&#41;</span>
signature = signature.<span style="color: black;">replace</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'='</span>,<span style="color: #483d8b;">'='</span><span style="color: black;">&#41;</span>
url_string += <span style="color: #483d8b;">&quot;&amp;Signature;=%s&quot;</span> <span style="color: #66cc66;">%</span> signature
<span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">&quot;%s?%s&quot;</span> <span style="color: #66cc66;">%</span> <span style="color: black;">&#40;</span>base_url,url_string<span style="color: black;">&#41;</span></pre></p>

<p>A few quick notes before moving on to the other examples. The timestamp here follows the <a href="http://en.wikipedia.org/wiki/ISO_8601" target="_blank" title="Wiki article on ISO 8061">ISO 8601 standard</a>. This standard does not require milliseconds or the terminating Z, but I have seen examples with and without each of these. I believe all of the following timestamps would be valid:
</p><ul>
<li>2009-07-25T07:31Z</li>
<li>2009-07-25T07:31:00Z</li> 
<li>2009-07-25T07:31:00.00000Z</li>
<li>2009-07-25T07:31</li>
<li>2009-07-25T07:31:00</li> 
<li>2009-07-25T07:31:00.00000</li>
</ul><p>
That said, the time format in the above example is known to work (we use it in production code, and I believe it&#8217;s the same time format used by <a href="http://code.google.com/p/boto/" target="_blank" title="Python AWS library">Boto</a>). The other issue I&#8217;d like to address is constructing the &#8220;string to sign&#8221;. This is a string which describes the request in a standardized way. The general format is:<br />
<pre class="html4strict code_block_class" style="font-family:monospace;">VERB
sub.domain.com
/api/path
param1=value1<span style="color: #ddbb00;">&amp;param2=value2&amp;...</span></pre><br />
The VERB is one of GET, PUT, DELETE, or POST (the HTTP REST verbs). Since the Products API is read-only, we will only be working with the GET verb. The base of the &#8220;string to sign&#8221; in the above example will be consistent for all Product Advertising API calls.<br />
<pre class="html4strict code_block_class" style="font-family:monospace;">GET
ecs.amazonaws.com
/onca/xml</pre>
</p><br/><p>
<strong>Python Resources</strong>
</p><ul>
<li>hmac library documentation <a href="http://docs.python.org/library/hmac.html" target="_blank">http://docs.python.org/library/hmac.html</a></li>
<li>base64 library documentation <a href="http://docs.python.org/library/base64.html" target="_blank">http://docs.python.org/library/base64.html</a></li>
<li>hashlib library documentation <a href="http://docs.python.org/library/hashlib.html" target="_blank">http://docs.python.org/library/hashlib.html</a></li>
</ul>
<br/>
<h3>PHP using built-in functions: hash_hmac, base64_encode</h3><p>
The PHP implementation is also pretty straightforward. I have seen some implementations that rely on additional packages install with Pear/Pecl, but I do not see the reasoning behind going outside of the standard library of functions.<br />
<pre class="php code_block_class" style="font-family:monospace;"><span style="color: #000088;">$AWS_ACCESS_KEY_ID</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;Your Access Key ID&quot;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$AWS_SECRET_ACCESS_KEY</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;Your Secret Key&quot;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000088;">$base_url</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;http://ecs.amazonaws.com/onca/xml&quot;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$url_params</span> <span style="color: #339933;">=</span> <a href="http://www.php.net/array"><span style="color: #990000;">array</span></a><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Operation'</span><span style="color: #339933;">=&gt;</span><span style="color: #0000ff;">&quot;ItemSearch&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">'Service'</span><span style="color: #339933;">=&gt;</span><span style="color: #0000ff;">&quot;AWSECommerceService&quot;</span><span style="color: #339933;">,</span>
 <span style="color: #0000ff;">'AWSAccessKeyId'</span><span style="color: #339933;">=&gt;</span><span style="color: #000088;">$AWS_ACCESS_KEY_ID</span><span style="color: #339933;">,</span><span style="color: #0000ff;">'AssociateTag'</span><span style="color: #339933;">=&gt;</span><span style="color: #0000ff;">&quot;yourtag-10&quot;</span><span style="color: #339933;">,</span>
 <span style="color: #0000ff;">'Version'</span><span style="color: #339933;">=&gt;</span><span style="color: #0000ff;">&quot;2006-09-11&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">'Availability'</span><span style="color: #339933;">=&gt;</span><span style="color: #0000ff;">&quot;Available&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">'Condition'</span><span style="color: #339933;">=&gt;</span><span style="color: #0000ff;">&quot;All&quot;</span><span style="color: #339933;">,</span>
 <span style="color: #0000ff;">'ItemPage'</span><span style="color: #339933;">=&gt;</span><span style="color: #0000ff;">&quot;1&quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">'ResponseGroup'</span><span style="color: #339933;">=&gt;</span><span style="color: #0000ff;">&quot;Images,ItemAttributes,EditorialReview&quot;</span><span style="color: #339933;">,</span>
 <span style="color: #0000ff;">'Keywords'</span><span style="color: #339933;">=&gt;</span><span style="color: #0000ff;">&quot;Amazon&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">// Add the Timestamp</span>
<span style="color: #000088;">$url_params</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'Timestamp'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <a href="http://www.php.net/gmdate"><span style="color: #990000;">gmdate</span></a><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;Y-m-d<span style="color: #000099; font-weight: bold;">\T</span>H:i:s.<span style="color: #000099; font-weight: bold;">\\</span>0<span style="color: #000099; font-weight: bold;">\\</span>0<span style="color: #000099; font-weight: bold;">\\</span>0<span style="color: #000099; font-weight: bold;">\\</span>Z&quot;</span><span style="color: #339933;">,</span> <a href="http://www.php.net/time"><span style="color: #990000;">time</span></a><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">// Sort the URL parameters</span>
<span style="color: #000088;">$url_parts</span> <span style="color: #339933;">=</span> <a href="http://www.php.net/array"><span style="color: #990000;">array</span></a><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #b1b100;">foreach</span><span style="color: #009900;">&#40;</span><a href="http://www.php.net/array_keys"><span style="color: #990000;">array_keys</span></a><span style="color: #009900;">&#40;</span><span style="color: #000088;">$url_params</span><span style="color: #009900;">&#41;</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$key</span><span style="color: #009900;">&#41;</span>
    <span style="color: #000088;">$url_parts</span><span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$key</span><span style="color: #339933;">.</span><span style="color: #0000ff;">&quot;=&quot;</span><span style="color: #339933;">.</span><span style="color: #000088;">$url_params</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$key</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
<a href="http://www.php.net/sort"><span style="color: #990000;">sort</span></a><span style="color: #009900;">&#40;</span><span style="color: #000088;">$url_parts</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">// Construct the string to sign</span>
<span style="color: #000088;">$string_to_sign</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;GET<span style="color: #000099; font-weight: bold;">\n</span>ecs.amazonaws.com<span style="color: #000099; font-weight: bold;">\n</span>/onca/xml<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">.</span><a href="http://www.php.net/implode"><span style="color: #990000;">implode</span></a><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;&amp;&quot;</span><span style="color: #339933;">,</span><span style="color: #000088;">$url_parts</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$string_to_sign</span> <span style="color: #339933;">=</span> <a href="http://www.php.net/str_replace"><span style="color: #990000;">str_replace</span></a><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'+'</span><span style="color: #339933;">,</span><span style="color: #0000ff;">'%20'</span><span style="color: #339933;">,</span><span style="color: #000088;">$string_to_sign</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$string_to_sign</span> <span style="color: #339933;">=</span> <a href="http://www.php.net/str_replace"><span style="color: #990000;">str_replace</span></a><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">':'</span><span style="color: #339933;">,</span><span style="color: #0000ff;">'%3A'</span><span style="color: #339933;">,</span><span style="color: #000088;">$string_to_sign</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$string_to_sign</span> <span style="color: #339933;">=</span> <a href="http://www.php.net/str_replace"><span style="color: #990000;">str_replace</span></a><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">';'</span><span style="color: #339933;">,</span><a href="http://www.php.net/urlencode"><span style="color: #990000;">urlencode</span></a><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">';'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span><span style="color: #000088;">$string_to_sign</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">// Sign the request</span>
<span style="color: #000088;">$signature</span> <span style="color: #339933;">=</span> <a href="http://www.php.net/hash_hmac"><span style="color: #990000;">hash_hmac</span></a><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;sha256&quot;</span><span style="color: #339933;">,</span><span style="color: #000088;">$string_to_sign</span><span style="color: #339933;">,</span><span style="color: #000088;">$AWS_SECRET_ACCESS_KEY</span><span style="color: #339933;">,</span><span style="color: #009900; font-weight: bold;">TRUE</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">// Base64 encode the signature and make it URL safe</span>
<span style="color: #000088;">$signature</span> <span style="color: #339933;">=</span> <a href="http://www.php.net/base64_encode"><span style="color: #990000;">base64_encode</span></a><span style="color: #009900;">&#40;</span>signature<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$signature</span> <span style="color: #339933;">=</span> <a href="http://www.php.net/str_replace"><span style="color: #990000;">str_replace</span></a><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'+'</span><span style="color: #339933;">,</span><span style="color: #0000ff;">'%2B'</span><span style="color: #339933;">,</span><span style="color: #000088;">$signature</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$signature</span> <span style="color: #339933;">=</span> <a href="http://www.php.net/str_replace"><span style="color: #990000;">str_replace</span></a><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'='</span><span style="color: #339933;">,</span><span style="color: #0000ff;">'%3D'</span><span style="color: #339933;">,</span><span style="color: #000088;">$signature</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000088;">$url_string</span> <span style="color: #339933;">=</span> <a href="http://www.php.net/implode"><span style="color: #990000;">implode</span></a><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;&amp;&quot;</span><span style="color: #339933;">,</span><span style="color: #000088;">$url_parts</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$url</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$base_url</span><span style="color: #339933;">.</span><span style="color: #000088;">$url_string</span><span style="color: #339933;">.</span><span style="color: #0000ff;">&quot;&amp;Signature=&quot;</span><span style="color: #339933;">.</span><span style="color: #000088;">$signature</span><span style="color: #339933;">;</span>
<span style="color: #b1b100;">print</span> <span style="color: #000088;">$url</span><span style="color: #339933;">;</span></pre></p>

<p><strong>PHP Resources</strong>
</p><ul>
<li>hash_hmac documentation <a href="http://us3.php.net/manual/en/function.hash-hmac.php" target="_blank">http://us3.php.net/manual/en/function.hash-hmac.php</a></li>
<li>base64_encode documentation <a href="http://us3.php.net/base64_encode" target="_blank">http://us3.php.net/base64_encode</a></li>
</ul>
<br/>
<h3>Visual Basic 6 *sigh*</h3><p>
This was one a beast. I&#8217;m not a VB expert, and never hope to be, but I can make my way around well enough. Like most VB developers, I spent hours scouring forums, reading expert sex change, and banging my head on my desk. The resulting code is far to verbose to post here, but I will provide an archive of the files I came up with along with a brief description.</p>

<p>Starting with the simplest, I made a Class Module called TimeStamp (here is the <a href="https://cloudcarpenters.s3.amazonaws.com/TimeStamp.cls" target="_blank">CLS file</a>). This was the fastest/easiest way I could figure out how to get an ISO 8601 timestamp. I imagine it could be done more elegantly, but that wasn&#8217;t my goal. </p>

<p>Next are two files I found and imported with minimal modification: Base64 and CSHA256 (<a href="https://cloudcarpenters.s3.amazonaws.com/Base64.bas" target="_blank">BAS file</a> and <a href="https://cloudcarpenters.s3.amazonaws.com/CSHA256.cls" target="_blank">CLS file</a>, respectively). The former is a Base64 encode/decoder and the latter is a pure VB6 implementation of the SHA-256 hashing algorithm. Without these two files, none of this is remotely possible - mad props (and condolences) to the person who wrote CSHA256. </p>

<p>The CSHA256 file does require one modification. In the <code>ConvertToWordArray</code> function change <code>AscB</code> to <code>Asc</code>
</p><pre style="padding-left:20px;">
lByte = AscB(Mid(sMessage, lByteCount + 1, 1))
lByte = Asc(Mid(sMessage, lByteCount + 1, 1))
</pre><p>
The final file glues it all together: HMAC_SHA256 (dunno why I named it that). Here is the <a href="https://cloudcarpenters.s3.amazonaws.com/HMAC_SHA256.bas" target="_blank">BAS file</a>. The only function you need to worry about in here is <code>signEncode</code>. Here is how it is used:<br />
<pre class="vb code_block_class" style="font-family:monospace;"><span style="color: #000080;">Dim</span> URL <span style="color: #000080;">As</span> <span style="color: #000080;">String</span>
<span style="color: #000080;">Dim</span> AWSAccessKeyId <span style="color: #000080;">As</span> <span style="color: #000080;">String</span>
<span style="color: #000080;">Dim</span> AWSSecretAccessKey <span style="color: #000080;">As</span> <span style="color: #000080;">String</span>
<span style="color: #000080;">Dim</span> ts <span style="color: #000080;">As</span> TimeStamp
<span style="color: #000080;">Set</span> AWSAccessKeyId = <span style="color: #800000;">&quot;Your AWS Access Key Id&quot;</span>
<span style="color: #000080;">Set</span> AWSSecretAccessKey = <span style="color: #800000;">&quot;Your AWS Secret Access Key&quot;</span>
<span style="color: #000080;">Set</span> ts = <span style="color: #000080;">New</span> TimeStamp
URL = <span style="color: #800000;">&quot;http://ecs.amazonaws.com/onca/xml?Service=AWSEcommerceService&quot;</span> &amp;_ 
    <span style="color: #800000;">&quot;&amp;Timestamp=&quot;</span> &amp; ts.getIsoTimestamp() &amp; <span style="color: #800000;">&quot;&amp;Operation=ItemSearch&amp;&quot;</span> &amp; _
    <span style="color: #800000;">&quot;&amp;Service=AWSECommerceService&amp;AWSAccessKeyId=&quot;</span> &amp; AWSAccessKeyId &amp; _
    <span style="color: #800000;">&quot;&amp;AssociateTag=yourtag-10&amp;Version=2006-09-11&amp;Availability=Available&quot;</span> &amp; _
    <span style="color: #800000;">&quot;&amp;Condition=All&amp;ItemPage=1&amp;ResponseGroup=Images,ItemAttributes,EditorialReview&quot;</span> &amp; _
    <span style="color: #800000;">&quot;&amp;Keywords=Amazon&quot;</span>
URL = signEncode(URL)
MsgBox URL</pre><br />
The <code>signEncode</code> function does pretty much everything. It first separates the base URL from the request parameters, then sorts the parameters and calculates the signature. I had to fiddle around with it for a while before I found an issue with the Base64 encoding. I can&#8217;t take any credit for any of this really since I just gathered all the pieces and put them together. However, I hope this compilation of files and explanation will be useful.
</p><br/><p>
<strong>Visual Basic Resources</strong>
</p><ul>
<li>AWS Community Forums Thread (where most of this code comes from): <a href="http://developer.amazonwebservices.com/connect/thread.jspa?threadID=33204&amp;start=0&amp;tstart=0" target="_blank">http://developer.amazonwebservices.com/connect/thread.jspa?threadID=33204&amp;start=0&amp;tstart=0</a></li>
<li>Base64 Encoder/Decoder <a href="http://www.source-code.biz/snippets/vbasic/12.htm" target="_blank">http://www.source-code.biz/snippets/vbasic/12.htm</a></li>
<li>CSHA256 Class <a href="http://www.freevbcode.com/ShowCode.asp?ID=2565" target="_blank">http://www.freevbcode.com/ShowCode.asp?ID=2565</a></li>
<li>HexString2Bin Function <a href="http://www.experts-exchange.com/Programming/Programming_Languages/Visual_Basic/Q_21330788.html" target="_blank">http://www.experts-exchange.com/Programming/Programming_Languages/Visual_Basic/Q_21330788.html</a></li>
<li>Zip Archive of everything you need <a href="https://cloudcarpenters.s3.amazonaws.com/Amazon_request_signing.zip" target="_blank">Amazon_request_signing.zip</a></li>
</ul>
<br/><p>
<strong>Other Amazon Resources</strong>
</p><ul>
<li>Amazon Product Advertising API FAQ <a href="https://affiliate-program.amazon.com/gp/advertising/api/detail/faq.html" target="_blank">https://affiliate-program.amazon.com/gp/advertising/api/detail/faq.html</a></li>
<li>Request signing sandbox <a href="http://associates-amazon.s3.amazonaws.com/signed-requests/helper/index.html" target="_blank">http://associates-amazon.s3.amazonaws.com/signed-requests/helper/index.html</a></li>
<li>Product Advertising API Documentation <a href="http://docs.amazonwebservices.com/AWSECommerceService/2009-07-01/DG/" target="_blank">http://docs.amazonwebservices.com/AWSECommerceService/2009-07-01/DG/</a></li>
</ul>
<br/><p>
There you have it. Amazon Product Advertising API request signing in three languages: Python, PHP, and Visual Basic 6. Enjoy!</p>

<p>-David</p>


      ]]></content>
    </entry>

    <entry>
      <title>SimpleDB Primer with Python and Boto</title>
      <link rel="alternate" type="text/html" href="http://cloudcarpenters.com/site/simpledb_primer_with_python_and_boto/" />
      <id>tag:cloudcarpenters.com,2009:/2.15</id>
      <published>2009-06-12T17:49:01Z</published>
      <updated>2009-07-27T15:39:02Z</updated>
      <author>
            <name>david</name>
            <email>mumrah@gmail.com</email>
                  </author>

      <category term="Tutorials"
        scheme="http://cloudcarpenters.com/site/category/Tutorials/"
        label="Tutorials" />
      <content type="html"><![CDATA[
        <p><a href="http://aws.amazon.com/simpledb/" target="_blank" title="SimpleDB">SimpleDB</a> is Amazon's distributed, highly-available, super-awesome database system which runs on Amazon's cloud. It does not function or behave like a database in a traditional sense - it is more akin to a spreadsheet (Excel or OpenOffice Calc). It is, in fact, Schema-less. It is without Schema. You simply have Items which have key/value pairs. Items are grouped together into Domains, and an Item can have many Attributes (keys) and each Attribute can hold multiple Values. I know it's sort of confusing, so let's have an example. Consider the following data set:</p>
<div style="text-align: center"><img src="http://cloudcarpenters-cdn.s3.amazonaws.com/blog/dxhgtqb_36c9z93sfm_b.png" style="width: 640px; height: 133px"></div><br/>
<p>We have 6 <em>Items</em> in a <em>Domain</em> called <strong>test&ndash;domain</strong>, and each Item has a name that is unique (this is the only requirement for Items in SimpleDB). We have defined four <em>Attributes</em> which will hold the data for these Items, however none of these Attributes are required. In fact, you cannot specify a required Attribute in SimpleDB (if you need this functionality it must be imposed on the application side).</p>
<p>Keep in mind, we have no Schema. This can be a difficult notion for database-savvy people to come to terms with, but it is a key part of what makes SimpleDB so great and so flexible.</p>
<p>Let's get on with the example. The following code creates a connection to SimpleDB and selects the <strong>test&ndash;domain</strong> Domain and inserts a few Items into it. Before you can do anything with SimpleDB, you need to have an <a href="http://aws.amazon.com/" target="_blank" title="AWS Homepage">AWS account</a> and opt-in for access to SimpleDB. This takes only a moment, but I'm not waiting. Moving on.</p>

 <pre class="python code_block_class" style="font-family:monospace;"><span style="color: #808080; font-style: italic;"># Make the connection</span>
<span style="color: #ff7700;font-weight:bold;">import</span> boto
conn = boto.<span style="color: black;">connect_sdb</span><span style="color: black;">&#40;</span>aws_access_key_id,aws_secret_access_key<span style="color: black;">&#41;</span>
domain = conn.<span style="color: black;">get_domain</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'test-domain'</span><span style="color: black;">&#41;</span>
<span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #ff7700;font-weight:bold;">not</span> domain:
 domain = conn.<span style="color: black;">create_domain</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'test-domain'</span><span style="color: black;">&#41;</span></pre>


<pre class="python code_block_class" style="font-family:monospace;"><span style="color: #808080; font-style: italic;"># Define our data set</span>
data = <span style="color: black;">&#123;</span><span style="color: black;">&#125;</span>
data<span style="color: black;">&#91;</span><span style="color: #483d8b;">'some-item'</span><span style="color: black;">&#93;</span>   = <span style="color: black;">&#123;</span><span style="color: #483d8b;">'color'</span>:<span style="color: #483d8b;">'blue'</span>,<span style="color: #483d8b;">'price'</span>:<span style="color: #ff4500;">10</span>,<span style="color: #483d8b;">'size'</span>:<span style="color: #483d8b;">'small'</span><span style="color: black;">&#125;</span>
data<span style="color: black;">&#91;</span><span style="color: #483d8b;">'some-other-item'</span><span style="color: black;">&#93;</span> = <span style="color: black;">&#123;</span><span style="color: #483d8b;">'color'</span>:<span style="color: #483d8b;">'red'</span>,<span style="color: #483d8b;">'price'</span>:<span style="color: #ff4500;">15</span>,<span style="color: #483d8b;">'size'</span>:<span style="color: #483d8b;">'medium'</span><span style="color: black;">&#125;</span>
data<span style="color: black;">&#91;</span><span style="color: #483d8b;">'bicolored'</span><span style="color: black;">&#93;</span>    = <span style="color: black;">&#123;</span><span style="color: #483d8b;">'color'</span>:<span style="color: black;">&#91;</span><span style="color: #483d8b;">'blue'</span>,<span style="color: #483d8b;">'green'</span><span style="color: black;">&#93;</span>,<span style="color: #483d8b;">'price'</span>:<span style="color: #ff4500;">15</span>,<span style="color: #483d8b;">'size'</span>:<span style="color: #483d8b;">'small'</span><span style="color: black;">&#125;</span>
data<span style="color: black;">&#91;</span><span style="color: #483d8b;">'tricolored'</span><span style="color: black;">&#93;</span>   = <span style="color: black;">&#123;</span><span style="color: #483d8b;">'color'</span>:<span style="color: black;">&#91;</span><span style="color: #483d8b;">'red'</span>,<span style="color: #483d8b;">'blue'</span>,<span style="color: #483d8b;">'green'</span><span style="color: black;">&#93;</span>,<span style="color: #483d8b;">'price'</span>:<span style="color: #ff4500;">20</span>,<span style="color: #483d8b;">'size'</span>:<span style="color: #483d8b;">'medium'</span><span style="color: black;">&#125;</span>
data<span style="color: black;">&#91;</span><span style="color: #483d8b;">'nocolor'</span><span style="color: black;">&#93;</span>   = <span style="color: black;">&#123;</span><span style="color: #483d8b;">'price'</span>:<span style="color: #ff4500;">10</span>,<span style="color: #483d8b;">'size'</span>:<span style="color: #483d8b;">'small'</span><span style="color: black;">&#125;</span>
data<span style="color: black;">&#91;</span><span style="color: #483d8b;">'another-color'</span><span style="color: black;">&#93;</span> = <span style="color: black;">&#123;</span><span style="color: #483d8b;">'color'</span>:<span style="color: #483d8b;">'purple'</span>,<span style="color: #483d8b;">'price'</span>:<span style="color: #ff4500;">5</span>,<span style="color: #483d8b;">'size'</span>:<span style="color: #483d8b;">'tiny'</span>,
  <span style="color: #483d8b;">'comment'</span>:<span style="color: #483d8b;">'This one is really small'</span><span style="color: black;">&#125;</span></pre>
<pre class="python code_block_class" style="font-family:monospace;"><span style="color: #808080; font-style: italic;"># Insert the items</span>
<span style="color: #ff7700;font-weight:bold;">for</span> name,d <span style="color: #ff7700;font-weight:bold;">in</span> data.<span style="color: black;">items</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
 item = domain.<span style="color: black;">new_item</span><span style="color: black;">&#40;</span>name<span style="color: black;">&#41;</span>
 <span style="color: #ff7700;font-weight:bold;">for</span> k,v <span style="color: #ff7700;font-weight:bold;">in</span> d.<span style="color: black;">items</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
  item<span style="color: black;">&#91;</span>k<span style="color: black;">&#93;</span> = v
 item.<span style="color: black;">save</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre>

<p>Now that we have some data to play with, let's run some queries on it. In Boto, we are given interfaces to the two methods for getting data out of SimpleDB: <strong>Select</strong> and <strong>Query</strong>. As of the release of the 2009-04-15 SimpleDB API, Query has been deprecated in favor of Select. We will be using Select for the examples in this tutorial. Right on - let's see a query.</p>

<pre class="python code_block_class" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">for</span> item <span style="color: #ff7700;font-weight:bold;">in</span> domain.<span style="color: #dc143c;">select</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;SELECT * FROM `test-domain`&quot;</span><span style="color: black;">&#41;</span>:
 <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">&quot;&gt;&gt;&quot;</span>,item.<span style="color: black;">name</span>,item
&nbsp;
<span style="color: #66cc66;">&gt;&gt;</span> bicolored <span style="color: black;">&#123;</span>u<span style="color: #483d8b;">'color'</span>: <span style="color: black;">&#91;</span>u<span style="color: #483d8b;">'green'</span>, u<span style="color: #483d8b;">'blue'</span><span style="color: black;">&#93;</span>, u<span style="color: #483d8b;">'price'</span>: u<span style="color: #483d8b;">'15'</span>, u<span style="color: #483d8b;">'size'</span>: u<span style="color: #483d8b;">'small'</span><span style="color: black;">&#125;</span>
<span style="color: #66cc66;">&gt;&gt;</span> some-other-item <span style="color: black;">&#123;</span>u<span style="color: #483d8b;">'color'</span>: u<span style="color: #483d8b;">'red'</span>, u<span style="color: #483d8b;">'price'</span>: u<span style="color: #483d8b;">'15'</span>, u<span style="color: #483d8b;">'size'</span>: u<span style="color: #483d8b;">'medium'</span><span style="color: black;">&#125;</span>
<span style="color: #66cc66;">&gt;&gt;</span> nocolor <span style="color: black;">&#123;</span>u<span style="color: #483d8b;">'price'</span>: u<span style="color: #483d8b;">'10'</span>, u<span style="color: #483d8b;">'size'</span>: u<span style="color: #483d8b;">'small'</span><span style="color: black;">&#125;</span>
<span style="color: #66cc66;">&gt;&gt;</span> some-item <span style="color: black;">&#123;</span>u<span style="color: #483d8b;">'color'</span>: u<span style="color: #483d8b;">'blue'</span>, u<span style="color: #483d8b;">'price'</span>: u<span style="color: #483d8b;">'10'</span>, u<span style="color: #483d8b;">'size'</span>: u<span style="color: #483d8b;">'small'</span><span style="color: black;">&#125;</span>
<span style="color: #66cc66;">&gt;&gt;</span> another-color <span style="color: black;">&#123;</span>u<span style="color: #483d8b;">'color'</span>: u<span style="color: #483d8b;">'purple'</span>, u<span style="color: #483d8b;">'price'</span>: u<span style="color: #483d8b;">'5'</span>, u<span style="color: #483d8b;">'size'</span>: u<span style="color: #483d8b;">'tiny'</span>, 
  u<span style="color: #483d8b;">'comment'</span>:u<span style="color: #483d8b;">'This one is really small'</span><span style="color: black;">&#125;</span>
<span style="color: #66cc66;">&gt;&gt;</span> tricolored <span style="color: black;">&#123;</span>u<span style="color: #483d8b;">'color'</span>: <span style="color: black;">&#91;</span>u<span style="color: #483d8b;">'green'</span>, u<span style="color: #483d8b;">'blue'</span>, u<span style="color: #483d8b;">'red'</span><span style="color: black;">&#93;</span>, u<span style="color: #483d8b;">'price'</span>: u<span style="color: #483d8b;">'20'</span>, 
  u<span style="color: #483d8b;">'size'</span>: u<span style="color: #483d8b;">'medium'</span><span style="color: black;">&#125;</span></pre>

<p>Notice the syntax of Select is SQL-like. It is not SQL per se, but it has been designed to be very similar. There are no JOINs, UNIONs, or RDBMS things like this. Since SimpleDB is not relational, there is no need to support relational type queries like JOINs. Although relational database behavior can be emulated with SimpleDB, it is not recommended. I believe Amazon has intentionally left this and other features to keep SimpleDB nice and fast and, well, simple.</p>

<p>Let's get down to some serious querying, shall we.</p>

<h3>Predicate Statements</h3>
<p>In SimpleDB, most of the work is done in the predicate statements. SimpleDB supports most <a id="sdpw" href="http://docs.amazonwebservices.com/AmazonSimpleDB/2009-04-15/DeveloperGuide/UsingSelectOperators.html" target="_blank" title="SimpleDB documentation - Comparison Operators">common comparison operators</a> (equals, less than, etc) as well as a few special ones. A few examples will demonstrate how this works better than words.</p>
<div>Single predicate</div>
<pre class="python code_block_class" style="font-family:monospace;">SELECT <span style="color: #66cc66;">*</span> FROM <span style="color: #66cc66;">`</span>test-domain<span style="color: #66cc66;">`</span> WHERE <span style="color: #66cc66;">`</span>size<span style="color: #66cc66;">`</span> = <span style="color: #483d8b;">'small'</span>
&nbsp;
<span style="color: #66cc66;">&gt;&gt;</span> bicolored <span style="color: black;">&#123;</span>u<span style="color: #483d8b;">'color'</span>: <span style="color: black;">&#91;</span>u<span style="color: #483d8b;">'green'</span>, u<span style="color: #483d8b;">'blue'</span><span style="color: black;">&#93;</span>, u<span style="color: #483d8b;">'price'</span>: u<span style="color: #483d8b;">'15'</span>, u<span style="color: #483d8b;">'size'</span>: u<span style="color: #483d8b;">'small'</span><span style="color: black;">&#125;</span>
<span style="color: #66cc66;">&gt;&gt;</span> nocolor <span style="color: black;">&#123;</span>u<span style="color: #483d8b;">'price'</span>: u<span style="color: #483d8b;">'10'</span>, u<span style="color: #483d8b;">'size'</span>: u<span style="color: #483d8b;">'small'</span><span style="color: black;">&#125;</span>
<span style="color: #66cc66;">&gt;&gt;</span> some-item <span style="color: black;">&#123;</span>u<span style="color: #483d8b;">'color'</span>: u<span style="color: #483d8b;">'blue'</span>, u<span style="color: #483d8b;">'price'</span>: u<span style="color: #483d8b;">'10'</span>, u<span style="color: #483d8b;">'size'</span>: u<span style="color: #483d8b;">'small'</span><span style="color: black;">&#125;</span></pre>
<div>Multiple predicates on one Attribute - this is like a union.</div>
<pre class="python code_block_class" style="font-family:monospace;">SELECT <span style="color: #66cc66;">*</span> FROM <span style="color: #66cc66;">`</span>test-domain<span style="color: #66cc66;">`</span> WHERE <span style="color: #66cc66;">`</span>size<span style="color: #66cc66;">`</span> = <span style="color: #483d8b;">'small'</span> OR <span style="color: #66cc66;">`</span>size<span style="color: #66cc66;">`</span>=<span style="color: #483d8b;">'tiny'</span>
&nbsp;
<span style="color: #66cc66;">&gt;&gt;</span> bicolored <span style="color: black;">&#123;</span>u<span style="color: #483d8b;">'color'</span>: <span style="color: black;">&#91;</span>u<span style="color: #483d8b;">'green'</span>, u<span style="color: #483d8b;">'blue'</span><span style="color: black;">&#93;</span>, u<span style="color: #483d8b;">'price'</span>: u<span style="color: #483d8b;">'15'</span>, u<span style="color: #483d8b;">'size'</span>: u<span style="color: #483d8b;">'small'</span><span style="color: black;">&#125;</span>
<span style="color: #66cc66;">&gt;&gt;</span> nocolor <span style="color: black;">&#123;</span>u<span style="color: #483d8b;">'price'</span>: u<span style="color: #483d8b;">'10'</span>, u<span style="color: #483d8b;">'size'</span>: u<span style="color: #483d8b;">'small'</span><span style="color: black;">&#125;</span>
<span style="color: #66cc66;">&gt;&gt;</span> some-item <span style="color: black;">&#123;</span>u<span style="color: #483d8b;">'color'</span>: u<span style="color: #483d8b;">'blue'</span>, u<span style="color: #483d8b;">'price'</span>: u<span style="color: #483d8b;">'10'</span>, u<span style="color: #483d8b;">'size'</span>: u<span style="color: #483d8b;">'small'</span><span style="color: black;">&#125;</span>
<span style="color: #66cc66;">&gt;&gt;</span> another-color <span style="color: black;">&#123;</span>u<span style="color: #483d8b;">'color'</span>: u<span style="color: #483d8b;">'purple'</span>, u<span style="color: #483d8b;">'price'</span>: u<span style="color: #483d8b;">'5'</span>, u<span style="color: #483d8b;">'size'</span>: u<span style="color: #483d8b;">'tiny'</span>, 
  u<span style="color: #483d8b;">'comment'</span>:u<span style="color: #483d8b;">'This one is really small'</span><span style="color: black;">&#125;</span></pre>
<div>Multiple predicates on two Attributes - this is like an intersection</div>
<pre class="python code_block_class" style="font-family:monospace;">SELECT <span style="color: #66cc66;">*</span> FROM <span style="color: #66cc66;">`</span>test-domain<span style="color: #66cc66;">`</span> WHERE <span style="color: #66cc66;">`</span>size<span style="color: #66cc66;">`</span> = <span style="color: #483d8b;">'small'</span> AND <span style="color: #66cc66;">`</span>color<span style="color: #66cc66;">`</span>=<span style="color: #483d8b;">'blue'</span>
&nbsp;
<span style="color: #66cc66;">&gt;&gt;</span> bicolored <span style="color: black;">&#123;</span>u<span style="color: #483d8b;">'color'</span>: <span style="color: black;">&#91;</span>u<span style="color: #483d8b;">'green'</span>, u<span style="color: #483d8b;">'blue'</span><span style="color: black;">&#93;</span>, u<span style="color: #483d8b;">'price'</span>: u<span style="color: #483d8b;">'15'</span>, u<span style="color: #483d8b;">'size'</span>: u<span style="color: #483d8b;">'small'</span><span style="color: black;">&#125;</span>
<span style="color: #66cc66;">&gt;&gt;</span> some-item <span style="color: black;">&#123;</span>u<span style="color: #483d8b;">'color'</span>: u<span style="color: #483d8b;">'blue'</span>, u<span style="color: #483d8b;">'price'</span>: u<span style="color: #483d8b;">'10'</span>, u<span style="color: #483d8b;">'size'</span>: u<span style="color: #483d8b;">'small'</span><span style="color: black;">&#125;</span></pre>
<div>Single multi-valued predicate</div>
<pre class="python code_block_class" style="font-family:monospace;">SELECT <span style="color: #66cc66;">*</span> FROM <span style="color: #66cc66;">`</span>test-domain<span style="color: #66cc66;">`</span> WHERE <span style="color: #66cc66;">`</span>color<span style="color: #66cc66;">`</span> IN <span style="color: black;">&#40;</span><span style="color: #483d8b;">'red'</span>,<span style="color: #483d8b;">'blue'</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #66cc66;">&gt;&gt;</span> bicolored <span style="color: black;">&#123;</span>u<span style="color: #483d8b;">'color'</span>: <span style="color: black;">&#91;</span>u<span style="color: #483d8b;">'green'</span>, u<span style="color: #483d8b;">'blue'</span><span style="color: black;">&#93;</span>, u<span style="color: #483d8b;">'price'</span>: u<span style="color: #483d8b;">'15'</span>, u<span style="color: #483d8b;">'size'</span>: u<span style="color: #483d8b;">'small'</span><span style="color: black;">&#125;</span>
<span style="color: #66cc66;">&gt;&gt;</span> some-item <span style="color: black;">&#123;</span>u<span style="color: #483d8b;">'color'</span>: u<span style="color: #483d8b;">'blue'</span>, u<span style="color: #483d8b;">'price'</span>: u<span style="color: #483d8b;">'10'</span>, u<span style="color: #483d8b;">'size'</span>: u<span style="color: #483d8b;">'small'</span><span style="color: black;">&#125;</span>
<span style="color: #66cc66;">&gt;&gt;</span> tricolored <span style="color: black;">&#123;</span>u<span style="color: #483d8b;">'color'</span>: <span style="color: black;">&#91;</span>u<span style="color: #483d8b;">'green'</span>, u<span style="color: #483d8b;">'blue'</span>, u<span style="color: #483d8b;">'red'</span><span style="color: black;">&#93;</span>, u<span style="color: #483d8b;">'price'</span>: u<span style="color: #483d8b;">'20'</span>, 
  u<span style="color: #483d8b;">'size'</span>: u<span style="color: #483d8b;">'medium'</span><span style="color: black;">&#125;</span>
<span style="color: #66cc66;">&gt;&gt;</span> some-other-item <span style="color: black;">&#123;</span>u<span style="color: #483d8b;">'color'</span>: u<span style="color: #483d8b;">'red'</span>, u<span style="color: #483d8b;">'price'</span>: u<span style="color: #483d8b;">'15'</span>, u<span style="color: #483d8b;">'size'</span>: u<span style="color: #483d8b;">'medium'</span><span style="color: black;">&#125;</span></pre>

<div>Single predicate on a multi-valued Attribute using every()&nbsp;</div>
<pre class="python code_block_class" style="font-family:monospace;">SELECT <span style="color: #66cc66;">*</span> FROM <span style="color: #66cc66;">`</span>test-domain<span style="color: #66cc66;">`</span> WHERE every<span style="color: black;">&#40;</span><span style="color: #66cc66;">`</span>color<span style="color: #66cc66;">`</span><span style="color: black;">&#41;</span> = <span style="color: #483d8b;">'red'</span>
&nbsp;
<span style="color: #66cc66;">&gt;&gt;</span> some-other-item <span style="color: black;">&#123;</span>u<span style="color: #483d8b;">'color'</span>: u<span style="color: #483d8b;">'red'</span>, u<span style="color: #483d8b;">'price'</span>: u<span style="color: #483d8b;">'15'</span>, u<span style="color: #483d8b;">'size'</span>: u<span style="color: #483d8b;">'medium'</span><span style="color: black;">&#125;</span></pre>

<div>Single multi-valued predicate on a multi-valued Attribute using every()</div>
<pre class="python code_block_class" style="font-family:monospace;">SELECT <span style="color: #66cc66;">*</span> FROM <span style="color: #66cc66;">`</span>test-domain<span style="color: #66cc66;">`</span> WHERE every<span style="color: black;">&#40;</span><span style="color: #66cc66;">`</span>color<span style="color: #66cc66;">`</span><span style="color: black;">&#41;</span> IN <span style="color: black;">&#40;</span><span style="color: #483d8b;">'red'</span>,<span style="color: #483d8b;">'blue'</span><span style="color: black;">&#41;</span><span style="color: #483d8b;">&quot;
&nbsp;
&gt;&gt; some-item {u'color': u'blue', u'price': u'10', u'size': u'small'}
&gt;&gt; some-other-item {u'color': u'red', u'price': u'15', u'size': u'medium'}</span></pre>

<h3>Sorting</h3>
<div>Sorting can be a little strange. Let's look at our data set sorted by price in descending order.</div>
<pre class="python code_block_class" style="font-family:monospace;">SELECT <span style="color: #66cc66;">*</span> FROM <span style="color: #66cc66;">`</span>test-domain<span style="color: #66cc66;">`</span> WHERE <span style="color: #66cc66;">`</span>price<span style="color: #66cc66;">`</span> <span style="color: #66cc66;">!</span>= <span style="color: #483d8b;">''</span> ORDER BY <span style="color: #66cc66;">`</span>price<span style="color: #66cc66;">`</span> DESC
&nbsp;
<span style="color: #66cc66;">&gt;&gt;</span> another-color <span style="color: black;">&#123;</span>u<span style="color: #483d8b;">'color'</span>: u<span style="color: #483d8b;">'purple'</span>, u<span style="color: #483d8b;">'price'</span>: u<span style="color: #483d8b;">'5'</span>, u<span style="color: #483d8b;">'size'</span>: u<span style="color: #483d8b;">'tiny'</span>, 
  u<span style="color: #483d8b;">'comment'</span>:u<span style="color: #483d8b;">'This one is really small'</span><span style="color: black;">&#125;</span>
<span style="color: #66cc66;">&gt;&gt;</span> tricolored <span style="color: black;">&#123;</span>u<span style="color: #483d8b;">'color'</span>: <span style="color: black;">&#91;</span>u<span style="color: #483d8b;">'green'</span>, u<span style="color: #483d8b;">'blue'</span>, u<span style="color: #483d8b;">'red'</span><span style="color: black;">&#93;</span>, u<span style="color: #483d8b;">'price'</span>: u<span style="color: #483d8b;">'20'</span>, 
  u<span style="color: #483d8b;">'size'</span>: u<span style="color: #483d8b;">'medium'</span><span style="color: black;">&#125;</span>
<span style="color: #66cc66;">&gt;&gt;</span> some-other-item <span style="color: black;">&#123;</span>u<span style="color: #483d8b;">'color'</span>: u<span style="color: #483d8b;">'red'</span>, u<span style="color: #483d8b;">'price'</span>: u<span style="color: #483d8b;">'15'</span>, u<span style="color: #483d8b;">'size'</span>: u<span style="color: #483d8b;">'medium'</span><span style="color: black;">&#125;</span>
<span style="color: #66cc66;">&gt;&gt;</span> bicolored <span style="color: black;">&#123;</span>u<span style="color: #483d8b;">'color'</span>: <span style="color: black;">&#91;</span>u<span style="color: #483d8b;">'green'</span>, u<span style="color: #483d8b;">'blue'</span><span style="color: black;">&#93;</span>, u<span style="color: #483d8b;">'price'</span>: u<span style="color: #483d8b;">'15'</span>, u<span style="color: #483d8b;">'size'</span>: u<span style="color: #483d8b;">'small'</span><span style="color: black;">&#125;</span>
<span style="color: #66cc66;">&gt;&gt;</span> some-item <span style="color: black;">&#123;</span>u<span style="color: #483d8b;">'color'</span>: u<span style="color: #483d8b;">'blue'</span>, u<span style="color: #483d8b;">'price'</span>: u<span style="color: #483d8b;">'10'</span>, u<span style="color: #483d8b;">'size'</span>: u<span style="color: #483d8b;">'small'</span><span style="color: black;">&#125;</span>
<span style="color: #66cc66;">&gt;&gt;</span> nocolor <span style="color: black;">&#123;</span>u<span style="color: #483d8b;">'price'</span>: u<span style="color: #483d8b;">'10'</span>, u<span style="color: #483d8b;">'size'</span>: u<span style="color: #483d8b;">'small'</span><span style="color: black;">&#125;</span></pre>

<p>Wait, wait. That's not right. Last time I checked, five was certainly less than 20. This is unexpected, but completely correct. SimpleDB does all sorting lexicographically becaue (pay attention): <strong>everything in SimpleDB is a string</strong>. No numbers, no timestamps, none of that mess - only strings (and Unicode strings at that). It's hard to get used to, but not having data types is truly wonderful. I won't cover all of the details about <a href="http://docs.amazonwebservices.com/AmazonSimpleDB/2009-04-15/DeveloperGuide/NumericalData.html" target="_blank" title="SimpleDB Documentation - Numeric Data">numeric data in SimpleDB</a>, but I will say that you need to zero-pad the strings if you want to sort them numerically. In other words, '5' should be '05' or '005' depending on how many digits you need.</p>

<blockquote style="font-size:0.8em;">
 <h3>Aside</h3>
<p>A super easy way to zero-pad your strings in python is to use string formating. The only catch is you need to know roughly how large the numbers will get. For example, if you're doing dollar amounts for a store that sells ballons, 4 or 5 digits should be sufficient.</p>
<pre class="python code_block_class" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> x = <span style="color: #ff4500;">10</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #483d8b;">&quot;d&quot;</span> <span style="color: #66cc66;">%</span> x <span style="color: #808080; font-style: italic;">#zero-pad a 5 digit integer</span>
<span style="color: #483d8b;">'00010'</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #483d8b;">&quot;.2f&quot;</span> <span style="color: #66cc66;">%</span> x <span style="color: #808080; font-style: italic;">#zero-pad an 8 digit float with precision 2</span>
<span style="color: #483d8b;">'00010.00'</span></pre>
<p>There's another easy mistake when sorting in SimpleDB. Whichever Attribute you are sorting by must be included in at least one predicate statement. This ensures the returned set of Items has the Attribute required for sorting. If an Item does not have the required Attribute (price in our example) then it is not included in the returned set. There are no explicit NULLs in SimpleDB - if an Item does not have a certain Attribute, that Attribute IS NULL.</p>
</blockquote>

<h3>Counting</h3>
<pre class="python code_block_class" style="font-family:monospace;">SELECT count<span style="color: black;">&#40;</span><span style="color: #66cc66;">*</span><span style="color: black;">&#41;</span> FROM <span style="color: #66cc66;">`</span>test-domain<span style="color: #66cc66;">`</span> WHERE <span style="color: #66cc66;">`</span>color<span style="color: #66cc66;">`</span> IN <span style="color: black;">&#40;</span><span style="color: #483d8b;">'blue'</span>,<span style="color: #483d8b;">'red'</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #66cc66;">&gt;&gt;</span> Domain <span style="color: black;">&#123;</span>u<span style="color: #483d8b;">'Count'</span>: u<span style="color: #483d8b;">'5'</span><span style="color: black;">&#125;</span>
&nbsp;</pre>

<h3>Limiting</h3>
<p>Limiting your queries is a little strange. Basically, if you add a LIMIT clause to your query, that just tells SimpleDB how many results per page you want. This discussion really goes beyond the scope of this tutorial, but I'll just say you need to limit results on the application side. This is the only real problem with SimpleDB I've found so far. Watch <a href="http://groups.google.com/group/boto-users/browse_frm/thread/2a627fd9962e5464" title="Boto-users Google Group" target="_blank">this thread</a> on the boto-user's Google Group page for a more detailed discussion and a possible workaround.</p>

<h3>Highlights</h3>
<ul><li>SimpleDB uses a <a id="mu08" href="http://docs.amazonwebservices.com/AmazonSimpleDB/2009-04-15/DeveloperGuide/SimpleQueriesSelect.html" target="_blank" title="SimpleDB Documentation - Simple Queries">SQL-like Select language</a></li>
<li>Domains have Items, Items have Attributes, Attributes have Values (one or many)</li>
<li>Everything is a string, so remember to <a id="qyma" href="http://docs.amazonwebservices.com/AmazonSimpleDB/2009-04-15/DeveloperGuide/ZeroPadding.html" target="_blank" title="SimpleDB Documentation - Zero-padding Numbers">zero-pad your numbers</a></li>
<li>To <a id="r:25" href="http://docs.amazonwebservices.com/AmazonSimpleDB/2009-04-15/DeveloperGuide/QuotingRulesSelect.html" target="_blank" title="SimpleDB Documentation - Escaping Queries">be safe with your syntax</a>, use backticks (``) to escape Domain names and Attribute names and use single-quotes ('') for values</li>
<li>If you sort, the sort Attribute must appear in at least one predicate statement</li>
<li>Implicit NULLs, no explicit NULL values</li>
<li>Limiting is kinda borked</li></ul>
<h3>Resources</h3>
<a id="blvk" href="http://docs.amazonwebservices.com/AmazonSimpleDB/2009-04-15/DeveloperGuide/" target="_blank" title="Amazon SimpleDB Documentation">Amazon SimpleDB Documentation</a><br>
<a id="v1w:" href="http://code.google.com/p/boto/" target="_blank" title="Boto rocks!">Boto</a> - Python module for Amazon Web Services
      ]]></content>
    </entry>

    <entry>
      <title>Hello World</title>
      <link rel="alternate" type="text/html" href="http://cloudcarpenters.com/site/hello_world/" />
      <id>tag:cloudcarpenters.com,2009:/2.13</id>
      <published>2009-06-10T15:30:00Z</published>
      <updated>2009-06-10T16:51:01Z</updated>
      <author>
            <name>ian</name>
            <email>ian@cloudcarpenters.com</email>
                  </author>

      <category term="News"
        scheme="http://cloudcarpenters.com/site/category/News/"
        label="News" />
      <category term="Announcements"
        scheme="http://cloudcarpenters.com/site/category/Announcements/"
        label="Announcements" />
      <content type="html"><![CDATA[
        <p>Hello World,</p>

<p>This is Ian speaking, and I just want to write a little bit about what we are doing here at Cloud Carpenters. Our team has been making websites and web applications for some time now. We have been doing so for our respective employers as well as personal projects and have worked with varying amounts of resources. When Amazon Web Services (AWS) came out in beta we immediately jumped on it, not because we wanted to be in the &#8220;clouds&#8221;, but because we wanted affordable, scalable hosting with full control over our machines. We instantly recognized that this was a platform that could support our pet projects cheaply and easily scale if and when they take off. After David moved the startup he works for from managed hosting to mostly AWS (EC2 and S3) cutting monthly costs by a sizable amount, we realized that there are many people in the same boat as us. So we decided to get on a plane, and now we are starting this company to get those people, you, on that plane too. </p>

<p>We have been posting <a href="/tutorials">tutorials</a> to help get you started with AWS and we will be releasing more. We know we aren&#8217;t the only ones trying to save money and make applications that have global reach so feel free to follow us on <a href="http://twitter.com/cloudcarpenters">twitter</a> or <a href="/contact">contact</a> us directly to start a conversation about anything AWS related.</p>

<p>return 0;
</p> 
      ]]></content>
    </entry>

    <entry>
      <title>Bundling A Custom AMI</title>
      <link rel="alternate" type="text/html" href="http://cloudcarpenters.com/site/bundling_a_custom_ami/" />
      <id>tag:cloudcarpenters.com,2009:/2.10</id>
      <published>2009-06-04T17:58:05Z</published>
      <updated>2009-07-27T15:41:06Z</updated>
      <author>
            <name>david</name>
            <email>mumrah@gmail.com</email>
                  </author>

      <category term="Tutorials"
        scheme="http://cloudcarpenters.com/site/category/Tutorials/"
        label="Tutorials" />
      <content type="html"><![CDATA[
        <div id="blms" style="text-align: center;"><p>
<img src="http://cloudcarpenters-cdn.s3.amazonaws.com/blog/dxhgtqb_20f4fpdz8k_b.png" style="width: 640px; height: 494.545px;">
</p></div><p>
You will see a slew of public images (including some of our own), and the list is actualy quite daunting. This is actually a very important step since this will be the foundation on which you build you AMI. We use (exclusively) the Alestic Debian AMIs (32-bit or 64-bit depending on the application). More information about what <a href="http://alestic.com/" id="hdnc" target="_blank" title="Best AMIs this side of the Mississippi">Alestic can be here</a>. Search through the list, and find whichever base image you want to work with. If you are starting with Ubuntu or Debian, I really insist on using the Alestic images - they are frequently updated and are highly optimized for EC2.</p>

<p>Now that you&#8217;ve got your base AMI in hand, lets get to getting.</p>

<p>To begin, spawn your instance (I chose a Debian base AMI):<br />
<pre class="python code_block_class" style="font-family:monospace;">ec2-run-instances ami-67fe190e</pre><br />
Or spawn it with Elasticfox
</p><div id="j61i" style="text-align: center;"><p>
 <img src="http://cloudcarpenters-cdn.s3.amazonaws.com/blog/dxhgtqb_21g9gzw2qt_b.png" style="width: 579px; height: 681px;">
</p><div style="text-align: left;"><p>
Notice that when using a public AMI, you must spawn it using a keypair so you can access it. To read more about keypairs, check out our <a href="http://cloudcarpenters.com/blog/ec2_keypair/">other tutorial</a>. Once the instance has become available, ssh into it (Windows users check our <a href="http://cloudcarpenters.com/blog/ec2_putty/">article on using Putty and EC2</a>).<br></p>

<p> <br />
<pre class="bash code_block_class" style="font-family:monospace;"><span style="color: #c20cb9; font-weight: bold;">ssh</span> root<span style="color: #000000; font-weight: bold;">@</span>ec2-<span style="color: #000000;">72</span>-<span style="color: #000000;">44</span>-<span style="color: #000000;">61</span>-6.compute-1.amazonaws.com <span style="color: #660033;">-i</span> ~<span style="color: #000000; font-weight: bold;">/</span>.ssh<span style="color: #000000; font-weight: bold;">/</span>id-cloud-carpenters</pre></p>

<p>Once logged in, make like a sysadmin and get to apting - or rather, apt to getting. You get the idea.</p>

<p><pre class="bash code_block_class" style="font-family:monospace;"><span style="color: #c20cb9; font-weight: bold;">apt-get</span> update
<span style="color: #c20cb9; font-weight: bold;">apt-get</span> upgrade
<span style="color: #c20cb9; font-weight: bold;">apt-get</span> <span style="color: #c20cb9; font-weight: bold;">install</span> git-core apache2-mpm-worker libapache2-mod-python</pre></p>

<p> Now that your instance is awesome, you need to bundle it. The Alestic AMIs come with the AMI tools already installed so there&#8217;s no need to download them. In order to bundle a image, you will need your private key and certificate issued by Amazon. You can find them on http://aws.amazon.com under &#8220;Your Account&#8221; and then &#8220;Access Identifiers&#8221;. When you are first prompted to generate a certificate file, you should recieve the cert-yourcert.pem and pk-yourpk.pem files. Again, this tutorial is assuming you have a basic knowledge of EC2 which includes this account identification stuff. If you&#8217;re having trouble with this, try the unofficial IRC channel (##aws), or read <a href="http://docs.amazonwebservices.com/AWSEC2/latest/GettingStartedGuide/" id="e7gw" target="_blank" title="Amazon's getting started guide">Amazon&#8217;s getting started guide</a>. Once you have the private key and certificate files on the instance, start the bundle.</p>

<p> <br />
<pre class="bash code_block_class" style="font-family:monospace;">ec2-bundle-vol <span style="color: #660033;">-c</span> <span style="color: #000000; font-weight: bold;">/</span>root<span style="color: #000000; font-weight: bold;">/</span>.ec2<span style="color: #000000; font-weight: bold;">/</span>cert-yourcert.pem <span style="color: #660033;">-k</span> <span style="color: #000000; font-weight: bold;">/</span>root<span style="color: #000000; font-weight: bold;">/</span>.ec2<span style="color: #000000; font-weight: bold;">/</span>pk-yourpk.pem <span style="color: #660033;">-d</span> <span style="color: #000000; font-weight: bold;">/</span>mnt <span style="color: #660033;">-u</span> 0123456678901 <span style="color: #660033;">-e</span> <span style="color: #000000; font-weight: bold;">/</span>root<span style="color: #000000; font-weight: bold;">/</span>.ec2</pre><br />
 </p></div>
</div><p>
A couple of notes about that command. Notice the pk and cert are in a directory under root called &#8220;.ec2&#8221;. I put them in their own directory so that I can explicitly exclude that directory from the bundle, because you probably don&#8217;t want you cert and private key on the newly created image (especially if you make it public). The &#8220;-u&#8221; is your 12 digit account number sans dashes from &#8220;Your Account&#8221; on http://aws.amazon.com, and &#8220;-e&#8221; is a comma-delimited list of directories you want excluded from the bundle.</p>

<p>The bundle shouldn&#8217;t take all that long (unless you installed a lot of stuff, or have some data files or something). It usually takes less than 5 minutes for our images to bundle (we rebundle often). After the bundling is complete, simply upload it to your S3 account.<br />
<pre class="bash code_block_class" style="font-family:monospace;">ec2-upload-bundle <span style="color: #660033;">-b</span> bucket-for-new-image <span style="color: #660033;">-m</span> <span style="color: #000000; font-weight: bold;">/</span>mnt<span style="color: #000000; font-weight: bold;">/</span>image.manifest.xml-a yourawsaccesskeyid <span style="color: #660033;">-s</span> yourawssecretkey</pre><br />
The AWS Access Key Id and Secret Key can be found on your &#8220;Access Identifiers&#8221; page on Amazon&#8217;s website. I like to give my images meaningful names unlike &#8220;cloudcarpenters-the-best-image-ever&#8221; or &#8220;cloudcarpenters-my-ami-brings-all-the-boys-to-the-yard&#8221;. </p>

<p>The final step before testing you delicious new AMI is registering the <strike>manifesto</strike> manifest. This can be done with Elasticfox or with the EC2-API-tools.<br />
<pre class="bash code_block_class" style="font-family:monospace;">ec2-register</pre>
</p><div id="t_yb" style="text-align: center;"><p><img style="width: 452px; height: 105px;" src="http://cloudcarpenters-cdn.s3.amazonaws.com/blog/dxhgtqb_22fkcnj6fh_b.png">
</p><div style="text-align: left;"><p>
Personally, I&#8217;ve found Elasticfox to be somewhat flaky in this department, so I typically will use the command line tools. Note: If you register an existing image manifest, it will override any previous AMI that used that manifest. Sometimes this is the desired functionality, sometimes not. If you need to do versioning with your images I would recommend a naming scheme like: my-lamp-image-0.1, my-lamp-image-0.2, etc.</p>

<p>Once the image is registered, launch it log in and make sure you didn&#8217;t leave anything important lying around - you know, like you certificate/private keyxt, your SSN, incriminating photos, etc.</p>

<p>You now have you&#8217;re very own AMI!
</p></div>
</div>

<p>&nbsp;</p> <div id="blms" style="text-align: center;"><p>
<img src="http://cloudcarpenters-cdn.s3.amazonaws.com/blog/dxhgtqb_20f4fpdz8k_b.png" style="width: 640px; height: 494.545px;">
</p></div><p>
You will see a slew of public images (including some of our own), and the list is actualy quite daunting. This is actually a very important step since this will be the foundation on which you build you AMI. We use (exclusively) the Alestic Debian AMIs (32-bit or 64-bit depending on the application). More information about what <a href="http://alestic.com/" id="hdnc" target="_blank" title="Best AMIs this side of the Mississippi">Alestic can be here</a>. Search through the list, and find whichever base image you want to work with. If you are starting with Ubuntu or Debian, I really insist on using the Alestic images - they are frequently updated and are highly optimized for EC2.</p>

<p>Now that you&#8217;ve got your base AMI in hand, lets get to getting.</p>

<p>To begin, spawn your instance (I chose a Debian base AMI):<br />
<pre class="python code_block_class" style="font-family:monospace;">ec2-run-instances ami-67fe190e</pre><br />
Or spawn it with Elasticfox
</p><div id="j61i" style="text-align: center;"><p>
 <img src="http://cloudcarpenters-cdn.s3.amazonaws.com/blog/dxhgtqb_21g9gzw2qt_b.png" style="width: 579px; height: 681px;">
</p><div style="text-align: left;"><p>
Notice that when using a public AMI, you must spawn it using a keypair so you can access it. To read more about keypairs, check out our <a href="http://cloudcarpenters.com/blog/ec2_keypair/">other tutorial</a>. Once the instance has become available, ssh into it (Windows users check our <a href="http://cloudcarpenters.com/blog/ec2_putty/">article on using Putty and EC2</a>).<br></p>

<p> <br />
<pre class="bash code_block_class" style="font-family:monospace;"><span style="color: #c20cb9; font-weight: bold;">ssh</span> root<span style="color: #000000; font-weight: bold;">@</span>ec2-<span style="color: #000000;">72</span>-<span style="color: #000000;">44</span>-<span style="color: #000000;">61</span>-6.compute-1.amazonaws.com <span style="color: #660033;">-i</span> ~<span style="color: #000000; font-weight: bold;">/</span>.ssh<span style="color: #000000; font-weight: bold;">/</span>id-cloud-carpenters</pre></p>

<p>Once logged in, make like a sysadmin and get to apting - or rather, apt to getting. You get the idea.</p>

<p><pre class="bash code_block_class" style="font-family:monospace;"><span style="color: #c20cb9; font-weight: bold;">apt-get</span> update
<span style="color: #c20cb9; font-weight: bold;">apt-get</span> upgrade
<span style="color: #c20cb9; font-weight: bold;">apt-get</span> <span style="color: #c20cb9; font-weight: bold;">install</span> git-core apache2-mpm-worker libapache2-mod-python</pre></p>

<p> Now that your instance is awesome, you need to bundle it. The Alestic AMIs come with the AMI tools already installed so there&#8217;s no need to download them. In order to bundle a image, you will need your private key and certificate issued by Amazon. You can find them on http://aws.amazon.com under &#8220;Your Account&#8221; and then &#8220;Access Identifiers&#8221;. When you are first prompted to generate a certificate file, you should recieve the cert-yourcert.pem and pk-yourpk.pem files. Again, this tutorial is assuming you have a basic knowledge of EC2 which includes this account identification stuff. If you&#8217;re having trouble with this, try the unofficial IRC channel (##aws), or read <a href="http://docs.amazonwebservices.com/AWSEC2/latest/GettingStartedGuide/" id="e7gw" target="_blank" title="Amazon's getting started guide">Amazon&#8217;s getting started guide</a>. Once you have the private key and certificate files on the instance, start the bundle.</p>

<p> <br />
<pre class="bash code_block_class" style="font-family:monospace;">ec2-bundle-vol <span style="color: #660033;">-c</span> <span style="color: #000000; font-weight: bold;">/</span>root<span style="color: #000000; font-weight: bold;">/</span>.ec2<span style="color: #000000; font-weight: bold;">/</span>cert-yourcert.pem <span style="color: #660033;">-k</span> <span style="color: #000000; font-weight: bold;">/</span>root<span style="color: #000000; font-weight: bold;">/</span>.ec2<span style="color: #000000; font-weight: bold;">/</span>pk-yourpk.pem <span style="color: #660033;">-d</span> <span style="color: #000000; font-weight: bold;">/</span>mnt <span style="color: #660033;">-u</span> 0123456678901 <span style="color: #660033;">-e</span> <span style="color: #000000; font-weight: bold;">/</span>root<span style="color: #000000; font-weight: bold;">/</span>.ec2</pre><br />
 </p></div>
</div><p>
A couple of notes about that command. Notice the pk and cert are in a directory under root called &#8220;.ec2&#8221;. I put them in their own directory so that I can explicitly exclude that directory from the bundle, because you probably don&#8217;t want you cert and private key on the newly created image (especially if you make it public). The &#8220;-u&#8221; is your 12 digit account number sans dashes from &#8220;Your Account&#8221; on http://aws.amazon.com, and &#8220;-e&#8221; is a comma-delimited list of directories you want excluded from the bundle.</p>

<p>The bundle shouldn&#8217;t take all that long (unless you installed a lot of stuff, or have some data files or something). It usually takes less than 5 minutes for our images to bundle (we rebundle often). After the bundling is complete, simply upload it to your S3 account.<br />
<pre class="bash code_block_class" style="font-family:monospace;">ec2-upload-bundle <span style="color: #660033;">-b</span> bucket-for-new-image <span style="color: #660033;">-m</span> <span style="color: #000000; font-weight: bold;">/</span>mnt<span style="color: #000000; font-weight: bold;">/</span>image.manifest.xml <span style="color: #660033;">-a</span> yourawsaccesskeyid <span style="color: #660033;">-s</span> yourawssecretkey</pre><br />
The AWS Access Key Id and Secret Key can be found on your &#8220;Access Identifiers&#8221; page on Amazon&#8217;s website. I like to give my images meaningful names unlike &#8220;cloudcarpenters-the-best-image-ever&#8221; or &#8220;cloudcarpenters-my-ami-brings-all-the-boys-to-the-yard&#8221;. </p>

<p>The final step before testing you delicious new AMI is registering the <strike>manifesto</strike> manifest. This can be done with Elasticfox or with the EC2-API-tools.<br />
<pre class="bash code_block_class" style="font-family:monospace;">ec2-register</pre>
</p><div id="t_yb" style="text-align: center;"><p><img style="width: 452px; height: 105px;" src="http://cloudcarpenters-cdn.s3.amazonaws.com/blog/dxhgtqb_22fkcnj6fh_b.png">
</p><div style="text-align: left;"><p>
Personally, I&#8217;ve found Elasticfox to be somewhat flaky in this department, so I typically will use the command line tools. Note: If you register an existing image manifest, it will override any previous AMI that used that manifest. Sometimes this is the desired functionality, sometimes not. If you need to do versioning with your images I would recommend a naming scheme like: my-lamp-image-0.1, my-lamp-image-0.2, etc.</p>

<p>Once the image is registered, launch it log in and make sure you didn&#8217;t leave anything important lying around - you know, like you certificate/private keyxt, your SSN, incriminating photos, etc.</p>

<p>You now have you&#8217;re very own AMI!
</p></div>
</div>

<p>&nbsp;</p>
      ]]></content>
    </entry>

    <entry>
      <title>Accessing EC2 from Windows with Putty</title>
      <link rel="alternate" type="text/html" href="http://cloudcarpenters.com/site/ec2_putty/" />
      <id>tag:cloudcarpenters.com,2009:/2.7</id>
      <published>2009-05-21T15:12:44Z</published>
      <updated>2009-06-08T14:54:45Z</updated>
      <author>
            <name>david</name>
            <email>mumrah@gmail.com</email>
                  </author>

      <category term="Tutorials"
        scheme="http://cloudcarpenters.com/site/category/Tutorials/"
        label="Tutorials" />
      <content type="html"><![CDATA[
        <p>Since Windows does not have a built in SSH client, logging into an EC2 instance with Windows is a little tricky. Here we present a (hopefully) straightforward approach to getting your keys setup and getting logged in with Putty.<br><br />
<br><br />
You will need to download two executable files from Putty: putty.exe and puttygen.exe. Both are available for free on <a title="Putty's download page" target="_blank" href="http://www.chiark.greenend.org.uk/%7Esgtatham/putty/download.html" id="vcug">their website</a>. There are other SSH clients for Windows, but Putty is the only decent free one (to my knowledge). <br><br />
<br><br />
Assuming you&#8217;re already created a key (if not check out this tutorial), we need to first prep the key for use with Putty. Load Puttygen.exe and load your private key-pair file. The contents of you key should appear in the window (I removed it from the following screenshot).<br>
</p> <p><br>
</p><div id="x.mp" style="text-align: center;"><img style="width: 503px; height: 489px;" src="http://cloudcarpenters-cdn.s3.amazonaws.com/blog/dxhgtqb_27hfzqtmd9_b.png"></div><p>
<br><br />
Now that you have loaded you SSH-2 RSA key into Puttygen.exe, you will need to save a Putty-compatible private key. It&#8217;s generally a good idea to password protect your private keys, so go ahead and put in a password you&#8217;ll remember into &#8220;Key passphrase&#8221; and &#8220;Confirm passphrase&#8221;. Next click &#8220;Save private key&#8221; and give your key a meaningful name and stick it in My Documents.<br><br />
<br><br />
The resulting file will be a ppk file that is useable by Putty.exe. Next, fire up Putty.exe.<br><br />
<br>
</p><div id="lnv4" style="text-align: center;"><p><img style="width: 474px; height: 459px;" src="http://cloudcarpenters-cdn.s3.amazonaws.com/blog/dxhgtqb_28crwzr2cf_b.png"><br>
</p><div style="text-align: left;"><p><br><br />
Fill in &#8220;Host Name&#8221; with the public dns name of your instance (something like <span style="font-family: Verdana;">ec2-72-44-61-6.compute-1.amazonaws.com). Then in the left tree menu, expand &#8220;Connection&#8221; and then &#8220;SSH&#8221;. In the &#8220;Auth&#8221; section, there will be a spot for you to choose a private key to use for this connection. Click &#8220;Browse&#8221; and select the ppk file you just saved.<br><br />
<br>
</p><div id="r8zj" style="text-align: center;"><p><img style="width: 472px; height: 459px;" src="http://cloudcarpenters-cdn.s3.amazonaws.com/blog/dxhgtqb_29x6468vdd_b.png"><br><br />
<br><br />
<br>
</p></div><p>
</span>
</p><div style="text-align: left;"><p>That should do it. If you have any problems, you can look at <a title="Connecting to EC2 with Putty" target="_blank" href="http://docs.amazonwebservices.com/AWSEC2/latest/GettingStartedGuide/putty.html" id="fkjv">Amazon&#8217;s documentation about using Putty</a>, or head over the the unofficial IRC channel, ##aws. Sorry if this tutorial was a little dry - there&#8217;s just nothing funny about Windows. <br>
</p></div>
</div><p>
<br>
</p></div><p>
<br>
</p>
      ]]></content>
    </entry>

    <entry>
      <title>Generating a Keypair for Amazon EC2</title>
      <link rel="alternate" type="text/html" href="http://cloudcarpenters.com/site/ec2_keypair/" />
      <id>tag:cloudcarpenters.com,2009:/2.6</id>
      <published>2009-05-18T12:51:53Z</published>
      <updated>2009-07-27T15:41:55Z</updated>
      <author>
            <name>david</name>
            <email>mumrah@gmail.com</email>
                  </author>

      <category term="Tutorials"
        scheme="http://cloudcarpenters.com/site/category/Tutorials/"
        label="Tutorials" />
      <content type="html"><![CDATA[
        <p>Before you do anything on EC2, you need a keypair plain and simple. There are two easy ways to generate a key: one is using <a title="Elasticfox" target="_blank" href="http://developer.amazonwebservices.com/connect/entry.jspa?externalID=609" id="s1af">Elasticfox</a> (my preferred method), and the other is using <a title="Amazon's EC2-API-tools" target="_blank" href="http://developer.amazonwebservices.com/connect/entry.jspa?externalID=351" id="nxki">Amazon&#8217;s EC2-API-tools</a>. If you are reading this tutorial, I&#8217;m assuming you&#8217;re new to working with EC2. A very brief run down of how to get the EC2-API-tools working:<br><br />
<br>
</p><ul><li>Goto http://aws.amazon.com, sign up for EC2</li>
<li>Under &#8220;Your Account&#8221; click &#8220;Access Identifiers&#8221; (you will likely come back here often)</li>
<li>Generate a certificate (you should get two *.pem files cert-somelonghash.pem and pk-somelonghash.pem</li>
<li>Make a directory in your home folder, call it something like &#8220;ec2&#8221; or &#8220;.ec2&#8221; or &#8220;aws&#8221;. Put the files here.&nbsp;</li>
<li>Download the tools (link above)</li>
<li>Install and configure the tools (Amazon has a good <a title="Amazon's getting started guide for EC2-API-tools" target="_blank" href="http://docs.amazonwebservices.com/AWSEC2/2008-12-01/GettingStartedGuide/index.html?setting-up-your-tools.html" id="m_q4">write-up</a> on this)</li></ul>

<p>&nbsp;</p> <p><br><br />
Now that all that is taken care of, we can get started (for reals this time). <br><br />
<pre class="bash code_block_class" style="font-family:monospace;">ec2-add-keypair cloud-carpenters<span style="color: #000000; font-weight: bold;">&lt;</span>br<span style="color: #000000; font-weight: bold;">&gt;</span>
&nbsp;</pre>
</p><div id="c:9v" style="text-align: center;">
<div style="text-align: left;"><p>This will generate the key signature (which will appear in ec2-describe-keypairs and in the &#8220;KeyPairs&#8221; tab of Elasticfox) as well as the private key itself. The generated key will look like<br><br />
<br><br />
<pre class="bash code_block_class" style="font-family:monospace;"><span style="color: #660033;">-----BEGIN</span> RSA PRIVATE KEY-----
&nbsp;
A Whole mess of stuff
&nbsp;
<span style="color: #660033;">-----END</span> RSA PRIVATE KEY-----</pre><br />
<br><br />
You&#8217;ll want to copy/paste the contents of the key (including the BEGIN/END lines) into a blank file. It would actually be easier to just cat the output of ec2-add-keypair like<br><br />
<br><br />
<pre class="bash code_block_class" style="font-family:monospace;">ec2-add-keypair cloud-carpenters <span style="color: #000000; font-weight: bold;">&gt;</span> id-cloud-carpenters</pre><br />
<br><br />
and then remove the first line of the file. This way you don&#8217;t have to worry about your text editor doing funny things with wrapping and newlines. <br><br />
<br><br />
In Elasticfox, click the green key icon and give the key a name.<br>
</p></div><p>
<img style="width: 640px; height: 494.545px;" src="http://cloudcarpenters-cdn.s3.amazonaws.com/blog/dxhgtqb_24d7g96fc7_b.png"><br>
</p><div style="text-align: left;"><p>Once generated, Elasticfox will prompt you to download your freshly generated key. Regardless of the method you chose, move the key into a safe directory (like ~/.ssh) and change the permissions to 400 (read-only by you). <br><br />
<br><br />
To use this key, you need to spawn instances with it. This is super simple in Elasticfox, and not too complicated with the command line tools. With the command line tools, you need to add &#8220;-k&#8221; to the argument list with the name of the key you just created<br><br />
<pre class="bash code_block_class" style="font-family:monospace;">ec2-run-instance ami-0123abcd <span style="color: #660033;">-k</span> cloud-carpenters</pre>
</p></div>
</div>
<div id="v8t1" style="text-align: center;">
<div style="text-align: left;"><p>Or in Elasticfox<br>
</p></div><p>
<img style="width: 579px; height: 681px;" src="http://cloudcarpenters-cdn.s3.amazonaws.com/blog/dxhgtqb_2534fc9xhb_b.png"></p></div><p>
<br><br />
Once the instance is available, you can ssh into using the key (Windows users, check out our Putty tutorial)<br><br />
<pre class="bash code_block_class" style="font-family:monospace;"><span style="color: #c20cb9; font-weight: bold;">ssh</span> root<span style="color: #000000; font-weight: bold;">@</span>ec2-<span style="color: #000000;">72</span>-<span style="color: #000000;">44</span>-<span style="color: #000000;">61</span>-6.compute-1.amazonaws.com <span style="color: #660033;">-i</span> ~<span style="color: #000000; font-weight: bold;">/</span>.ssh<span style="color: #000000; font-weight: bold;">/</span>id-cloud-carpenters</pre><br />
And there you have it. Oh, and don&#8217;t use cloud-carpenters as your keyname - that was just for the tutorial. Use something like &#8220;home&#8221; or &#8220;yourname&#8221;.<br>
</p>
      ]]></content>
    </entry>


</feed>