OWASP O2 Platform Blog

O2 Script to create an Amazon EC2 Image

If you want to automate the creation of an EC2 image  (for example the O2 Platform one) , here is a script that does that:

Gui Screenshot:

Source Code:


//var topPanel = panel.clear().add_Panel();
var topPanel = "start amazon instance".popupWindow();
var apiKey = @"C:\....\accounts.xml".credential("AmazonAWS");

var amazonEC2 = new API_AmazonEC2(apiKey);
var ec2Client =  amazonEC2.getEC2Client();

var width = 400;
var height = 150;

var createPanel = topPanel.add_GroupBox("Create amazon EC2 Instance")
.fill(false)
.width(width).height(height)
.add_Panel();
var imageID = createPanel.add_Label("Image Id:",5,0)
.append_Control<ComboBox>()
.width(200)
.top(0).left(90);
imageID.append_Link("View Image's List",
()=>amazonEC2.show_ImagesList_In_TreeView(ec2Client))
.top(5);

var imageSize =createPanel.add_Label("Image Size:",30,0)
.append_Control<ComboBox>()
.dropDownList()
.top(25).left(90);

var securityGroup = createPanel.add_TextBox(60,"Security Group","").left(90).width(120);
var keyName = createPanel.add_TextBox(80,"Pem Key name","").left(90).width(120);

var defaultImages = new Dictionary<string,string>();
defaultImages.add("O2 Platform Image", "OWASP O2 Platform - Windows 2008")
.add("Amazon Win 2008 32bit IIS+SQL", "Windows-Server2008-i386-SqlExpress-v103")
.add("Amazon Win 2008 64bit IIS+SQL", "Windows-2008R2-SP1-English-SQLExpress-v101")
.add("Amazon Win 2008 64bit IIS+SQL", "Windows-Server2003R2-i386-SqlExpress-v109")
.add("Microsoft Win 2008 64bit IIS+SQL", "Optimized-SQL-Server-2008R2-3-2-11");

imageID.add_Items(defaultImages.keys());

imageSize.add_Items(new List<string> {"m1.small", "t1.micro", "c1.medium","m1.large", "m1.xlarge"});
imageID.select_Item(0);
imageSize.select_Item(0);

securityGroup.set_Text("O2 Boxes");
keyName.set_Text("O2 Key");

var statusMessage = createPanel.add_Label("...", 90,230);
createPanel.add_Button("Launch Image", 60,230)
.align_Right(createPanel).widthAdd(-10)
.onClick(()=>{
statusMessage.set_Text("...launching image").textColor(Color.DarkBlue);
try
{
var imageId = imageID.get_Text();
if (defaultImages.hasKey(imageId))
imageId = amazonEC2.getImagesList(ec2Client).name(defaultImages[imageId]).ImageId;
"using imageId: {0}".info(imageId);
var runningInstance = ec2Client.launchInstance(imageId,
imageSize.get_Text(),
securityGroup.get_Text(),
keyName.get_Text());
statusMessage.set_Text("done, created instance: {0}".format(runningInstance.InstanceId)).textColor(Color.DarkGreen);
}
catch(Exception ex)
{
statusMessage.set_Text(ex.Message).textColor(Color.Red);
ex.log();
}

});
return "done";

//here are a number of code snippets that show the multiple methods available in the API_AmazonEC2

//using Amazon.EC2.Model
//using Amazon.EC2

//return images.description("WebMatrix Hosting Server provided by Microsoft");
//return images.description_Contains("Amazon Linux");
//return images.amazon().description_RegEx("windows.*32");

//return images.name_Contains("amzn-ami");
//return images.name_RegEx("amzn.*i386");

//return images.imageId(".....");
//return images.imageId("ami-9d1043d8");
//return <a href="mailto:images.@public().amazon().windows">images.@public().amazon().windows</a>();
//return <a href="mailto:images.@public().amazon()._32Bit">images.@public().amazon()._32Bit</a>();
//return <a href="mailto:images.@public().amazon()._64Bit">images.@public().amazon()._64Bit</a>();
//return <a href="mailto:images.@public().amazon">images.@public().amazon</a>();
//return <a href="mailto:images.@public().microsoft">images.@public().microsoft</a>();
//return <a href="mailto:images.@public()._32Bit">images.@public()._32Bit</a>();
//return <a href="mailto:images.@public()._64Bit">images.@public()._64Bit</a>();
//return <a href="mailto:images.@private">images.@private</a>();
//return <a href="mailto:images.@private">images.@private</a>();
//amazonEC2.show_ImagesList_In_TreeView(ec2Client,topPanel);

return "ok";
//O2File:API_AmazonEC2.cs
//O2Ref:AWSSDK.dll

O2 Platform EC2 Image

Note: if you want to use the Amazon Web Interface to start the O2 AMI, here is how to find it (NOTE that this is in US West):

November 23, 2011 Posted by | EC2 | Leave a comment

O2 Platform Amazon EC2 Image (AMI)

If you want to take O2 for a test drive and don’t have a windows box (or VM) at hand, now you can use Amazon EC2.

Here are the steps to take:

  • Login to Amazon AWS account,
  • Go to EC2 (if needed choose the desired region)
  • Go to the Instances Section
  • Click on ‘Launch Instance
  • Search for O2     (the full name of this AMI is ‘727618846505/OWASP O2 Platform – Windows 2008’)
  • Click Select (and follow the wizard till the end)

After a couple minutes, you will be able to RDP into your VM.

The default administrator password is: mK-jv7sj@L

After login, start O2 so that it updates the rules, and you are all set 🙂

Let me know if you have any issues using this Amazon EC2 image

July 18, 2011 Posted by | EC2 | Leave a comment

Using ‘Amazon S3 Browser’ script to upload files to Amazon S3

If you have an Amazon S3 account (http://aws.amazon.com/s3/) then you might find useful to use the ‘Amazon S3 Browser.h2’ script to upload files to the S3 servers (you can also create folders and delete files)

To upload files, select the target foldder (top left treeview) and  just drop the desired file on the the bottom left treeview (the red color indicates that the file is being uploaded)

When the upload has completed, the bottom treeview will refresh and show the uploaded file there:

To get the link to the file, click on it and copy it from the top right textbox

For small files (like images or html files) you can get a quick preview by selecting the ‘Auto Preview Selected File’ checkbox

Note that when you upload files using this GUI/Script the file permission will be set to public (the default is to make it private).

The ‘Amazon S3 Browser.h2‘ script (shown below) consumes the API_AmazonS3.cs file and is mainly focused on building the GUI:

//O2Ref:WatiN.Core.1x.dll
var topPanel = O2Gui.open<Panel>("Amazon S3 Browser",700,400);
var autoPreviewSelectedFile = false;
var amazonS3 = new API_AmazonS3();  </pre>
&nbsp;

topPanel.add_Label("Logging in to S3", 150,300);
amazonS3.login();
topPanel.clear();
var statusLabel = topPanel.parentForm().add_StatusStrip(); 
statusLabel.set_Text("Welcome to O2's Amazon S3 Browser (click on folder to see files)");
var foldersTreeView = topPanel.add_TreeView()
                           .showSelection();
                          
var previewArea = foldersTreeView.insert_Right<Panel>(topPanel.width() /2 ).add_1x1("Selected File Url", "Selected File Contents",false, 65) ;
var previewPanel = previewArea[1];
var selectFile = previewArea[0].add_TextBox().fill();
previewArea[0].add_CheckBox("Auto Preview selected File (to see single files just press enter above)",40,4, (value) => autoPreviewSelectedFile = value).autoSize(); 

var filesTreeView = foldersTreeView.insert_Below<TreeView>(topPanel.height()/2)
                                   .showSelection();  

MethodInvoker refreshFolders =
    ()=>{
            foldersTreeView.clear();
            foldersTreeView.add_Nodes(amazonS3.folders());
        };
       
MethodInvoker refreshFileView =
    ()=>{
            amazonS3.showFilesInTreeView(filesTreeView, foldersTreeView.selected().get_Text());           
        };       
                                  
foldersTreeView.insert_Below<Panel>(25)  
               .add_LabelAndTextAndButton("New folder name:", "", "create",
                           (newFolderName)=>
                               {
                                statusLabel.set_Text("Creating folder:{0}".format(newFolderName));
                                   if (amazonS3.create_Folder(newFolderName).valid())
                                   {
                                       foldersTreeView.clear();                                      
                                    foldersTreeView.add_Nodes(amazonS3.folders());   
                                   };
                               });
filesTreeView.onDrop(
    (fileOrFolder)=>{
                        if (fileOrFolder.isFile())
                        {
                            filesTreeView.backColor(Color.LightPink);
                            O2Thread.mtaThread(
                                ()=>{
                                        statusLabel.set_Text("adding file:{0}".format(fileOrFolder));
                                        var currentFolder = foldersTreeView.selected().get_Text();
                                        amazonS3.add_S3_Object(currentFolder, fileOrFolder);
                                        amazonS3.showFilesInTreeView(filesTreeView, currentFolder);                           
                                        statusLabel.set_Text("Done");
                                        filesTreeView.backColor(Color.White);
                                    });
                        }
                           
                    });
  
var foldersContextMenu = foldersTreeView.add_ContextMenu();
var filesContextMenu = filesTreeView.add_ContextMenu();

//menu actions 
foldersContextMenu.add_MenuItem("Delete Folder", 
                            ()=>{
                                    var folderToDelete = foldersTreeView.selected().get_Text();
                                    if ("Are you sure you want to Delete the folder: {0}".format(folderToDelete).askUserQuestion())
                                        if (amazonS3.delete_Folder(folderToDelete).valid())                                      
                                        {
                                            statusLabel.set_Text("Deleting folder:{0}".format(folderToDelete));
                                               refreshFolders();
                                           }
                                });
 
filesContextMenu.add_MenuItem("Delete File", 
                            ()=>{
                                    //filesTreeView.SelectedNode =
                                    var currentFolder = foldersTreeView.selected().get_Text();
                                    var fileToDelete = filesTreeView.selected().get_Text();
                                    if ("Are you sure you want to Delete the file: {0}".format(fileToDelete).askUserQuestion())                                   
                                    {
                                        statusLabel.set_Text("Deleting File:{0}".format(fileToDelete));
                                        if (amazonS3.delete_File(currentFolder, fileToDelete).valid())                                      
                                            amazonS3.showFilesInTreeView(filesTreeView, currentFolder);
                                    }
                                });

// events
foldersTreeView.afterSelect<string>(
    (folder) =>{
                    statusLabel.set_Text("Showing files in folder: {0}".format(folder));
                    refreshFileView();
                });

filesTreeView.afterSelect<Uri>(
    (uri)=>    {               
                var url = uri.str();
                "url: {0}".info(url);
                statusLabel.set_Text("Showing details for file: {0} ".format(url));
                selectFile.set_Text(url);               
                if (autoPreviewSelectedFile)
                    amazonS3.showFileInControl(previewPanel, uri);                                       
            });

selectFile.onEnter(
    (url)=> {               
                amazonS3.showFileInControl(previewPanel, url.uri());       
             });

// ContextMenu

filesContextMenu.add_MenuItem("Refresh", refreshFileView);

var folders = amazonS3.folders();
foldersTreeView.add_Nodes(folders);   
amazonS3.showFilesInTreeView(filesTreeView,"");

return "done";
//using O2.External.IE.ExtensionMethods

//O2File:API_AmazonS3.cs
//O2Ref:AWSSDK.dll
//O2Ref:O2_External_IE.dll
//O2Ref:System.Xml.dll
//O2Ref:System.Xml.Linq.dll

 

July 16, 2011 Posted by | EC2, Interoperability, WatiN | Leave a comment

New Amazon EC2 ‘image filtering focused’ Extension Methods

I just added a number of extension methods to the O2 Amazon EC2 API that help to easily find images

Here are the new ‘image filtering focused’ extension methods in action

var apiKey = @"C:\O2\_USERDATA\accounts.xml".credential("AmazonAWS");
   
var amazonEC2 = new API_AmazonEC2(apiKey);
var ec2Client =  amazonEC2.getEC2Client();  
 
amazonEC2.CachedImageListRequest = @"C:\O2\_tempDir\4-16-2011\tmp8DC3.tmp.xml"; 
 
 
var images = amazonEC2.getImagesList(ec2Client);         
 
//return images.description("WebMatrix Hosting Server provided by Microsoft"); 
//return images.description_Contains("Amazon Linux");
return images.amazon().description_RegEx("windows.*32");
//return images.name("WebMatrixHostingServer");  
//return images.name_Contains("amzn-ami");   
//return images.name_RegEx("amzn.*i386");  </pre>
 

//return images.imageId(".....");      
//return images.imageId("ami-9d1043d8");  
//return images.@public().amazon().windows();
//return images.@public().amazon()._32Bit(); 
//return images.@public().amazon()._64Bit(); 
//return images.@public().amazon();    
//return images.@public().microsoft();  
//return images.@public()._32Bit();  
//return images.@public()._64Bit();    
//return images.@private();   
//return images.@private();  

And here is the  class added to the O2 Amazon EC2 API

public static class API_AmazonEC2_ExtensionMethods_Images
    {   
        //Visibility
        public static List<Image> @public(this List<Image> images)
        { 
            return images.where(image=>image.Visibility == "Public");
        }
       
        public static List<Image> @private(this List<Image> images)
        { 
            return images.where(image=>image.Visibility == "Private");
        }
       
        //Architecture
        public static List<Image> _32Bit(this List<Image> images)
        { 
            return images.where(image=>image.Architecture == "i386");
        }
       
        public static List<Image> _64Bit(this List<Image> images)
        { 
            return images.where(image=>image.Architecture == "x86_64");
        }
       
        //ImageOwnerAlias
        public static List<Image> amazon(this List<Image> images)
        { 
            return images.where(image=>image.ImageOwnerAlias == "amazon");
        }
       
        public static List<Image> microsoft(this List<Image> images)
        { 
            return images.where(image=>image.ImageOwnerAlias == "microsoft"); 
        }
       
        //Platform
        public static List<Image> windows(this List<Image> images)
        { 
            return images.where(image=>image.Platform == "windows"); 
        }       
       
        //ImageId
        public static Image imageId(this List<Image> images, string imageId)
        { 
            return images.where(image=>image.ImageId == imageId).first(); 
        }       
       
        //Name
       
        public static Image name(this List<Image> images, string name)
        { 
            return images.where(image=>image.Name == name).first();
        }       
       
        public static List<Image> name_Contains(this List<Image> images, string name)
        { 
            return images.where(image=>image.Name.contains(name));
        }       
       
        public static List<Image> name_RegEx(this List<Image> images, string name)
        { 
            return images.where(image=>image.Name.regEx(name));
        }       
       
        //Description
        public static Image description(this List<Image> images, string description)
        { 
            return images.where(image=>image.Description == description).first(); 
        }       
       
        public static List<Image> description_Contains(this List<Image> images, string description)
        { 
            return images.where(image=>image.Description.contains(description));
        }       
       
        public static List<Image> description_RegEx(this List<Image> images, string description)
        { 
            return images.where(image=>image.Description.regEx(description));
        }       
       
        //this quite an expensive operation (3M of data retrieved) - so I added caching support
        public static List<Image> getImagesList(this API_AmazonEC2 amazonEC2, AmazonEC2Client ec2Client)
        {                                       
            if (amazonEC2.CachedImageListRequest.fileExists())
                return amazonEC2.CachedImageListRequest.load<List<Amazon.EC2.Model.Image>>();
               
            var describeImagesRequest = new DescribeImagesRequest();                
            "Retrieving ImagesList from Amazon..".info();   
            var images = ec2Client.DescribeImages(describeImagesRequest)
                      .DescribeImagesResult.Image;
            if (images.isNull() || images.size()==0)
            {
                "in getImagesList, there was an error retrieving list (are we online?)".error();               
            }
            else
            {
                amazonEC2.CachedImageListRequest = images.save();
                "The Image List was saved to : {0}".info(amazonEC2.CachedImageListRequest); 
            }
            return images;
        }
    }

 

I also made a change in the formula used to populate the TreeView with the available images so that the images with the same name are all grouped together 

April 17, 2011 Posted by | EC2 | Leave a comment

Script to view Amazon EC2 Images List

I just added a couple new methods to the O2’s Amazon EC2 API which provide details about the available AMIs (Amazon Machine Images).

The new capabilities are now avaialble on the Amazon EC2 Browser:

 

… click on the View Available Images (AMIs) link a

…which will popup a new window:

… that will load the data from Amazon (the blue color indicates that it is fetching data):

To help to navigate through the large amount of AMIs available, a couple filters were added:

When expanded will show the list of Images on that category , and when clicked on a AMI node,  its details will show on the right:

Source code

Here is how to consume directly this feature

var apiKey = @"C:\O2\_USERDATA\accounts.xml".credential("AmazonAWS");
   
var amazonEC2 = new API_AmazonEC2(apiKey);
var ec2Client =  amazonEC2.getEC2Client(); </pre>
 

amazonEC2.show_ImagesList_In_TreeView(ec2Client); 
 
//O2File:API_AmazonEC2.cs
//O2Ref:AWSSDK.dll

the code above has no cache support, which is show below:

var apiKey = @"C:\O2\_USERDATA\accounts.xml".credential("AmazonAWS");
   
var amazonEC2 = new API_AmazonEC2(apiKey);
var ec2Client =  amazonEC2.getEC2Client(); </pre>
 

amazonEC2.CachedImageListRequest = @"C:\O2\_tempDir\4-16-2011\tmp8DC3.tmp.xml"; 
amazonEC2.show_ImagesList_In_TreeView(ec2Client); 
 
//O2File:API_AmazonEC2.cs
//O2Ref:AWSSDK.dll

Here are the new methods thare were added to O2’s Amazon EC2 API :

        //this quite an expensive operation (3M of data retrieved) - so I added caching support
        public static List<Image> getImagesList(this API_AmazonEC2 amazonEC2, AmazonEC2Client ec2Client)
        {                                       
            if (amazonEC2.CachedImageListRequest.fileExists())
                return amazonEC2.CachedImageListRequest.load<List<Amazon.EC2.Model.Image>>();
               
            var describeImagesRequest = new DescribeImagesRequest();                
            "Retrieving ImagesList from Amazon..".info();   
            var images = ec2Client.DescribeImages(describeImagesRequest)
                      .DescribeImagesResult.Image;
            if (images.isNull() || images.size()==0)
            {
                "in getImagesList, there was an error retrieving list (are we online?)".error();               
            }
            else
            {
                amazonEC2.CachedImageListRequest = images.save();
                "The Image List was saved to : {0}".info(amazonEC2.CachedImageListRequest); 
            }
            return images;
        }</pre>
 

        public static List<Image> show_ImagesList_In_TreeView(this API_AmazonEC2 amazonEC2)
        {
            return amazonEC2.show_ImagesList_In_TreeView(amazonEC2.getEC2Client());
        }
       
        public static List<Image> show_ImagesList_In_TreeView(this API_AmazonEC2 amazonEC2, AmazonEC2Client ec2Client)
        {
            return amazonEC2.show_ImagesList_In_TreeView(ec2Client, "Amazon EC2 Images List".popupWindow());
        }               
       
        public static List<Image> show_ImagesList_In_TreeView(this API_AmazonEC2 amazonEC2, AmazonEC2Client ec2Client, Control control)
        {               
            var treeView = control.clear().add_TreeView_with_PropertyGrid(false).sort();      
            treeView.backColor(System.Drawing.Color.Azure);
            Application.DoEvents();
            var imagesList = amazonEC2.getImagesList(ec2Client);
            Func<Amazon.EC2.Model.Image,string> imageName =
                (image)=> (image.Description.valid())
                                    ? "{0} - {1}".format(image.Description, image.Name)
                                    : "{0}".format(image.Name);
            Action<string> mapByProperty  =
                (propertyName)=>{               
                                    var visibilityNode = treeView.add_Node("by {0}".format(propertyName));
                                    foreach(var visibility in imagesList.Select((image)=>image.property(propertyName).str()).Distinct())
                                        visibilityNode.add_Node(visibility)
                                                      .add_Nodes(imagesList.Where((image) => image.property(propertyName).str() == visibility),
                                                                   imageName);
                                };
            mapByProperty("Visibility");
            mapByProperty("ImageOwnerAlias");
            mapByProperty("Platform");
            mapByProperty("Architecture");
            "Completed processing show_ImagesList_In_TreeView".info();
            if (treeView.nodes().size()>0)
                treeView.backColor(System.Drawing.Color.White);
            return imagesList;
        }

April 16, 2011 Posted by | EC2 | Leave a comment

Using the O2’s Amazon EC2 API

Here are a number of code snippets that show how to use the O2’s Amazon EC2 API.

All scripts should be executed from an O2 Script Editor (ideally a ‘Quick Development Gui’ since we will be using the provided panel in a couple examples:

 

Getting a fully logged-in AmazonEC2Client instance

var apiKey = @"C:\O2\_USERDATA\accounts.xml".credential("AmazonAWS");
   
var amazonEC2 = new API_AmazonEC2(apiKey);
var ec2Client = amazonEC2.getEC2Client();
return ec2Client.typeName();
//O2File:API_AmazonEC2.cs
//O2Ref:AWSSDK.dll

 

Getting a fully logged-in AmazonEC2Client instance in a specific region

The previous example connects to the default region on this API, which is  set to

 DefaultRegion = "us-west-1"; 

If you want to open a specific region, you can specify it as a parameter to the getEC2Client method. This next example returns is equivalent to the previous one

var amazonEC2 = new API_AmazonEC2(apiKey);
var ec2Client = amazonEC2.getEC2Client(amazonEC2.DefaultRegion);
return ec2Client;

and this one will connect to the europan EC2 data center:

var amazonEC2 = new API_AmazonEC2(apiKey);
var ec2Client = amazonEC2.getEC2Client("eu-west-1");
return ec2Client;

 

Retrieve list of Instances in default region

var amazonEC2 = new API_AmazonEC2(apiKey);
return amazonEC2.getEC2Instances(); 

 

Retrieve list of Instances in all regions

var amazonEC2 = new API_AmazonEC2(apiKey);
return amazonEC2.getEC2Instances(false);  

 

Visualize in a TreeView the data received from the getEC2Instances

var amazonEC2 = new API_AmazonEC2(apiKey);
var instancesData =  amazonEC2.getEC2Instances();
var instancesViewer = topPanel.add_TreeView();
foreach(var instanceMapping in instancesData)
    instancesViewer.add_Node(instanceMapping.Key)                 
                   .add_Nodes(instanceMapping.Value ,
                                (runningInstance)=>amazonEC2.getRunningInstanceSignature(runningInstance));

  

 

Get an Instance Object

To get an instance object you will need to drill the object returned from the getEC2Instances method

var amazonEC2 = new API_AmazonEC2(apiKey);
var instance =  amazonEC2.getEC2Instances().Values.First()[0];
return instance;

  

View Instance details – Mode 1

var amazonEC2 = new API_AmazonEC2(apiKey);
var instancesData =  amazonEC2.getEC2Instances();
var instance =  amazonEC2.getEC2Instances().Values.First()[0];
instance.showInfo();

 

View instance details – Mode 2

var amazonEC2 = new API_AmazonEC2(apiKey);
var instancesData =  amazonEC2.getEC2Instances();
var instance =  amazonEC2.getEC2Instances().Values.First()[0];
instance.details();

 

Starting and Stopping Instances

var amazonEC2 = new API_AmazonEC2(apiKey);
var instancesData =  amazonEC2.getEC2Instances();
var instance =  amazonEC2.getEC2Instances().Values.First()[0];
amazonEC2.startInstance(instance);
amazonEC2.stopInstance(instance); 

 

Viewing Console Out in separate window

var amazonEC2 = new API_AmazonEC2(apiKey);
var instancesData =  amazonEC2.getEC2Instances();
var instance =  amazonEC2.getEC2Instances()["SI Boxes"][1];
amazonEC2.showConsoleOut(instance);

Retrieving Instance Password

var amazonEC2 = new API_AmazonEC2(apiKey);
var instancesData =  amazonEC2.getEC2Instances();
var instance =  amazonEC2.getEC2Instances()["SI Boxes"][2];
amazonEC2.ApiRsa = new API_RSA();
return amazonEC2.getPassword(instance);


 If you don’t provide the path of a PEM file in the API_RSA(…) constructor you will be prompt for it

once you provide the PEM key, you can see the fetched data in the Log Viewer

or in the case of the script above, in the Invoke and Result output TextArea

 

April 16, 2011 Posted by | EC2 | 1 Comment

New Amazon EC2 .Net API

I just refactored the Amazon EC2 Browser so that most of its scripts are now in the API_AmazonEC2.cs file (which is a great API to access Amazon EC2 images)

This is what the new version of the Amazon EC2 Browser tool looks like (I added support for decrypting the Instance’s passwords using a *.pem file)

You can open it by executing the Tool – Amazon EC2 Browser.h2 script

Amazon_EC2.cs

This is what the Amazon_EC2.cs API looks like

// This file is part of the OWASP O2 Platform (<a href="http://www.owasp.org/index.php/OWASP_O2_Platform">http://www.owasp.org/index.php/OWASP_O2_Platform</a>) and is released under the Apache 2.0 License (<a href="http://www.apache.org/licenses/LICENSE-2.0">http://www.apache.org/licenses/LICENSE-2.0</a>)
using System;
using System.Threading;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Windows.Forms;
using System.Text;
using O2.Kernel;
using O2.Kernel.ExtensionMethods;
using O2.DotNetWrappers.DotNet;
using O2.DotNetWrappers.ExtensionMethods;
using O2.Views.ASCX.ExtensionMethods;
using O2.Views.ASCX.classes.MainGUI;
using O2.XRules.Database.Utils;
using O2.External.SharpDevelop.ExtensionMethods;
using Amazon.EC2;
using Amazon.EC2.Model;</pre>
 

//O2Ref:AWSSDK.dll
//O2File:ascx_AskUserForLoginDetails.cs   
//O2File:API_GuiAutomation.cs
//O2File:API_RSA.cs

//O2File:_Extra_methods_To_Add_to_Main_CodeBase.cs

namespace O2.XRules.Database.APIs
{   
    public class API_AmazonEC2
    {           
        public ICredential ApiKey { get; set; }
        public string DefaultRegion { get; set; }
        public API_RSA ApiRsa { get; set; }
       
        public int TimerCount = 60;
        public int TimerSleep  = 60 * 1000;

       
        public API_AmazonEC2() : this(null)
        {
           
        }       
       
        public API_AmazonEC2(ICredential apiKey)
        {
            DefaultRegion = "us-west-1";//"eu-west-1";
            if (apiKey.isNull())
                apiKey = ascx_AskUserForLoginDetails.ask();
            ApiKey = apiKey;
        }
    }
   
    public static class API_AmazonEC2_ExtensionMethods
    {
        public static List<string> getEC2Regions(this API_AmazonEC2 amazonEC2)
        {
            var ec2Client = new AmazonEC2Client(amazonEC2.ApiKey.UserName, amazonEC2.ApiKey.Password);
            return (from region in  ec2Client.DescribeRegions(new DescribeRegionsRequest())
                                                .DescribeRegionsResult.Region
                    select region.RegionName).toList();
        }
       
        public static AmazonEC2Client getEC2Client(this API_AmazonEC2 amazonEC2, string region)
        {
            return new AmazonEC2Client(amazonEC2.ApiKey.UserName,
                                        amazonEC2.ApiKey.Password, new AmazonEC2Config()
                                                                    {ServiceURL = "<a href="http://%7b0%7d.ec2.amazonaws.com%22.format(region/">http://{0}.ec2.amazonaws.com".format(region</a>)});
        }
       
       
        public static List<Reservation> getReservationsInRegion(this API_AmazonEC2 amazonEC2, string region)
        {
                "Gettting Reservations in region: {0}".info(region);
                var ec2ClientInRegion = amazonEC2.getEC2Client(region);
                var describesInstance = new DescribeInstancesRequest();                
                var reservations = ec2ClientInRegion.DescribeInstances(describesInstance)
                                                    .DescribeInstancesResult
                                                    .Reservation;                
                return reservations;                                     
        }
       
        public static Dictionary<string,List<RunningInstance>> getEC2Instances(this API_AmazonEC2 amazonEC2,bool onlyShowDefaultRegion)
        {       
            var instances = new Dictionary<string,List<RunningInstance>>();       
           
            var reservations = new List<Reservation>();
            if (onlyShowDefaultRegion)
                reservations.add(amazonEC2.getReservationsInRegion(amazonEC2.DefaultRegion));
            else
                foreach(var region in amazonEC2.getEC2Regions())
                    reservations.add(amazonEC2.getReservationsInRegion(region));                       
                       
            foreach(var reservation in reservations)
                    foreach(var runningInstance in reservation.RunningInstance)
                        instances.add(reservation.GroupName.Aggregate((a, b) => a + ',' + b),
                                      runningInstance);            
            return instances;           
        }
    }
   
    public static class API_AmazonEC2_ExtensionMethods_RunningInstance
    {
        public static RunningInstance startInstance(this API_AmazonEC2 amazonEC2, RunningInstance runningInstance)
        {                           
            "Starting instance with ID: {0}".info(runningInstance.InstanceId);                           
            var ec2Client = amazonEC2.getEC2Client(runningInstance.Placement.AvailabilityZone.removeLastChar());
            var result = ec2Client.StartInstances(new StartInstancesRequest()
                                                    .WithInstanceId(runningInstance.InstanceId));
            return runningInstance;
        }

        public static RunningInstance stopInstance(this API_AmazonEC2 amazonEC2, RunningInstance runningInstance)
        {                                                   
            "Stopping instance with ID: {0}".info(runningInstance.InstanceId);                           
            var ec2Client = amazonEC2.getEC2Client(runningInstance.Placement.AvailabilityZone.removeLastChar());
            var result = ec2Client.StopInstances(new StopInstancesRequest()
                                                    .WithInstanceId(runningInstance.InstanceId));
            return runningInstance;
        }
      
        public static RunningInstance showConsoleOut(this API_AmazonEC2 amazonEC2, RunningInstance runningInstance)
        {                           
            "Getting Console out instance with ID: {0}".info(runningInstance.InstanceId);           
            var ec2Client = amazonEC2.getEC2Client(runningInstance.Placement.AvailabilityZone.removeLastChar());
            var consoleOutResult = ec2Client.GetConsoleOutput(new GetConsoleOutputRequest()
                                                                        .WithInstanceId(runningInstance.InstanceId));
            var consoleOut = consoleOutResult.GetConsoleOutputResult.ConsoleOutput.Output.base64Decode();   
            consoleOut.showInCodeViewer(".bat");
            return runningInstance;
        }       
   
        public static string getPassword(this API_AmazonEC2 amazonEC2, RunningInstance runningInstance)   
        {   
            "Tests on  instance with ID: {0}".info(runningInstance.InstanceId);                                       
            var ec2Client = amazonEC2.getEC2Client(runningInstance.Placement.AvailabilityZone.removeLastChar());
            var passwordResponse = ec2Client.GetPasswordData(new GetPasswordDataRequest().WithInstanceId(runningInstance.InstanceId));
            "raw password data : {0}".info(passwordResponse.GetPasswordDataResult.ToXML());                      
            var decryptedPassword = amazonEC2.ApiRsa.decryptPasswordUsingPem(passwordResponse.GetPasswordDataResult.PasswordData.Data);                
            "decrypted password: {0}".info(decryptedPassword);
            return decryptedPassword;           
           }
          
           public static string getRunningInstanceSignature(this API_AmazonEC2 amazonEC2, RunningInstance runningInstance)   
           {
            var signature = "{0}  -  {1}  -  {2}  -  {3}  -  {4} ".format(
                                   runningInstance.InstanceId,
                                   runningInstance.InstanceType,
                                   runningInstance.IpAddress,
                                   runningInstance.Placement.AvailabilityZone,
                                   runningInstance.InstanceState.Name);
            foreach(var tag in runningInstance.Tag)
                //signature = "{0}= {1}  -  {2}".format(tag.Key, tag.Value, signature);
                signature = "{1}  -  {2}".format(tag.Key, tag.Value, signature);
               return signature;
        }
    }
   
    public static class API_AmazonEC2_ExtensionMethods_GUIs
    {
        public static API_AmazonEC2 addStopInstanceGui(this API_AmazonEC2 amazonEC2, Panel targetPanel, TreeView treeViewWithInstances)
        {                       
            Action startTimer = null;
            Action stopTimer = null;
            var instancesToStop = targetPanel.add_GroupBox("Stop Instance in {0} minutes".format((amazonEC2.TimerCount * amazonEC2.TimerCount / 60)))
                                             .add_TreeView();                       
            var timerBar = instancesToStop.insert_Below(20).add_ProgressBar();
            instancesToStop.add_ContextMenu().add_MenuItem("Stop now",true,
                                                    ()=>{
                                                            "Stopping {0} instances now".debug(instancesToStop.nodes().size());
                                                            foreach(var node in instancesToStop.nodes())
                                                                amazonEC2.stopInstance((RunningInstance)node.get_Tag());
                                                        })
                                             .add_MenuItem("Clear list", ()=>instancesToStop.clear());
            var startTimerLink = instancesToStop.insert_Above(15).add_Link("Add instance to list",0,0,
                                                    ()=>{
                                                            var selectedNode = treeViewWithInstances.selected();
                                                            if (selectedNode.notNull())
                                                            {
                                                                var tag = selectedNode.get_Tag(); 
                                                                if (tag is RunningInstance)
                                                                {
                                                                    var selectedInstance = (RunningInstance)tag;
                                                                    var nodeText = "{0} - {1}".format(selectedInstance.InstanceId, selectedInstance.IpAddress);
                                                                    instancesToStop.add_Node(nodeText, selectedInstance);
                                                                }
                                                            }
                                                            //treeViewWithInstances.nodes().showInfo();
                                                        })
                                            .append_Link("Start timer", ()=>startTimer()); 
            var timerEnabled = false;                               
            var    stopTimerLink = startTimerLink.append_Link("Stop timer", ()=>stopTimer()).enabled(false);                             
            startTimer = ()=>{                                           
                                    "starting timer".info();
                                    timerEnabled = true;                                               
                                    timerBar.maximum(amazonEC2.TimerCount);
                                    timerBar.value(0);
                                    startTimerLink.enabled(false);
                                    stopTimerLink.enabled(true);
                                    while(timerEnabled && timerBar.Value < amazonEC2.TimerCount)
                                    {
                                        "In StopInstances Timer [{0}/{1}], sleeping for {2} seconds".info(timerBar.Value, amazonEC2.TimerCount, amazonEC2.TimerSleep/1000);
                                        timerBar.sleep(amazonEC2.TimerSleep, false);
                                        timerBar.increment(1);                                                                                                       
                                    }
                                    if (timerEnabled)
                                    {                                                   
                                        "Timer is completed stopping {0} instances now".debug(instancesToStop.nodes().size());
                                        foreach(var node in instancesToStop.nodes())
                                            amazonEC2.stopInstance((RunningInstance)node.get_Tag());
                                    }
                                    else
                                        "Timer was stopped so nothing to do".debug();           
                                    startTimerLink.enabled(true);
                                    stopTimerLink.enabled(false);

                             };
            stopTimer = ()=>{
                               
                                    "stopping timer".info();
                                    timerEnabled = false;
                                   
                                    startTimerLink.enabled(true);
                                    stopTimerLink.enabled(false);
                             };
            targetPanel.onClosed(()=>     timerEnabled=false);                    
           
            return amazonEC2;
        }
    }
   
}
 

Tool – Amazon EC2 Browser.h2

And here it the refactored code that creates the GUI that is show in the Tool – Amazon EC2 Browser.h2 script (before all of the above code was inside the script below: )

//var topPanel = panel.clear().add_Panel();
var topPanel = O2Gui.open<Panel>("AmazonEC2",580,400);  
topPanel.insert_Below(100).add_LogViewer(); 
 
var apiKey = @"C:\O2\_USERDATA\accounts.xml".credential("AmazonAWS");
   
var amazonEC2 = new API_AmazonEC2(apiKey);
                            
Action<RunningInstance> rdpIntoBox =
    (runningInstance)=>{               
                            "Creating RDP connection to instance with ID: {0} and IP ".info(runningInstance.InstanceId,runningInstance.IpAddress );           
                            new API_RDP().launchRdpClient(runningInstance.IpAddress);                   
                        };</pre>
 
/*Action<RunningInstance> testInstance =
    (runningInstance)=>{                           
                            "Tests on  instance with ID: {0}".info(runningInstance.InstanceId);                                      
                            var ec2Client = getEC2Client(runningInstance.Placement.AvailabilityZone.removeLastChar());
                            var passwordResponse = ec2Client.GetPasswordData(new GetPasswordDataRequest().WithInstanceId(runningInstance.InstanceId));
                            "password: {0}".info(passwordResponse.GetPasswordDataResult.ToXML());
                            "Done".info();
                       };                              
*/                      
                      
                       

                       
Action<Panel> showRunningInstancesDetails =
    (targetPanel)=> {
                       
                        var treeView = targetPanel.add_GroupBox("Amazon EC Instances").add_TreeView();
                        var actionsPanel = treeView.insert_Below(100);                           
                        treeView.beforeExpand<List<RunningInstance>>(
                            (treeNode, runningInstanceList) =>{
                                                                treeNode.clear();
                                                                treeNode.add_Nodes(runningInstanceList , (runningInstance)=>amazonEC2.getRunningInstanceSignature(runningInstance));
                                                                foreach(var node in treeNode.nodes())
                                                                    if (node.get_Text().contains("stopped"))
                                                                        node.color(Color.DarkGreen);
                                                                    else if (node.get_Text().contains("running"))
                                                                        node.color(Color.DarkRed);
                                                                    else
                                                                        node.color(Color.DarkBlue); 
                                                                       
                                                             });
                        Action<bool> refresh =
                            (onlyShowDefaultRegion)=>{
                                    treeView.backColor(Color.Azure);
                                    O2Thread.mtaThread(
                                        ()=>{                                                                               
                                                var ec2Instances =     amazonEC2.getEC2Instances(onlyShowDefaultRegion);
                                                treeView.clear();
                                                treeView.add_Nodes(ec2Instances.keys(), (text)=>text, (text) => ec2Instances.value(text), (text) => ec2Instances.value(text).size() > 0);
                                                treeView.selectFirst().selected().expand().nodes()[0].selected();
                                                treeView.backColor(Color.White);
                                            });
                                };
                               
                        actionsPanel.add_Link("Refresh Instances list (default Region)", 0,0, ()=> refresh(true)).click();       
                        actionsPanel.add_Link("Refresh Instances list (all Regions)",20,0, ()=> refresh(false));
                        
                        RunningInstance selectedInstance = null;
                        actionsPanel.add_Link("Show Instance Details", 40,0, ()=>  selectedInstance.details());
                        actionsPanel.add_Link("View Instance  Console Out", 60,0, ()=>  amazonEC2.showConsoleOut(selectedInstance));
                        var link = actionsPanel.add_Link("Show Decrypted password  ", 80,0, ()=> amazonEC2.getPassword(selectedInstance));
                        actionsPanel.add_Link("Start Instance ", 0,220, ()=> amazonEC2.startInstance(selectedInstance));
                        actionsPanel.add_Link("Stop Instance ", 20,220, ()=> amazonEC2.stopInstance(selectedInstance)); 
                        actionsPanel.add_Link("RDP Instance ", 40,220, ()=> rdpIntoBox(selectedInstance));  
                       
                        amazonEC2.addStopInstanceGui(actionsPanel.insert_Right(240),treeView);  
                       
                        /*var link = actionsPanel.add_Link("Test request Instance ", 80,220, ()=> testInstance(selectedInstance));
                        O2Thread.mtaThread(()=>{
                                link.sleep(1000);
                                link.click();
                            });*/                                                                    
                       
                        treeView.afterSelect<RunningInstance>((runningInstance)=> selectedInstance = runningInstance);   
                       
                    };
                                    
showRunningInstancesDetails(topPanel); 

//O2File:API_AmazonEC2.cs
//O2File:API_RDP.cs
//using Amazon.EC2
//using Amazon.EC2.Model
//O2Ref:AWSSDK.dll
//O2File:ascx_AskUserForLoginDetails.cs   
//O2Ref:White.Core.dll

 

April 16, 2011 Posted by | EC2 | 2 Comments

Solved the problem with decryping AmazonEC2 Instance’s password

I was able to solve the problem I had with decrypting the AmazonEC2 instance’s password.

Here is the code that is part of the API_AmazonEC2.cs script

        public static string getPassword(this API_AmazonEC2 amazonEC2, RunningInstance runningInstance)   
        {   
            "Tests on  instance with ID: {0}".info(runningInstance.InstanceId);                                       
            var ec2Client = amazonEC2.getEC2Client(runningInstance.Placement.AvailabilityZone.removeLastChar());
            var passwordResponse = ec2Client.GetPasswordData(new GetPasswordDataRequest().WithInstanceId(runningInstance.InstanceId));
            "raw password data : {0}".info(passwordResponse.GetPasswordDataResult.ToXML());                       
            var decryptedPassword = amazonEC2.ApiRsa.decryptPasswordUsingPem(passwordResponse.GetPasswordDataResult.PasswordData.Data);                
            "decrypted password: {0}".info(decryptedPassword);
            return decryptedPassword;           
           }

which calls the ApiRsa.decryptPasswordUsingPem(passwordResponse.GetPasswordDataResult.PasswordData.Data) method from the newly created API_RSA.cs script:

// This file is part of the OWASP O2 Platform (<a href="http://www.owasp.org/index.php/OWASP_O2_Platform">http://www.owasp.org/index.php/OWASP_O2_Platform</a>) and is released under the Apache 2.0 License (<a href="http://www.apache.org/licenses/LICENSE-2.0">http://www.apache.org/licenses/LICENSE-2.0</a>)
using System;
using System.IO;
using System.Text;
using O2.Kernel;
using O2.Kernel.ExtensionMethods;
using O2.DotNetWrappers.ExtensionMethods;
using O2.DotNetWrappers.Windows;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Encodings;
using Org.BouncyCastle.OpenSsl;
using Org.BouncyCastle.Crypto.Engines;
//O2Ref:itextsharp.dll
//O2Ref:O2_DotNetWrappers.dll
//O2Ref:O2_Kernel.dll</pre>
 

namespace O2.XRules.Database.APIs
{   
    public class API_RSA
    {   
        public string PathToPemKey { get;set;}
       
        public API_RSA()
        {}
       
        public API_RSA(string pathToPemKey)
        {
            PathToPemKey = pathToPemKey;
        }
       
        public  string decryptPasswordUsingPem(string password)
        {
            try
            {
                var passwordBytes = Convert.FromBase64String(password); 
                AsymmetricCipherKeyPair keyPair;
                PathToPemKey =  PathToPemKey ?? "Where is the PEM private Key".askUser();
               
               
                using (var reader = File.OpenText(PathToPemKey)) 
                    keyPair = (AsymmetricCipherKeyPair) new PemReader(reader).ReadObject();
               
                var decryptEngine = new Pkcs1Encoding(new RsaEngine());
                decryptEngine.Init(false, keyPair.Private);
                
                var decryptedPassword = Encoding.UTF8.GetString(decryptEngine.ProcessBlock(passwordBytes, 0, passwordBytes.Length));
                
                return decryptedPassword;
            }
            catch(Exception ex)
            {
                "[API_RSA] in decryptPasswordUsingPem: {0}".error(ex.Message);
                return "";
            }
        }
    }       
}

April 16, 2011 Posted by | EC2 | Leave a comment

Trying to Decrypt Amazon EC2 password using BouncyCastle and it is not working

For O2’s Amazon EC2 Browser, I was adding the ability to decrypt the Instance’s Password (retrieved using the AWSSDK.dll GetPassswordDataRequest) but I can’t seem to decrypt its value, any ideas on how to do it?

Here is my the code that doesn’t work (uses BouncyCastle API)

var bytesToDecrypt = Convert.FromBase64String("...");</pre>
 

AsymmetricCipherKeyPair keyPair;
var pemFile = @"C:\...\SI_Key.pem";
using (var reader = File.OpenText(pemFile))
{
    keyPair = (AsymmetricCipherKeyPair) new PemReader(reader).ReadObject();
    var decryptEngine = new Pkcs1Encoding(new RsaEngine());
    decryptEngine.Init(false, keyPair.Private);

    var decrypted = Encoding.UTF8.GetString(decryptEngine.ProcessBlock(bytesToDecrypt, 0, bytesToDecrypt.Length));   
    return decrypted;
}

 

When that code executes I get the following error:

 at Org.BouncyCastle.Crypto.Encodings.Pkcs1Encoding.DecodeBlock(Byte[] input, Int32 inOff, Int32 inLen)
   at Org.BouncyCastle.Crypto.Encodings.Pkcs1Encoding.ProcessBlock(Byte[] input, Int32 inOff, Int32 length)
   at DynamicType.dynamicMethod(Object returnData, Panel panel)  StackTrace:</pre>
 

   at Org.BouncyCastle.Crypto.Encodings.Pkcs1Encoding.DecodeBlock(Byte[] input, Int32 inOff, Int32 inLen)
   at Org.BouncyCastle.Crypto.Encodings.Pkcs1Encoding.ProcessBlock(Byte[] input, Int32 inOff, Int32 length)

(the above code sample was based on this StackOverflow answer: http://stackoverflow.com/questions/243646/how-to-read-a-pem-rsa-private-key-from-net)

April 16, 2011 Posted by | EC2 | 2 Comments

Amazon EC2 Browser – Timer to Stop Instances

When using the new O2 Amazon EC browser tool (which works really well and is really helping me to better manage my EC2 usage), I reallized that what I really wanted was a way to stop instances after a certain period.

The problem is that Amazon EC2 can be quite expensive if we leave the instances running for a while (and in a lot of cases they are not needed to be up for longer periods of time). The lack of automatically stopping instances (after a while) was really preventing me from trying a couple ‘high performace’  instances (since they can be up to 11USD per day). 

The solution was to add a feature to the O2 Amazon EC browser where we could set-up a timer that would stop the instances after 1h (60m), with the ability to reset the clock if we wanted more time).

This feature is now availbale on the latest version of the  Tool – Amazon EC2 Browser.h2 O2 script (see ‘Stop Instances in 60 minutes panel on the bottom right):

This will also allow me to better manage the O2 images that I am providing to the O2 Subscribers

April 10, 2011 Posted by | EC2 | 4 Comments