<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0">

<channel>
	<title>AWSNinja</title>
	
	<link>http://awsninja.com</link>
	<description />
	<lastBuildDate>Mon, 21 Nov 2011 03:27:19 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.1.3</generator>
		<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/AwsNinja" /><feedburner:info uri="awsninja" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><feedburner:emailServiceId>AwsNinja</feedburner:emailServiceId><feedburner:feedburnerHostname>http://feedburner.google.com</feedburner:feedburnerHostname><item>
		<title>Recent AWS News</title>
		<link>http://feedproxy.google.com/~r/AwsNinja/~3/ULT5iT6whkY/</link>
		<comments>http://awsninja.com/2011/11/20/recent-aws-news-5/#comments</comments>
		<pubDate>Mon, 21 Nov 2011 03:27:19 +0000</pubDate>
		<dc:creator>Jay Muntz</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://awsninja.com/?p=557</guid>
		<description><![CDATA[Amazon Web Services Opens New Oregon Data Center New Amazon AWS Cluster Lowers Costs for Both Customers and Amazon AWS Management Console Adds Support for Amazon Route 53 Amazon Web Services GovCloud Adds HyperOffice Cloud Collaboration Solution Amazon Web Services Announces Cloud Supercomputer Ranked 42 On Top500 List]]></description>
			<content:encoded><![CDATA[<ul>
<li><a href="http://www.pcmag.com/article2/0,2817,2396153,00.asp#fbid=r9YxGKbixnQ">Amazon Web Services Opens New Oregon Data Center</a></li>
<li><a href=" http://www.readwriteweb.com/cloud/2011/11/new-amazon-aws-cluster-lowers.php">New Amazon AWS Cluster Lowers Costs for Both Customers and Amazon</a></li>
<li><a href="http://aws.amazon.com/about-aws/whats-new/2011/11/17/aws-management-console-adds-support-for-amazon-route-53/">AWS Management Console Adds Support for Amazon Route 53</a></li>
<li><a href=" http://www.thewhir.com/web-hosting-news/111111_Amazon_Web_Services_GovCloud_Adds_HyperOffice_Cloud_Collaboration_Solution">Amazon Web Services GovCloud Adds HyperOffice Cloud Collaboration Solution</a></li>
<li><a href="http://cloud-computing-today.com/2011/11/15/amazon-web-services-announces-cloud-supercomputer-ranked-42-on-top-500-list/">Amazon Web Services Announces Cloud Supercomputer Ranked 42 On Top500 List</a></li>
</ul>
<img src="http://feeds.feedburner.com/~r/AwsNinja/~4/ULT5iT6whkY" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://awsninja.com/2011/11/20/recent-aws-news-5/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://awsninja.com/2011/11/20/recent-aws-news-5/</feedburner:origLink></item>
		<item>
		<title>Recent AWS News</title>
		<link>http://feedproxy.google.com/~r/AwsNinja/~3/LPKUGmMI6v4/</link>
		<comments>http://awsninja.com/2011/11/06/recent-aws-news-4/#comments</comments>
		<pubDate>Mon, 07 Nov 2011 01:06:43 +0000</pubDate>
		<dc:creator>Jay Muntz</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://awsninja.com/?p=553</guid>
		<description><![CDATA[Benchmarking Amazon Web Services (AWS) Vs Rackspace Researchers demo cloud security issue with Amazon AWS hijacking attack SQLServer 2012 Denali on AWS AWS Management Console Adds Support for Amazon SES Amazon SQS New Features: Delay Queues, Message Timers and Batch APIs AWS Management Console Support for the Simple Email Service Two-factor authetication without the fob [...]]]></description>
			<content:encoded><![CDATA[<ul>
<li><a href="http://stress-testing.org/content/benchmarking-amazon-web-services-aws-vs-rackspace">Benchmarking Amazon Web Services (AWS) Vs Rackspace</a></li>
<li><a href="http://www.infoworld.com/d/cloud-computing/researchers-demo-cloud-security-issue-amazon-aws-hijacking-attack-177179www.infoworld.com/d/cloud-computing/researchers-demo-cloud-security-issue-amazon-aws-hijacking-attack-177179">Researchers demo cloud security issue with Amazon AWS hijacking attack</a></li>
<li><a href="http://www.i-programmer.info/news/141-cloud-computing/3244-aws-support-for-denali.html">SQLServer 2012 Denali on AWS</a></li>
<li><a href="http://aws.amazon.com/about-aws/whats-new/2011/10/26/aws-management-console-adds-support-for-Amazon-ses/">AWS Management Console Adds Support for Amazon SES</a></li>
<li><a href="http://aws.amazon.com/about-aws/whats-new/2011/10/21/amazon-sqs-new-features-delay-queues-message-timers-and-batch-apis/">Amazon SQS New Features: Delay Queues, Message Timers and Batch APIs</a></li>
<li><a href="http://aws.typepad.com/aws/2011/10/new-aws-management-console-support-for-the-simple-email-service.html">AWS Management Console Support for the Simple Email Service</a></li>
<li><a href="http://www.pcworld.com/businesscenter/article/243113/amazon_adds_app_for_easier_twofactor_authentication.html">Two-factor authetication without the fob</a></li>
</ul>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<img src="http://feeds.feedburner.com/~r/AwsNinja/~4/LPKUGmMI6v4" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://awsninja.com/2011/11/06/recent-aws-news-4/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://awsninja.com/2011/11/06/recent-aws-news-4/</feedburner:origLink></item>
		<item>
		<title>Recent AWS News</title>
		<link>http://feedproxy.google.com/~r/AwsNinja/~3/UdkrLJbBodQ/</link>
		<comments>http://awsninja.com/2011/10/16/recent-aws-news-3/#comments</comments>
		<pubDate>Sun, 16 Oct 2011 23:06:37 +0000</pubDate>
		<dc:creator>Jay Muntz</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://awsninja.com/?p=551</guid>
		<description><![CDATA[Virtual Private Cloud now supports Spot Instances Simple Queue Service now available in the Management Console Getting the most from CloudFront. Is Google chasing Amazon into the cloud? Is the cloud a bubble?  Does it matter? Why is Amazon winning? &#160;]]></description>
			<content:encoded><![CDATA[<ul>
<li>Virtual Private Cloud now supports <a href="http://aws.typepad.com/aws/2011/10/launch-ec2-spot-instances-in-a-virtual-private-cloud.html">Spot Instances</a></li>
<li>Simple Queue Service now available in the <a href="http://aws.typepad.com/aws/2011/10/aws-management-console-now-supports-the-simple-queue-service-sqs.html">Management Console</a></li>
<li>Getting the most from <a href="http://www.seomoz.org/ugc/improving-page-speed-with-amazon-web-services-a-beginners-guide">CloudFront</a>.</li>
<li>Is Google <a href="http://www.readwriteweb.com/cloud/2011/10/google-guns-for-amazon-web-ser.php">chasing</a> Amazon into the cloud?</li>
<li>Is the cloud a <a href="http://informationweek.com/thebrainyard/news/strategy/231900722/web-20-expo-is-this-a-cloud-bubble">bubble</a>?  Does it matter?</li>
<li>Why is Amazon <a href="http://cloudscaling.com/blog/cloud-computing/what-is-amazons-secret-for-success-and-why-is-ec2-a-runaway-train">winning</a>?</li>
</ul>
<p>&nbsp;</p>
<img src="http://feeds.feedburner.com/~r/AwsNinja/~4/UdkrLJbBodQ" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://awsninja.com/2011/10/16/recent-aws-news-3/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://awsninja.com/2011/10/16/recent-aws-news-3/</feedburner:origLink></item>
		<item>
		<title>Recent AWS News</title>
		<link>http://feedproxy.google.com/~r/AwsNinja/~3/yv5_MZxZQ60/</link>
		<comments>http://awsninja.com/2011/10/10/recent-aws-news-2/#comments</comments>
		<pubDate>Mon, 10 Oct 2011 16:45:56 +0000</pubDate>
		<dc:creator>Jay Muntz</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://awsninja.com/?p=548</guid>
		<description><![CDATA[Startups who love AWS, but are not naive about its limitations. Silk: Unfair? New CloudFormation enhancements. S3 get server side encryption. The first South American edge location.]]></description>
			<content:encoded><![CDATA[<ul>
<li><a href="http://gigaom.com/cloud/for-developers-amazons-cloud-is-a-harsh-mistress/">Startups who love AWS, but are not naive about its limitations</a>.</li>
<li>Silk: <a href="http://www.technologyreview.com/web/38728/">Unfair</a>?</li>
<li>New CloudFormation <a href="http://aws.amazon.com/about-aws/whats-new/2011/09/29/aws-cloudformation-new-features-update-stack-and-iam-support/">enhancements</a>.</li>
<li>S3 get <a href="http://aws.amazon.com/about-aws/whats-new/2011/10/04/amazon-s3-announces-server-side-encryption-support/">server side encryption</a>.</li>
<li>The first South American <a href="http://aws.amazon.com/about-aws/whats-new/2011/09/30/new-edge-location-sao-paulo/">edge location</a>.</li>
</ul>
<img src="http://feeds.feedburner.com/~r/AwsNinja/~4/yv5_MZxZQ60" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://awsninja.com/2011/10/10/recent-aws-news-2/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://awsninja.com/2011/10/10/recent-aws-news-2/</feedburner:origLink></item>
		<item>
		<title>Recent  AWS News</title>
		<link>http://feedproxy.google.com/~r/AwsNinja/~3/DY2TWI0Hbqc/</link>
		<comments>http://awsninja.com/2011/10/02/recent-aws-news/#comments</comments>
		<pubDate>Sun, 02 Oct 2011 23:24:08 +0000</pubDate>
		<dc:creator>Jay Muntz</dc:creator>
				<category><![CDATA[Recent News]]></category>

		<guid isPermaLink="false">http://awsninja.com/?p=539</guid>
		<description><![CDATA[Silk has its own Blog Amazon&#8217;s Cloud Services Pass Muster for Advanced Government Use Whitepaper: Amazon&#8217;s Corporate IT Deploys Corporate Intranet Running SharePoint 2010 on AWS Review of “Amazon Web Services: Migrating your .NET Enterprise Application” Amazon Route 53 Reduces Prices EC2 Cluster Compute and Cluster GPU with Windows AWS for Feds]]></description>
			<content:encoded><![CDATA[<ul>
<li>Silk has its own <a href="http://amazonsilk.wordpress.com/">Blog</a></li>
<li><a href="http://www.cmswire.com/cms/enterprise-20/amazons-cloud-services-pass-muster-for-advanced-government-use-012759.php">Amazon&#8217;s Cloud Services Pass Muster for Advanced Government Use</a></li>
<li>Whitepaper: <a href="http://aws.typepad.com/aws/2011/09/amazon-corporate-it-migration-to-aws-new-white-paper.html">Amazon&#8217;s Corporate IT Deploys Corporate Intranet Running SharePoint 2010 on AWS</a></li>
<li><a href="http://www.awsug.com/2011/09/review-of-amazon-web-services-migrating-your-net-enterprise-application/">Review</a> of “Amazon Web Services: Migrating your .NET Enterprise Application”</li>
<li>Amazon Route 53 <a href="http://aws.amazon.com/about-aws/whats-new/2011/09/27/amazon-route53-hosted-zone-price-change/">Reduces Prices</a></li>
<li>EC2 Cluster Compute and Cluster GPU with <a href="http://aws.amazon.com/about-aws/whats-new/2011/09/18/windows-for-cluster-instances/">Windows</a></li>
<li>AWS for <a href="http://www.infoworld.com/d/cloud-computing/amazon-web-services-receives-critical-government-certification-173185">Feds</a></li>
</ul>
<img src="http://feeds.feedburner.com/~r/AwsNinja/~4/DY2TWI0Hbqc" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://awsninja.com/2011/10/02/recent-aws-news/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://awsninja.com/2011/10/02/recent-aws-news/</feedburner:origLink></item>
		<item>
		<title>Get a Grip on CloudFront Private Streaming</title>
		<link>http://feedproxy.google.com/~r/AwsNinja/~3/BREYmNw5ujs/</link>
		<comments>http://awsninja.com/2010/10/26/get-a-grip-on-cloudfront-private-streaming/#comments</comments>
		<pubDate>Tue, 26 Oct 2010 16:31:55 +0000</pubDate>
		<dc:creator>Jay Muntz</dc:creator>
				<category><![CDATA[CloudFront]]></category>

		<guid isPermaLink="false">http://awsninja.com/?p=417</guid>
		<description><![CDATA[AWSNinja Code Library Name: awsninja_cloudfrontprivatestreaming AWS Services: CloudFront, S3 Source: at GitHub In a Sentence: Setting up Private Streaming on CloudFront is hard, so I automated it. Setting up private streaming on CloudFront is way more difficult that it probably needs to be. There are all sorts of little niggling details that will have you [...]]]></description>
			<content:encoded><![CDATA[<div class="librarybox">
<p><span class="libTitle">AWSNinja Code Library</span></p>
<p><span class="libSubTitle">Name:</span> awsninja_cloudfrontprivatestreaming</p>
<p><span class="libSubTitle">AWS Services:</span> <a href="http://aws.amazon.com/cloudfront/">CloudFront</a>, <a href="http://aws.amazon.com/s3/">S3</a></p>
<p><span class="libSubTitle">Source:</span> <a href="http://github.com/awsninja/awsninja_cloudfrontprivatestreaming">at GitHub</a></p>
<p><span class="libSubTitle">In a Sentence:</span> Setting up Private Streaming on CloudFront is hard, so I automated it.</p>
</div>
<p>Setting up private streaming on CloudFront is way more difficult that it probably needs to be.  There are all sorts of little niggling details that will have you pulling your hair out.  My hope is that this post will help ease the pain, by gliding you right past the rough edges so you can get it done <em>and</em> maintain your sanity.</p>
<p>To do that, this tutorial will set up a CloudFront Streaming Distribution, set up the security, upload some videos, and set up a webpage to view those videos using private streaming.  In addition to the AWS Ninja code that I&#8217;ve written, the package includes the <a href="http://www.longtailvideo.com/">JW Player</a> and the <a href="http://aws.amazon.com/sdkforphp/">AWS SDK for PHP</a>, both of which are included consistent with the licenses granted by those works.</p>
<p><span id="more-417"></span></p>
<p>If you&#8217;re just trying to learn more about the architecture of CloudFront and the API, you might just want to take a look at the source of <a href="http://github.com/awsninja/awsninja_cloudfrontprivatestreaming/blob/master/examples/oneTimeSetup.php">oneTimeSetup.php</a>, <a href="http://github.com/awsninja/awsninja_cloudfrontprivatestreaming/blob/master/examples/pushFilesToCloudFront.php">pushFilesToCloudFront.php</a>, and <a href="http://github.com/awsninja/awsninja_cloudfrontprivatestreaming/blob/master/examples/cleanup.php">cleanup.php</a>.  The steps for signing requests are in <a href="v">index.php</a>.</p>
<h3>CloudFront doesn&#8217;t do everything</h3>
<h3><span style="font-weight: normal; font-size: 13px;">The first way I will attempt to save your time is by informing you that CloudFront Private Streaming lacks certain security features.  It is not the most secure way to deliver your streams.  It has been noted in CloudFront Forums that there are are <a href="http://developer.amazonwebservices.com/connect/thread.jspa?messageID=190202">two</a> <a href="http://developer.amazonwebservices.com/connect/thread.jspa?messageID=188768">specific</a> security techniques that CloudFront doesn&#8217;t support:</span></h3>
<ol>
<li>While CloudFront supports RTMPE (encrypted streaming), it does not not have a way to stop end users from unencrypted streaming.  This means that if a user has access to your stream, he will have the capability of saving a copy of it using certain third-party tools which can be found online.  A user with some level of technical sophistication could obtain a copy of your content in this way.</li>
<li>CloudFront does not support SWF verification.  This is a technique whereby the streaming server will only stream to a SWF file that is &#8220;approved.&#8221;  This is another method of preventing your stream from being copied.</li>
</ol>
<p>Despite these limitations, CloudFront Private Streaming does give you a lot.  It prevents unauthorized streaming of your content by IP address of the user and/or date range.  This allows you to effectively set up a pay-walled or limited access video site or intranet for content you do not want to make available to the world.  Also, CloudFront is one of the AWS services that is still in beta, and we can reasonably expect Amazon to add these and other missing security features at some point.</p>
<p>You should also keep in mind, nothing is 100% secure.  It&#8217;s a truism that <a href="http://www.longtailvideo.com/support/blog/13088/securing-your-content">Anybody who can watch your video can steal your video</a>.  Your objective is to employ cost-effective means of making your content hard to steal.</p>
<p>If you decide that CloudFront does meet your requirements, what follows is your guide to go from zero to streaming.</p>
<h3>Set Up</h3>
<p>First, download the <a title="awsninja_cloudfrontprivatestreaming" href="http://http://github.com/awsninja/awsninja_cloudfrontprivatestreaming">awsninja_cloudfrontprivatestreaming</a> project from GitHub.  The project also includes a copy of the newly-relaunched <a href="http://aws.amazon.com/sdkforphp/">AWS SDK for PHP</a> from Amazon and the <a href="http://www.longtailvideo.com/players/">JW Player</a> flash player.  Once you&#8217;ve downloaded and uncompressed the library, you need to set up the SDK for PHP config.  Rename the &#8220;./aws/sdk/config-sample.inc.php&#8221; file to &#8220;&#8221;./aws/sdk/config.inc.php.&#8221;  Then, specify all of the parameters that are listed there:</p>
<ul>
<li>AWS_KEY</li>
<li>AWS_SECRET_KEY</li>
<li>AWS_ACCOUNT_ID</li>
<li>AWS_CANONICAL_ID</li>
<li>AWS_CANONICAL_NAME</li>
<li>AWS_CLOUDFRONT_KEYPAIR_ID</li>
<li>AWS_CLOUDFRONT_PRIVATE_KEY_PEM</li>
</ul>
<p>Instructions for how to set all of these can be found in the &#8220;config.inc.php&#8221; file itself.</p>
<h3>One-Time Steps</h3>
<p>Once you&#8217;ve completed the SDK config file, you should then run the &#8220;oneTimeSetup.php&#8221; script on the command line.  This is found in the &#8220;examples&#8221; directory.  This script automates and ensures  completion of all of the steps of the setup process.  Here are the pitfalls the script helps you avoid:</p>
<ul>
<li>You must specify a &#8220;Caller Reference&#8221; when you create an Origin Access Identity (OAI).  You&#8217;ll probably never use it, but the CloudFront API requires that you have one.  When using the &#8220;oneTimeSetup.php&#8221;, a Caller Reference is created for you automatically.</li>
<li>When creating a private streaming distribution, there are several required pieces of information:
<ol>
<li><strong>The OAI Id</strong> &#8211; You must specify the OAI Id, so you need to create the OAI before creating the distribution.</li>
<li><strong>The Streaming Flag</strong> &#8211; A &#8220;Distribution&#8221; and a &#8220;Streaming Distribution&#8221; are really different things. In order to create a &#8220;Streaming Distribution&#8221; you must add the Streaming=true argument.  If you forget to include it you will create a normal Distribution.  There is no way to change a normal Distribution to a Streaming Distribution or vise-versa.</li>
<li><strong>The TrustedSigners Flag</strong> &#8211; In order to control how your streams are used (which is bascially what we mean by &#8220;private&#8221;), you must make the stream unavailable to requesters who don&#8217;t properly sign their requests.  To activate that requirement, you must set the TrustedSigners flag to either &#8220;Self&#8221; or to the Canonical Id of another AWS user.  There is no setting called &#8220;Require Signed Request&#8221; or anything like that.  Whether or not a signed request is required is determined by whether or not you specify a TrustedSigner.Furthermore, if you do not set up any TrustedSigners for your Streaming Distribution but the requester sends a signed request &#8211; the stream will still work.  This might mislead you into thinking that your stream is protected when in reality it would work equally well with an unsigned request.</li>
</ol>
</li>
</ul>
<p>The &#8220;oneTimeSetup.php&#8221; script will take up to 15 minutes to run because it takes that long for your new Streaming Distribution to become active and deployed.  Once that completes successfully, rename the &#8220;config-sample.php&#8221; file to &#8220;config.php.&#8221; The &#8220;oneTimeSetup.php&#8221; script will echo out the PHP define() methods that you need to put in the &#8220;config.php&#8221; file (not the AWS SDK &#8220;config.inc.php&#8221; file!).  This completes the configuration of the other scripts.</p>
<p>To see that your Streaming Distribution is all set up, log into the AWS Console and click the CloudFront tab:</p>
<div class="img " style="width:500px;">
	<a href="http://assets.docmonk.com/ninja/distributionReady.png"><img src="http://assets.docmonk.com/ninja/distributionReady.png" alt="Your Streaming Distribution is Ready" width="500"  /></a>
	<div>Your Streaming Distribution is Ready</div>
</div>
<h3>Uploading Files</h3>
<p>Now that your CloudFront Origin bucket, OAI, and Streaming Distribution are all set up and configured, it&#8217;s time to upload some videos to your streaming bucket.</p>
<p>Included in the package is a file called &#8220;getCrockfordVids.sh.&#8221;  If you run this file on your command line, it will download five videos of <a href="http://www.crockford.com/">Douglas Crockford&#8217;s</a> talks on JavaScript from <a href="http://developer.yahoo.com/yui/theater/">YUI Theater</a>.  If that&#8217;s not enough JavaScript instruction for you, there are about 15 more videos in the file that are also available for download if you uncomment those lines.  If you&#8217;re wondering what to do next New Year&#8217;s Eve, I highly recommend downloading them all and hosting a &#8220;Douglas Crockford Viewing Marathon.&#8221;  Best New Years EVER!  (BTW &#8211; Douglas Crockford is awesome and I&#8217;ve learned a lot from his presentations even though I&#8217;ve only watched a small portion of what he&#8217;s put out.)</p>
<p>Anyway, the &#8220;getCrockfordVids.sh&#8221; file will download Crockford videos to the &#8220;video&#8221; directory (warning: the five files that are set to download by default comprise 1.6GB of video).   Once that is complete, you can run the &#8220;pushFilesToCloudFront.php&#8221; script to upload the files to the S3 bucket that was created for you by the &#8220;oneTimeSetup.php&#8221; script.  In this script, there are two calls to the S3 API.  The first one simply puts the object to S3, specifying that the owner has full control:</p>
<pre class="brush: php; title: ; notranslate">
echo(&quot;Put $file on S3\n&quot;);
$cbr = $s3-&gt;create_object(NINJA_STREAMING_BUCKET, $file, array(
	'fileUpload'=&gt;NINJA_BASEPATH . 'awsninja_cloudfrontprivatestreaming/videos/' . $file,
	'acl'=&gt;AmazonS3::ACL_OWNER_FULL_CONTROL
));
</pre>
<p>The second step sets the Access Control List (ACL) so that the Origin Identity we previously set up has READ access. This is the step that allows your CloudFront Distribution to read your files from S3.</p>
<pre class="brush: php; title: ; notranslate">
$acl = array(
	array(
		'id'=&gt;AWS_CANONICAL_ID,
		'permission'=&gt;AmazonS3::GRANT_FULL_CONTROL
	),
	array(
		'id'=&gt;NINJA_STREAMING_CANONICALID,
		'permission'=&gt;AmazonS3::GRANT_READ
	)
);
echo(&quot;Update the ACL for $file on S3.\n\n&quot;);
$sas = $s3-&gt;set_object_acl(NINJA_STREAMING_BUCKET, $file, $acl);
</pre>
<p>Note that the $acl array of arrays holds the permissions for the owner (indicated by the  AWS_CANONICAL_ID constant) and the Origin Access Identity (indicated by NINJA_STREAMING_CANONICALID).</p>
<h3>Streaming your Content</h3>
<p>Next, you need to set up the webpage that will be used for streaming.  All of the files you need to stream to are in the &#8220;www&#8221; directory.   If your project is not in your web root, you will need to either move the &#8220;www&#8221; directory (and fix the include paths in &#8220;index.php&#8221;) or use a symbolic link so that you can view that directory in your web browser.</p>
<p><strong>Extending the AmazonCloudFrontClass</strong><br />
In order to make this tutorial work, there is a minor change that needed to be made to the  AmazonCloudFront service class in the SDK for PHP.  The original AmazonCloudFront service contains a method called get_private_object_url() which is designed to create the signed url requests that are used to serve private content.  The method returns a complete signed url with domain name, path and query string. This is a problem because JW Player actually wants the domain name and the path as two separate arguments.  To solve this, I extended the AmazonCloudFront class from the SDK and added a method called get_private_object_path() which just consists of the portion of the get_private_object_url() which generates the path.  The get_private_object_url() remains the same (except that the logic that was moved to get_private_object_path() was replaced with a call to the new method).  You can inspect this work in the &#8220;ninja.cloudfront.class.php&#8221; file.</p>
<p><strong>Protection Options</strong><br />
There are a few different options for protecting your stream.  At a minimum, you need to set an expiration date (called &#8220;DateLessThan&#8221;) after which the stream stops working.  Additionally, you can set a start date (&#8220;DateGreaterThan&#8221;) and/or an IP Address.  If you set the IPAddress, the request must come from that IP Address in order to work.</p>
<p>If you want to make sure that your content can only be streamed from a web page that you control, the best way to do that is to sign the request using the $_SERVER['REMOTE_ADDR'] PHP global.  Your arguments in &#8220;index.php&#8221; would look like this:</p>
<pre class="brush: php; title: ; notranslate">
$expiration = strtotime('+4320 minutes');  //three days

$opt = array(
//	'BecomeAvailable'=&gt;strtotime('+10 minutes'),  //starts working in 10 minutes
	'IPAddress'=&gt; $_SERVER['REMOTE_ADDR']  //limit to the current IP address (prevents the user from embedding the flash player to serve the content to other users)
);

$cfsn = new AmazonCloudFrontNinja();
$urlcloud = $cfsn-&gt;get_private_object_path($item, $expiration, $opt);;
</pre>
<p><strong>Note:</strong> &#8220;BecomeAvailable&#8221; is the argument you send to the AmazonCloudFront service (the SDK for PHP).  Inside the service class, it gets changed to &#8220;DateGreaterThan&#8221; which is the correct name for the CloudFront API.  Since the &#8220;BecomeAvailable&#8221; parameter is commented out in the code above, the stream would be available immediately.</p>
<h3>Load-er Up!</h3>
<p>Pull up the &#8220;index.php&#8221; file in your web browser  - and you should see your videos.  Happy New Year!</p>
<h3>Tear-er Down!</h3>
<p>Once you&#8217;re done working though this tutorial, the  &#8220;cleanup.php&#8221; script will remove all of the Streaming Distributions and OAIs.  The process of removing these objects is nearly as complicated as creating themm but I an not going to describe it.  The source code has documentation and explains what&#8217;s going on.  <strong>Take Heed:</strong> If you&#8217;re currently running a live Streaming Distribution, this script will delete that one too.</p>
<img src="http://feeds.feedburner.com/~r/AwsNinja/~4/BREYmNw5ujs" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://awsninja.com/2010/10/26/get-a-grip-on-cloudfront-private-streaming/feed/</wfw:commentRss>
		<slash:comments>12</slash:comments>
		<feedburner:origLink>http://awsninja.com/2010/10/26/get-a-grip-on-cloudfront-private-streaming/</feedburner:origLink></item>
		<item>
		<title>A PHP Framework for Hosting your JavaScript Applications on CloudFront</title>
		<link>http://feedproxy.google.com/~r/AwsNinja/~3/nDZ5LFgj7dE/</link>
		<comments>http://awsninja.com/2010/09/28/a-php-framework-for-hosting-your-javascript-applications-on-cloudfront/#comments</comments>
		<pubDate>Tue, 28 Sep 2010 04:16:12 +0000</pubDate>
		<dc:creator>Jay Muntz</dc:creator>
				<category><![CDATA[CloudFront]]></category>

		<guid isPermaLink="false">http://awsninja.com/?p=280</guid>
		<description><![CDATA[AWSNinja Code Library Name: awsninja_cloudfrontjavascript AWS Services: CloudFront, S3 Source: at GitHub In a Sentence: A system for optimal JavaScript management and performance in both production and development environments. Today I’m going to try to answer the question: JavaScript &#8211; How do you organize this mess?!? The StackOverflow user who posted this question was primarily [...]]]></description>
			<content:encoded><![CDATA[<div class="librarybox">
<p><span class="libTitle">AWSNinja Code Library</span></p>
<p><span class="libSubTitle">Name:</span> awsninja_cloudfrontjavascript</p>
<p><span class="libSubTitle">AWS Services:</span> <a href="http://aws.amazon.com/cloudfront/">CloudFront</a>, <a href="http://aws.amazon.com/s3/">S3</a></p>
<p><span class="libSubTitle">Source:</span> <a href="http://github.com/awsninja/awsninja_cloudfrontjavascript">at GitHub</a></p>
<p><span class="libSubTitle">In a Sentence:</span> A system for optimal JavaScript management and performance in both production and development environments.</p>
</div>
<p>Today I’m going to try to answer the question: <a href="http://stackoverflow.com/questions/247209/javascript-how-do-you-organize-this-mess">JavaScript &#8211; How do you organize this mess?!?</a> The StackOverflow user who posted this question was primarily concerned with organizing JavaScript classes and namespaces &#8211; but many of the replies were about managing and serving script files.  Both topics are extremely important, and in this post I’ll be focusing on the latter.</p>
<p>I’ve <a href="http://awsninja.com/2010/06/11/a-php-framework-for-hosting-images-on-amazon-cloudfront/">previously written</a> about managing your site’s images on CloudFront, and this article will basically tackle the same topic for JavaScript.  Someday, I will post a third post in this series that deals with CSS.</p>
<p><span id="more-280"></span></p>
<h3>The Headaches</h3>
<div class="wp-caption alignright" style="width: 189px"><a href="http://www.flickr.com/photos/migrainechick/526103563/"><img src="http://assets.docmonk.com/ninja/chronicpain.jpg" alt="" width="179" height="240" /></a><p class="wp-caption-text">My headache has JavaScript written all over it.</p></div>
<p>The headaches that your site’s JavaScript cause can be grouped into two categories, <strong>Maintainability Considerations</strong> and <strong>Performance Considerations</strong>.  Here are the main points:</p>
<p><strong>JavaScript Maintainability Considerations:</strong></p>
<ul>
<li><strong>It’s a lot of code doing a lot of complex stuff.</strong> In addition to the functionality you write yourself, you’re including more third-party libraries and plug-ins than ever before.</li>
<li><strong>You need to manage dependencies.</strong> When you include a component on the page, you need to make sure you include the other required components.</li>
<li><strong>The order that you include the code in your page matters.</strong> A dependency needs to appear before the component that depends on it.</li>
<li><strong>The development environment is completely different from production. </strong>
<ul>
<li>In <strong>development</strong>, your primary concern is finding where the error is, so you want your application to be broken down logically into files and you want the code to be readable for a human being like yourself.</li>
<li>On <strong>production</strong>, you want peak performance which means combining the JavaScript into one file and minimizing the code.</li>
</ul>
</li>
</ul>
<p><strong>JavaScript Performance Considerations:</strong></p>
<ul>
<li><strong>Minimize</strong> your code.</li>
<li><strong>Compress</strong> your files.</li>
<li><strong>Combine</strong> your files.</li>
<li>Get the browser to <strong>cache</strong> your files (but also make sure the browser isn’t using an outdated version).</li>
</ul>
<p><em>These performance considerations (and many, many others) come mainly from the work of <a href="http://stevesouders.com/">Steve Souders</a>. If you’re not familiar with his work in front-end optimizations, go read up.  We&#8217;ll be here when you get back.</em></p>
<p>The CloudFrontJavaScript package is my strategy for implementing the best practices in all of these areas.  The idea is to keep track of all of your JavaScript files in a couple of database tables, then use a class called the CloudFrontJavaScriptService to manage the resources on CloudFront and generate the SCRIPT tags with the proper source URLs to be inserted into your HTML page.</p>
<p>Before I describe the technical details and how to install and use the package, I am going to highlight a couple of key features of CloudFrontJavaScriptService:</p>
<h3>Maintenance Mode</h3>
<p>To facilitate website development, the CloudFrontJavaScriptService can be run in Maintenance Mode.  In Maintenance Mode, several things are different:</p>
<div class="wp-caption alignright" style="width: 210px"><a href="http://www.flickr.com/photos/ultimateslug/109566859/"><img src="http://assets.docmonk.com/ninja/caching.jpg" alt="" width="200" height="317" /></a><p class="wp-caption-text">Next time, try flushing your cache.</p></div>
<ul>
<li>JavaScripts are sent to the browser as the original source files.   They are not minimized, compressed or combined.  This is so that your browser development tools (e.g. Firebug) can work effectively.</li>
<li>A random string (called “cacheBust”) is appended to the script paths on each page refresh.  This is done just to make sure that your web browser does not cache any of your JavaScript, avoiding that frustrating development scenario that goes like this:
<ul>
<li>Adjust your code</li>
<li>Refresh</li>
<li>See no change</li>
<li>Make Another Change</li>
<li>Refresh</li>
<li>Still no change</li>
<li>Make Still Another Change</li>
<li>Refresh</li>
<li>“What’s wrong with me!?!”</li>
<li>Make a change that is absolutely guaranteed to completely break the program.</li>
<li>Refresh</li>
<li>&amp;%^#(%$)!!!</li>
</ul>
</li>
<li>The script files are served from your web server, not CloudFront.</li>
</ul>
<p>By providing Maintenance Mode, the CloudFrontJavaScriptService accommodates the needs of the development environment without adding to the work required to maintain the code and without making any compromises in performance on the production environment.</p>
<h3>Compression</h3>
<p>One of the major downsides of Amazon CloudFront compared to some other CDNs is that CloudFront will not automatically compress (i.e. gzip) your content for web browsers that support it.  Amazon is almost certainly developing this feature and could announce its availability at any time.   In the meantime, the CloudFrontJavaScriptService handles this for you.  The service does this by storing both the compressed and uncompressed versions on CloudFront.  When a page request comes in, it examines the headers for the HTTP_ACCEPT_ENCODING header to determine if gzip is supported.  It then returns the URL to either the compressed or uncompressed  version of the file.</p>
<h3>Versioning</h3>
<p>Both CloudFront edge locations and your users’ web browsers are going to cache your content.  This is what you want them to do in order to get the best possible performance from your website.  However, this creates an issue when your content changes because you can’t fully control when your users will see the updated content.</p>
<p>The CloudFrontJavaScript service handles this by maintaining a version number.  The version number is part of the URL of the JavaScript file.  The number is reset whenever a new version of your site is deployed.    This causes the URL of the JavaScript files to change.  Because a new URL indicates a completely new file, both CloudFront and the user’s browser are guaranteed to request the new version.  Consider the URL of “script 25” in CloudFrontJavaScriptService:</p>
<pre class="brush: plain; title: ; notranslate">

http://d5zgyj1bk6lvu.cloudfront.net/javascript/1285535650_25.gz.js
</pre>
<p>After deploying a new version, the URL of this resource might look like this</p>
<pre class="brush: plain; title: ; notranslate">

http://d5zgyj1bk6lvu.cloudfront.net/javascript/1285362461_25.gz.js
</pre>
<p>The large number is the version number and is also a Unix timestamp.  That value matches the time that the version was deployed, ensuring that caching does not prevent users from getting the most recent version of your JavaScript.</p>
<h3>The Database</h3>
<p>To help you get a sense of the underlying architecture of the service, here are the two database tables that keep track of the details:</p>
<p><a href="http://assets.docmonk.com/ninja/cloudfrontjavascript_tables.png" target="_blank"><img src="http://assets.docmonk.com/ninja/cloudfrontjavascript_tables.png" alt="CloudFrontImageService Database Tables" /></a></p>
<p>The <strong>tbl_javaScriptScript</strong> table contains the following fields:</p>
<ul>
<li><strong>id</strong> &#8211; The auto-incrementing primary key.</li>
<li><strong>lookupId</strong> &#8211; This is a unique number that you will assign to the script file and will be the number you use to indicate which script you’re requesting from the CloudFrontScriptService.  I prefer to increment the numbers by five and to make the lookupId be the same as the sortOrder.</li>
<li><strong>fileName</strong> &#8211; This is the file name of the script.  Each script will appear in your filesystem in two versions (one normal and one minimized).  In this field, the filename is displayed in the form to be used for the minimized version of the file.  The minimized form will be like this “yahoo_yahoo.js.”  In your development environment (where you will actually work the files) this file would appear in “yahoo” subdirectory and would appear like this “yahoo/yahoo.js”  The CloudFrontScriptService has a method in it for translating one form to the other.</li>
<li><strong>dependencies</strong> &#8211; This field contains a comma-delimited string of lookupIds which represent the dependencies of the script.  A typical value in this field would be “25,35,40” where the scripts with lookup ids of “25”, “35”, and “40” are dependencies of the current script.</li>
<li><strong>sortOrder</strong> &#8211; This field specifies the sort order the scripts.  When the CloudFrontScriptService determines which scripts (including dependencies) it needs to include in your webpage, it will order them in the order specified here.  Typically, I like to start out with the lookupIds and sortOrder as the same value.  For example, the file with a lookupId of 10 will start out with a sortOrder of 10.   If I find out later that things need to be reordered, I can just adjust the sortOrder without the much bigger hassle of rearranging the lookupIds.</li>
</ul>
<p>The <strong>tbl_javaScriptCDN</strong> table contains the following fields:</p>
<ul>
<li><strong>id</strong> &#8211; An auto-incrementing id.  Not the primary key and not currently used.  (The primary key is a composite of scriptIds and gzip.)</li>
<li><strong>scriptIds</strong> &#8211; This is a comma-separated list of the scriptIds that were requested.  If you request the script with lookupId 25, then the value in this field will be “25”.  If you request scripts 25 and 35 then the value will be “25,35”.  The dependencies of scripts 25 and 35 won’t be included here even though they would be sent to the browser.</li>
<li><strong>version</strong> &#8211; This indicates the version number of the scripts that are currently being served from Cloudfront.  If the version number in this row is out of date, the CloudfrontJavaScript service knows to rebuild the script package, upload it to CloudFront and update the version number in this table.</li>
<li><strong>gzip</strong> &#8211; This indicates whether the combined JavaScript file is gzipped.</li>
</ul>
<h3>Installation and Usage</h3>
<p>Download the <a href="http://github.com/awsninja/awsninja_cloudfrontjavascript">package</a> from GitHub and put it on your webserver.  You will also need the <a href="http://github.com/awsninja/awsninja_core">awsninja_core</a> package.</p>
<p><strong>YUI Components</strong><br />
To demonstrate how the CloudFrontJavaScriptService works with a large JavaScript project, the javascript directory in the package contains the JavaScript files from  the YUI Library.   If you want to test out the ability of the service to serve files to a web browser in Maintenance Mode, you will need to move the files to a location within your web root and change the CDN_JAVASCRIPT_SOURCE_PATH in config.php to match the new path.</p>
<p><strong>Steps to Get Set Up</strong></p>
<ol>
<li>Update the settings on config.samp.php and rename the file to config.php.</li>
<li>Run the sql in the ninja_cloudfrontimages.sql against your database to create the needed tables.</li>
<li>In the examples directory, run the yuiStoke.php script from the command line  (e.g.  type “php yuiStoke.php”) to populate the tbl_javaScriptScript table with the YUI script file information.  The yuiStoke.php script uses a <a href="http://old.nabble.com/Re:-yui-dependency-tree-for-use-in-php.-p22585940.html">dependency tree</a> created by jassem.shahrani to set up the YUI files.</li>
<li>Run the deploymentTest.php script from the command line.  This will minimize and copy the YUI JavaScript files to the js-minified directory.  It will also delete the version file, which will cause the CloudFrontJavaScriptService to create a new version number at the first opportunity.</li>
<li>Run the serviceTest.php script to see a demonstration of how the CloudFrontJavaScriptService generates HTML Script Tags.</li>
</ol>
<p>At step five, you know that you’ve got it set up correctly if you see output similar to this:<br />
<a href="http://assets.docmonk.com/ninja/coudfrontjavascript_output.png" target="_blank"><img src="http://assets.docmonk.com/ninja/coudfrontjavascript_output.png" alt="serviceTest.php output" /></a></p>
<p>The code in the example requests script 25, which is the YUI datasource.js script.  This script is dependent on event.js (script 10) which itself is dependent on yahoo.js (script 5).  In all of the examples, we use the getScriptHTML() method with the first argument 25.  See the serviceTest.php source for more details.</p>
<p><strong>The following uses are demonstrated:</strong></p>
<ul>
<li>Under <strong>“Here’s the uncombined script”</strong> you see that the datasource.js script and it’s dependencies are individually included.  The scripts are ordered according to the sort_order field in the database and a random “cacheBust” string is included at the end of the URLs.  This is ideal for the development environment, because your code will be properly broken out into files that are not minimized.  Your browser development tool (e.g. Firebug)  will have no problem directing you to your errors by file and line number.</li>
<li>Under <strong>“Here&#8217;s the combined uncompressed script:”</strong> you see that there  is a single file and it is being served from a CloudFront domain name.  The three JavaScript files are combined into one and minimized.  In this example, they are not compressed because this is an example of how the scripts would be served to browsers that do not support compression.</li>
<li>Under <strong>“Here&#8217;s the combined compressed script:”</strong> you see something very similar to the previous one.  The difference is that before the “.js” extension there is an extra “.gz” in the path.  This is the path to the combined, minimized and compressed file.</li>
<li>Under <strong>“Here&#8217;s how to let the web browser determine whether to compress or not:”</strong> the script echos out the most common way to use the service to insert script into HTML.  Basically, you just give it the script number you want and let the service figure out the best way to serve the script.</li>
<li>Finally, under <strong>“In the current context, that code produces this:”</strong> the script gives an example of what the script in the previous example outputs in the current context.  The context of this output is the command line, so it sends the combined and minimized (but not compressed) script. The reason it does not send the compressed script is that in the command line context, there is no browser HTTP_ACCEPT_ENCODING header.</li>
</ul>
<h3>How I Organize and Add New Scripts to my JavaScript Project</h3>
<p>There is one more thing that I would like to share about how I like to manage my scripts.  My general strategy is to separate my third party scripts (third-party libraries and plug-ins) from the scripts that I write specifically for the project that I’m working on.  I do this by including a large gap of lookupIds between the third-party components and my own components.  Here’s an example from one of my projects where I’m using jQuery and a bunch of jQuery plug-ins:<br />
<a href="http://assets.docmonk.com/ninja/projectfiles2.png"><img src="http://assets.docmonk.com/ninja/projectfiles2.png" alt="Project JavaScript Files" target="_blank" /></a><br />
Note that the third party code (jquery and jquery plug-ins) start at lookupId 1000 and my code (the “marketplace” files) start at lookupId 1500.  The gap between 1000 and 1500 provides plenty of room for me to add more third party components as needed.  The third-party components will always appear above my components, which is good because the third-party scripts are the dependencies.</p>
<p>When I need to add a new JavaScript file (either third-party or my own component), I add the file to the filesystem, then add the row directly to the database table.</p>
<p><strong>Conclusion:</strong><br />
I hope that you find this method of managing your JavaScript useful, and I hope that I was successful in clearly explaining how it works.  As always, I’d very much like to know what you think.  If you read this far, then for gosh sakes leave a comment and let me know!  It makes me happy.</p>
<img src="http://feeds.feedburner.com/~r/AwsNinja/~4/nDZ5LFgj7dE" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://awsninja.com/2010/09/28/a-php-framework-for-hosting-your-javascript-applications-on-cloudfront/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		<feedburner:origLink>http://awsninja.com/2010/09/28/a-php-framework-for-hosting-your-javascript-applications-on-cloudfront/</feedburner:origLink></item>
		<item>
		<title>A Simple Framework for Managing your Images, Instances, Volumes and Snapshots on EC2</title>
		<link>http://feedproxy.google.com/~r/AwsNinja/~3/PcmNgVNc9FQ/</link>
		<comments>http://awsninja.com/2010/09/07/a-simple-framework-for-managing-your-images-instances-volumes-and-snapshots-on-ec2/#comments</comments>
		<pubDate>Wed, 08 Sep 2010 00:47:03 +0000</pubDate>
		<dc:creator>Jay Muntz</dc:creator>
				<category><![CDATA[EC2]]></category>

		<guid isPermaLink="false">http://awsninja.com/?p=246</guid>
		<description><![CDATA[AWSNinja Code Library Name: awsninja_ec2resourcemanagement AWS Services: EC2 Source: at GitHub In a Sentence: A script framework for automating operations on EC2 resources When I first moved beyond simply playing around with EC2 and made the decision that I was actually going to build and deploy a web application on it, I quickly discovered that [...]]]></description>
			<content:encoded><![CDATA[<div class="librarybox">
<p><span class="libTitle">AWSNinja Code Library</span></p>
<p><span class="libSubTitle">Name:</span> awsninja_ec2resourcemanagement</p>
<p><span class="libSubTitle">AWS Services:</span> <a href="http://aws.amazon.com/ec2/">EC2</a></p>
<p><span class="libSubTitle">Source:</span> <a href="http://github.com/awsninja/awsninja_ec2resourcemanagement">at GitHub</a></p>
<p><span class="libSubTitle">In a Sentence:</span> A script framework for automating operations on EC2 resources</p>
</div>
<p>When I first moved beyond simply playing around with EC2 and made the decision that I was actually going to build and deploy a web application on it, I quickly discovered that it’s next to impossible to keep everything straight.</p>
<p>The reason for this is the heart of the difference between using actual computer hardware and using virtualization. Virtualization is more flexible because it has more parts.  That&#8217;s also the reason why it is more complicated.</p>
<p>With traditional hosting, you (or your hosting provider) build a server to a specification.  This involves capital investment because you have to purchase the hardware and locate it somewhere.  Once you’ve bought the hardware, you are stuck with it.  Changes to your configuration require new capital investment and may result in unwanted legacy components in your possession.  This costs time and money.</p>
<p><span id="more-246"></span></p>
<p>EC2 and other cloud-hosting services exist mainly for the purpose of eliminating these burdens.  But as is often the case, elimination of one problem creates a new one.  Since the problems associated with virtualization are newer, developers are not as adept at dealing with them yet.  We’re still learning.</p>
<p>The biggest problem is essentially this: The power to rearrange your hardware in real-time means that you now have much more to keep track of.  With traditional hosting, you were constrained by your inability to quickly add disk storage, RAM, CPU, or whatever.  You also may have been constrained in terms of your ability to quickly add new software.</p>
<p>Those constraints are now gone:</p>
<ul>
<li><strong>Need more hard disk space?</strong> Add it in five minutes.</li>
<li><strong>Need a backup?</strong> Take a snapshot.</li>
<li><strong>Running low on RAM?</strong> Spin up a high-memory instance and you’re back in business.</li>
</ul>
<p>But virtualization has created new questions, which you may not have answers for:</p>
<ul>
<li><strong>How will you keep track of that new volume you created?</strong></li>
<li><strong>How can you find that snapshot you created six weeks ago?</strong></li>
<li><strong>What’s the Instance-Id of that high-memory instance you started yesterday?</strong></li>
</ul>
<p><strong>Here is a partial-list of EC2 objects you will need to track:</strong></p>
<ul>
<li>Your <strong>Amazon Machine Images</strong>.  Each different type of server you use in your application will have an AMI.  Additionally, you may have multiple versions of those AMI’s that you need to keep track of. More about this below.</li>
<li>Your <strong>Instances</strong>.  Traditionally you will have a Development, Staging and Production environment, each consisting of one or more instances.  For instance you may have web and database servers in each environment.  That’s at least six instances right there.</li>
<li>Your <strong>Elastic Block Store Volumes</strong>.  EBS volumes provide wonderful flexibility for managing your data stores.  You may have volumes for your database, application root or for storing files such as images or PDF files.  Wonderful, if you can keep track of them.</li>
<li>Your <strong>EBS Snapshots</strong>.  The most common use of EBS Snapshots is to make backups of your EBS volumes.  You might have hundreds of these.  You may also need a plan for purging them when the time is right.</li>
</ul>
<h3>How I Organized my EC2 Resources</h3>
<p>For my applications, I’ve settled on using SimpleDB for the purpose of keeping track of all of my EC2 resources.  This has several advantages:</p>
<ul>
<li><strong>It’s free.</strong> The free tier of SimpleDB is more than adequate for this purpose.</li>
<li><strong>It’s always on.</strong> This is very important.  See below.</li>
<li><strong>It’s Amazon.</strong> If you’re familiar with other AWS services (ahem &#8211; why else would you be reading this?), you have a leg-up in learning SimpleDb.</li>
</ul>
<p>The “Always On” characteristic of SimpleDb is extremely useful for our purposes here.  It would make sense to keep track of your EC2 resources in a relational database like MySQL, except for the fact that you probably want to run your MySQL database on EC2.  There’s a chicken and egg problem in here.  Suppose you want to start up your MySQL instance?  If the Instance ID  and other information is sitting in your MySQL database, which isn’t running yet. . . . you see what I mean.</p>
<p>By keeping your EC2 resource information on SimpleDB, you can use it even when none of the resources of your application are running by running a SimpleDB client like <a href="http://awsninja.com/2010/07/08/simpledbadmin-a-phpmyadmin-like-interface-for-amazon-simpledb/">SimpleDBAdmin</a> or <a href="http://www.sdbexplorer.com/">SimpleDB Explorer</a>.</p>
<p>Another advantage of using SimpleDB to store information about your EC2 resources is that it makes it possible for your EC2 instances to identify themselves at boot time by running a boot script that queries SimpleDb.  This is an elegant and seamless way to start a new instance.  You can include a boot script which checks for its own EC2 Instance ID, looks itself  up in SimpleDb and then automatically configures all of the EBS Volumes and other resources that belong to it. The <em>EC2ResourceManagement</em> package includes an example of this.</p>
<h3>The Code</h3>
<p>The <em>EC2ResourceManagement</em> library consists of a few different services and two types of classes.  The <em>EC2Service</em> and <em>EC2Classes</em> interact with the Amazon EC2 API.  The <em>EC2Classes</em> represent objects like instances, volumes, AMIs and snapshots that exist in your EC2 account.  The <em>EC2ManagementService</em> and the <em>SimpleDBService</em> interact with SimpleDB.  The classes used by the <em>EC2ManagementService</em> (found in the <em>classes</em> directory of the library) represent records that are stored in SimpleDB and which are designed to represent EC2 objects and to keep track of how they are intended to be used.</p>
<h3>Getting Started</h3>
<p>To get started, download and unpack the <a href="http://github.com/awsninja/awsninja_ec2resourcemanagement">awsninja_ec2resourcemanagement</a> and <a href="http://github.com/awsninja/awsninja_core">awsninja_core</a> packages.  You’ll also need an AWS account with EC2 and SimpleDB enabled.</p>
<p>Add your credentials to the <em>config.samp.php</em> file and rename it to <em>config.php</em>.  Then try running a few of the scripts found in the examples directory (these are designed to be run from the command line).</p>
<p><strong>The following example scripts are included:</strong></p>
<ul>
<li><strong>buildEC2ResourceInventory.php</strong> &#8211; This is a good script to start with.  This script will examine your EC2 account and find the Images, Instances and Volumes that belong to you and will create records in SimpleDB to help you keep track of them.  To do this, it will ask you a few questions about what all of the different objects are for.  You’ll have better luck if you know the answers.</li>
<li><strong>attachVolume.php</strong> &#8211; This is a simple script that shows how to attach a volume to an instance.  You give it the Volume object, and the script will determine which instance to attach to and what device to use by looking up the details in SimpleDB.</li>
<li><strong>backups.php</strong> &#8211; This script will make snapshots of your Volumes and create Snapshot records in SimpleDB.  Perfect for backing up your data &#8211; and keeping track of what your snapshots are for.</li>
<li><strong>cloneVolume.php </strong>- This script will clone a volume and assign it to whatever instance you want.  For instance, if you wanted to clone the MySQL database volume on your development server  so that you could use an exact copy on your staging server, this script will do that.  Clones are accomplished by creating a snapshot, then creating a volume from that snapshot.  A record for your new Volume is created in SimpleDB and the new Volume becomes one of your managed EC2 resources.</li>
<li><strong>launchInstance.php </strong>- This will launch an instance from one of your images.  You only need to specify an Image and a role.  The role is something like “development,” “staging,” or “production.”</li>
<li><strong>listInstances.php</strong> &#8211; This simply lists your managed instances.  Simple enough.</li>
</ul>
<p>If you’ve got everything configured, you can run the buildEC2ResourceInventory.php to get your environment to create SimpleDB records for your Images, Instances and Volumes.  The script is intended to be run from the command line and will prompt you to answer some questions about your Images, Instances and Volumes.</p>
<p>When you run the buildEC2ResourceInventory.php, here are the questions you will get:</p>
<div class="wp-caption alignnone" style="width: 483px"><img src="http://docmonkcdn.s3.amazonaws.com/ninja/ec2resources_imageName.png" alt="What is the name of the image?" width="473" height="29" /><p class="wp-caption-text">The answer given here is &quot;WebServer.&quot;  The idea is to describe the purpose of the AMI that is being asked about.  Your &quot; WebServer&quot; could be launched into instances in multiple roles (i.e. Development, Staging, Production) - but presumably all of these instances would use the WebServer image.</p></div>
<p>Next, it asks about your Instances:</p>
<div class="wp-caption alignnone" style="width: 589px"><img src="http://docmonkcdn.s3.amazonaws.com/ninja/ec2resources_instanceRole.png" alt="What is the instance role?" width="579" height="76" /><p class="wp-caption-text">This question (asked regarding two instances in the image above) inquires about he role of individual Instances you are running. I have answered that one is the Development and one is Staging.</p></div>
<p>Then, it asks about your EBS Volumes:</p>
<div class="wp-caption alignnone" style="width: 634px"><img src="http://docmonkcdn.s3.amazonaws.com/ninja/ec2resources_volumeroleandpath.png" alt="What is the Volume Role and Path" width="624" height="196" /><p class="wp-caption-text">Next, the script inquires about our volumes. It asks the role of the Volume (&quot;application&quot; and &quot;database&quot; are the answers because these volumes hold the application root and the database files), then it asks what path on the Instance that these volumes should be mounted to. Note that the script does not ask what instance the volume is attached to or what the device address is. It gets that information from the EC2 api and will automatically configure those values.</p></div>
<p>Once the script is finished, you can look in your SimpleDB domains to see how your EC2 resources are mapped to records in SimpleDB</p>
<h3>Final Note</h3>
<p>The scripts in this package are not intended to be a turn-key solution for getting your stuff organized.   You will need to adjust and build on them for your own projects.  The main idea here is to provide you with a foundation on which you can start keeping track of your objects and automating operations on them to save time, reduce errors and increase the overall quality of the service you provide.</p>
<img src="http://feeds.feedburner.com/~r/AwsNinja/~4/PcmNgVNc9FQ" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://awsninja.com/2010/09/07/a-simple-framework-for-managing-your-images-instances-volumes-and-snapshots-on-ec2/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		<feedburner:origLink>http://awsninja.com/2010/09/07/a-simple-framework-for-managing-your-images-instances-volumes-and-snapshots-on-ec2/</feedburner:origLink></item>
		<item>
		<title>CloudWatch as an Ad-Hoc Debugging Tool</title>
		<link>http://feedproxy.google.com/~r/AwsNinja/~3/laRq17ZhbLU/</link>
		<comments>http://awsninja.com/2010/07/20/cloudwatch-as-an-ad-hoc-debugging-tool/#comments</comments>
		<pubDate>Wed, 21 Jul 2010 03:12:50 +0000</pubDate>
		<dc:creator>Jay Muntz</dc:creator>
				<category><![CDATA[CloudWatch]]></category>

		<guid isPermaLink="false">http://awsninja.com/?p=199</guid>
		<description><![CDATA[This post is not going to be long-winded dissertation on how CloudWatch can help you with debugging your applications.  It is just a quick description of a recent experience I had. I recently had an issue on DocMonk when the script that sends out the emails to the PDF recipients was crashing.  After checking it [...]]]></description>
			<content:encoded><![CDATA[<p>This post is not going to be long-winded dissertation on how CloudWatch can help you with debugging your applications.  It is just a quick description of a recent experience I had.</p>
<p>I recently had an issue on <a href="http://www.docmonk.com" target="_blank">DocMonk</a> when the script that sends out the emails to the PDF recipients was crashing.  After checking it out, I discovered that the crashes coincided with the startup of another script which handles backend aggregating for the reporting pages.  I was initially skeptical that this other script could really be causing such a problem.  I decided to try to see what else was going on on the server.  I started CloudWatch Monitoring on the server and went away for a few hours.</p>
<p>When I came back, this is what the CPU Utilization Chart looked like:<br />
<span id="more-199"></span></p>
<p><center><div class="img aligncenter" style="width:400px;">
	<a href="http://assets.docmonk.com/ninja/cpuspikes.png"><img src="http://assets.docmonk.com/ninja/cpuspikes.png" alt="Some Spiky CPU" width="400"  /></a>
	<div>Some Spiky CPU</div>
</div></center></p>
<p>Those spikes were happening every 15 minutes, which happens to be the frequency of the reportAggregator.php script &#8211; the reporting script I originally suspected.</p>
<p>Armed with new certainty that I was on the right track, I set about diagnosing the problem.  One SQL query was running very slowly, but only under certain conditions.  It looked like this:</p>
<pre class="brush: sql; title: ; notranslate">
SELECT * FROM tbl_pdfRecipient WHERE pdfOrigialId=:pdfOriginalId ORDER BY ID ASC LIMIT 0,100
</pre>
<p>Assuming you&#8217;ve got intelligent indexes on the table, this is a very fast query, but change the limit clause to &#8220;LIMIT 100000, 100&#8243; an it will be much, much slower.  If you&#8217;re going to be processing a lot pages of data, this is a very inefficient way to do it.</p>
<p>The solution was to query the minimum and maximum id values of the rows I&#8217;m querying for, then step through the pages by comparing the id values to ranges within the max and min range of the entire set.  The following queries demonstrate:</p>
<pre class="brush: sql; title: ; notranslate">
SELECT min(id), max(id) FROM tbl_pdfRecipient WHERE pdfOriginalId=:pdfOriginalId
/* Assume :min=1 and :max=1534.  We will grab these pages in groups of 100*/
/* Here's the efficient way to get all of the records */
SELECT * FROM tbl_pdfRecipient WHERE pdfOriginalId=:pdfOriginalId and id BETWEEN 1 AND 100;
SELECT * FROM tbl_pdfRecipient WHERE pdfOriginalId=:pdfOriginalId and id BETWEEN 101 AND 200;
SELECT * FROM tbl_pdfRecipient WHERE pdfOriginalId=:pdfOriginalId and id BETWEEN 201 AND 300;
SELECT * FROM tbl_pdfRecipient WHERE pdfOriginalId=:pdfOriginalId and id BETWEEN 301 AND 400;
SELECT * FROM tbl_pdfRecipient WHERE pdfOriginalId=:pdfOriginalId and id BETWEEN 401 AND 500;
SELECT * FROM tbl_pdfRecipient WHERE pdfOriginalId=:pdfOriginalId and id BETWEEN 501 AND 600;
SELECT * FROM tbl_pdfRecipient WHERE pdfOriginalId=:pdfOriginalId and id BETWEEN 601 AND 700;
/* and so fourth. . .*/
</pre>
<p>With this method, the 10,000th page would be retrieved just as quickly as the first.  Here&#8217;s the PHP code from the reportAggregator application.  Note that the SQL queries are not shown because they are abstracted away to other parts of the application.  This code is intended to show how to handle the looping and the <em>startId</em> and <em>endId</em> for the queries.</p>
<pre class="brush: php; title: ; notranslate">
$pageSize = 100;  //whatever your page size will be

//Initialize the start and end id values
$minId = PDFTO_domain_PDFRecipient::findMinByPDFOId($pdfo-&gt;getId());
$maxId = PDFTO_domain_PDFRecipient::findMaxByPDFOId($pdfo-&gt;getId());

//Initialize the first $startId and $endId
$startId = $minId;
$endId = $startId+$pageSize-1;

//Get the first page of results
$pdfRecpts = PDFTO_domain_PDFRecipient::findByPDFOIdAndIdRange($pdfo-&gt;getId(), $startId, $endId);
while($startId &lt;= $maxId)  //See how we will know when to stop it?
{
	foreach($pdfRecpts as $pdfRecpt) //Loop though the members of the page
	{
		/* DO SOMETHING WITH THE $pdfRecpt */
	}
	//Done with page, now set $startId and $endId for the next page
	$startId = $endId+1;
	$endId = $startId+$pageSize-1;

	//Run the next query - (this is at the bottom of the while loop because the first instance happens before we entered it)
	$pdfRecpts = PDFTO_domain_PDFRecipient::findByPDFOIdAndIdRange($pdfo-&gt;getId(), $startId, $endId);
}
//All done!
</pre>
<p>A few hours later after deploying this change, here what my CPU Utilization Chart looked like:<br />
<center><div class="img aligncenter" style="width:400px;">
	<a href="http://assets.docmonk.com/ninja/cloudwatch_allfixed.png" target="_blank"><img src="http://assets.docmonk.com/ninja/cloudwatch_allfixed.png" alt="All Fixed" width="400"  /></a>
	<div>All Fixed</div>
</div></center></p>
<p>Much better, I think.</p>
<img src="http://feeds.feedburner.com/~r/AwsNinja/~4/laRq17ZhbLU" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://awsninja.com/2010/07/20/cloudwatch-as-an-ad-hoc-debugging-tool/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://awsninja.com/2010/07/20/cloudwatch-as-an-ad-hoc-debugging-tool/</feedburner:origLink></item>
		<item>
		<title>SimpleDBAdmin – A "PHPMyAdmin-like" Interface for Amazon SimpleDB</title>
		<link>http://feedproxy.google.com/~r/AwsNinja/~3/NIVJMv7gIM8/</link>
		<comments>http://awsninja.com/2010/07/08/simpledbadmin-a-phpmyadmin-like-interface-for-amazon-simpledb/#comments</comments>
		<pubDate>Thu, 08 Jul 2010 13:15:47 +0000</pubDate>
		<dc:creator>Jay Muntz</dc:creator>
				<category><![CDATA[SimpleDb]]></category>

		<guid isPermaLink="false">http://awsninja.com/?p=142</guid>
		<description><![CDATA[AWSNinja Code Library Name: awsninja_simpledbadmin AWS Services: SimpleDB Source: at GitHub In a Sentence: A web interface for Amazon SimpleDB. SimpleDBAdmin is an administration tool for Amazon SimpleDB.   If you don’t know what SimpleDB is here’s the first paragraph from Amazon’s SimpleDB site: Amazon SimpleDB is a highly available, scalable, and flexible non-relational data store that [...]]]></description>
			<content:encoded><![CDATA[<div class="librarybox">
<p><span class="libTitle">AWSNinja Code Library</span></p>
<p><span class="libSubTitle">Name:</span> awsninja_simpledbadmin</p>
<p><span class="libSubTitle">AWS Services:</span> <a href="http://aws.amazon.com/simpledb/">SimpleDB</a></p>
<p><span class="libSubTitle">Source:</span> <a href="http://github.com/awsninja/awsninja_simpledbadmin">at GitHub</a></p>
<p><span class="libSubTitle">In a Sentence:</span> A web interface for Amazon SimpleDB.</p>
</div>
<div>SimpleDBAdmin is an administration tool for Amazon SimpleDB.   If you don’t know what SimpleDB is here’s the first paragraph from <a href="http://aws.amazon.com/simpledb/">Amazon’s SimpleDB site</a>:</div>
<div>
<div>
<blockquote><p>Amazon SimpleDB is a highly available, scalable, and flexible non-relational data store that offloads the work of database administration. Developers simply store and query data items via web services requests, and Amazon SimpleDB does the rest.</p></blockquote>
<h3>Why SimpleDBAdmin is Needed</h3>
<div>I started building SimpleDBAdmin because I wanted a package to administer my SimpleDB data that met the following criteria:</div>
<ul>
<li><strong>Web-based </strong>- so it could be used by anybody anywhere</li>
<li><strong>Free</strong> &#8211; for obvious reaons</li>
<li><strong>Intuitive to use</strong></li>
</ul>
<p><span id="more-142"></span></p>
<div>There are a couple of web-based SimpleDB managers out there, but I found them to be incredibly difficult to use for actually manipulating data. They seem to be designed for the purpose of teaching basic SimpleDB concepts to programmers.  That’s a laudable goal but it’s not what I was looking for.  <a href="http://www.awszone.com">AWSZone</a> and Amazon’s own <a href="http://developer.amazonwebservices.com/connect/entry.jspa?externalID=1137&amp;categoryID=148">JavaScript Scratchpad</a> expose all of the intricacies of the SimpleDB API and require you to perform actions like “Invoke Request” or use “PutAttributes.”  Rather than deal with all that, I wanted a package that provides a higher level of abstraction and focuses mainly on letting the user view and manipulate data. SimpleDBAdmin is designed to meet that need.</div>
</div>
<h3>How it was Built</h3>
<div>
<div>Because I wanted to make it possible to use the application on any platform, the vast majority of the application is written in JavaScript and based on JQuery.  In addition to JQuery and JQuery UI, the following packages are also used:</div>
<div>
<ul>
<li>The AWS Query Signer from <a href="http://sowacs.appspot.com/AWS/Downloads/">SonaCWS</a></li>
<li>Chris Domigan’s <a href="http://www.trendskitchens.co.nz/jquery/contextmenu/">Context Menu</a> plug-in for JQuery</li>
<li>Carhartl’s <a href="http://plugins.jquery.com/project/cookie">Cookie plug-in</a> for JQuery</li>
<li>The <a href="http://www.ibm.com/developerworks/xml/library/x-xml2jsonphp/">xmltojson php library</a> published on IBM developerWorks.</li>
</ul>
</div>
</div>
<div>
<div>Also included is a PHP component called <strong>relay.php</strong> that handles relaying the API commands to SimpleDB.  This is needed because the JavaScript <a href="http://docstore.mik.ua/orelly/webprog/jscript/ch21_03.htm">Same Origin</a> policy prevents a JavaScript application from sending requests to a separate domain name.  The relay.php component receives the completed request from the SimpleDBAdmin JavaScript package, passes it on to SimpleDB, receives the XML response from SimpleDB, converts it to JSON and passes it back to the JavaScript package.</div>
<div><strong>Note:</strong> Your AWS Secret Key is not sent to the relay.php script.  Instead, the signed request is created in JavaScript and sent to relay.php.  This prevents your Secret Key from being exposed in the internet traffic between the browser and server.</div>
<h3>SimpleDBAdmin Features</h3>
<div>
<div>
<ul>
<li>Supports saving multiple sets of AWS account credentials, useful if you manage SimpleDB data on multiple accounts.</li>
<li>Secret keys are encrypted and saved as cookies protected by a simple password.  You can access your SimpleDB account from the same computer without having to enter the AWS Access and Secret keys every time.</li>
<li>An elegant interface for storing, modifying and removing multiple values in the same attribute name.  Read about <a href="http://docs.amazonwebservices.com/AmazonSimpleDB/2009-04-15/DeveloperGuide/">SimpleDB’s data model</a> if you’re unfamiliar with SimpleDB’s ability to hold multiple values with the same attribute name.</li>
<li>Results are presented in a table format and are pageable.</li>
<li>Easily add and remove SimpleDB Domains.</li>
</ul>
</div>
</div>
<h3>Limitations and To-dos</h3>
<div>
<div>
<ul>
<li><strong>No Sorting</strong> &#8211; Currently, Domain contents are returned in SimpleDB&#8217;s default order.  I believe that this is the same as the chronological order that the items were added, but not sure if this is aways true.</li>
<li><strong>No Searching</strong> &#8211; The ability to search the items has not been added yet.</li>
<li><strong>Large Data</strong> &#8211; Domains with a large number of attribute names or large attribute values will not display optimally in the web browser.</li>
<li><strong>No Counts</strong> &#8211; The interface does not indicate the number of items in each Domain.</li>
</ul>
</div>
</div>
<h3>Installation</h3>
<div>To install SimpleDBAdmin, download the package from <a href="http://github.com/awsninja/awsninja_simpledbadmin">GitHub</a> and place the contents somewhere on your server’s web root.  Then navigate to the index.html with your web browser.  When you get it set up, it looks like this:</div>
<div>
<div class="wp-caption aligncenter" style="width: 520px"><div class="img " style="width:510px;">
	<img src="http://docmonkcdn.s3.amazonaws.com/ninja/simpledb_admin_installed.png" alt="Login Dialog" width="510" height="325" />
	<div>Login Dialog</div>
</div><p class="wp-caption-text">The Login Dialog</p></div>
</div>
<div>If it doesn’t work, you may need to adjust some of the paths within the index.html, relay.php or SimpleDbAdmin.js.</div>
</div>
<h3>Usage</h3>
<div>Once you’ve got the package installed and have the dialog shown above displayed in your browser, you then must enter your SimpleDB credentials.  To do this, fill in the form shown above with the following values:</div>
<div>
<div>
<ul>
<li><strong>Name</strong> &#8211; This is just the name that you want to give your account.  If you manage multiple SimpleDB accounts, this will help you keep track of them.</li>
<li><strong>Access Key</strong> &#8211; This is your AWS Access Key Id, which can be found from the<a href="https://aws-portal.amazon.com/gp/aws/developer/account/index.html?ie=UTF8&amp;action=access-key"> AWS Credentials page</a> when you are logged into the website.</li>
<li><strong>Secret Key</strong> &#8211; This is the AWS Secret Key associated with the Access Key and also found on the AWS Credentials Page.</li>
<li><strong>Password</strong> &#8211; This is a password chosen by you.  When you return to SimpleDBAdmin from the same web browser, the accounts you created will be available to you if you can enter the password.  The password is used to encrypt your Secret Key, so that it is not stored in plaintext in your browser’s cookies.</li>
</ul>
</div>
</div>
<div>Once you’ve entered your credentials, you should see your SimpleDB Domains (if any) listed on the left side of the screen.  You can click any of those Domains to browse through the data.  You can right click for the option to Delete a Domain (you will be asked to confirm this action).  You can also add a new Domain by clicking the “Add Domain” button.</div>
<div>
<div class="wp-caption aligncenter" style="width: 526px"><div class="img " style="width:516px;">
	<img src="http://docmonkcdn.s3.amazonaws.com/ninja/simpledb_admin_browsing.png" alt="Browse Data" width="516" height="315" />
	<div>Browse Data</div>
</div><p class="wp-caption-text">Browse Data</p></div>
<p>You can edit an item row by clicking on it.  Doing so brings up the Edit Item dialog box:</p>
<div class="wp-caption aligncenter" style="width: 510px"><div class="img " style="width:500px;">
	<img src="http://docmonkcdn.s3.amazonaws.com/ninja/simpledb_admin_editing.png" alt="Editing Data" width="500"  />
	<div>Editing Data</div>
</div><p class="wp-caption-text">Editing Data</p></div>
<p>Clicking the &#8220;Add Attribute Name&#8221; link will open a dialog that allows you to enter another name-value pair to the record.  When you are done making edits, click &#8220;Put&#8221; to save your changes.</p>
<h3>Online Sample</h3>
<p>You can give the application a try here:</p>
<p><a href="http://samples.awsninja.com/awsninja_simpledbadmin/">http://samples.awsninja.com/awsninja_simpledbadmin/</a></p>
<p>Please don&#8217;t use the sample application to manage live web applications or to view or manipulate any sensitive data.  The application is not configured to examine or log your data -but you should install your own copy of SimpleDBAdmin to be completely secure.</p>
<p>If you&#8217;d like to install a copy on your own server, <a href="http://github.com/awsninja/awsninja_simpledbadmin/downloads">download</a> it from GitHub.</p>
<p>I welcome questions, comments or suggestions.  Thanks for reading.</p>
</div>
</div>
<img src="http://feeds.feedburner.com/~r/AwsNinja/~4/NIVJMv7gIM8" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://awsninja.com/2010/07/08/simpledbadmin-a-phpmyadmin-like-interface-for-amazon-simpledb/feed/</wfw:commentRss>
		<slash:comments>14</slash:comments>
		<feedburner:origLink>http://awsninja.com/2010/07/08/simpledbadmin-a-phpmyadmin-like-interface-for-amazon-simpledb/</feedburner:origLink></item>
	</channel>
</rss>

