OWASP O2 Platform Blog

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

Script to fetch and present large number of WordPress.com blog entries

On the topic of O2’s WordPress scripts, here is a little utility that grabs raw data from workpress blogs and presents it in a consumable way

You can find it here:

 

When executed the first screen looks like this:

It is posible to fetch large number of posts by changing the ‘Number of  blogs to fetch’ )

When it is fetching the left treeView will have a light red color:

which goes back to white once the blog posts are downloaded

Another practical feature are the two windows at the bottom right, which provide lists of the blog’s title and  url locations

This is allows the easy creation of blocks of links to recent blog posts like this (which is what I use when I cross post these links on my personal blog 🙂 )

April 16, 2011 Posted by | IE Automation | Leave a comment

O2 Script to automatically upload clipboard images to WordPress.com

One of  constant themes in O2 is to create features (i.e. O2 Scripts) that automate actions and save those precious 10 seconds to 1 minute, which don’t seem a lot but are enough to kill the mojo of what we are trying to do (and prevent us from doing that task/action more often).

For example, while I already had a O2 tool to help with writing Workpress blog posts (like this one), it was still a pain to:

  • Upload Images
  • Get to the new post in full screen mode

The script below solves that, where it implements an auto image upload to Workpress (since WordPress XmlRpc API doesn’t seem to work).

The script actually become more complex and big than I was expecting since there were a number of steps that were needed to replicate WordPress file update workflow. What is interresting is that this script uses a number of techniques to get the job done:

  • WatiN
  • HtmlAgilityPack
  • MultPart Form upload
  • Jint

Here  is a screenshot just took with this GUI:

Here is the source code of this script ()

var topPanel = O2Gui.open<Panel>("Util - Write Blog post on o2platform.wordpress.com",1200,600);
//var topPanel = panel.clear().add_Panel();</pre>
 
var cookies = "";
var loggedInCookie = "";
var authCookie = "";
var wpnonce = "";
var postId = "";

Func<string,string> uploadFile =
    (fileToUpload)=>{
                var httpMultiPartForm = new HttpMultiPartForm();
               
                string postUrl = "https://o2platform.wordpress.com/wp-admin/async-upload.php";
                //string fileContentType = "multipart/form-data; boundary=----------Ij5Ef1ae0ei4ae0gL6gL6ae0gL6KM7";
                //string fileToUpload = @"C:\O2\_tempDir\4-16-2011\tmp2D26.tmp.jpeg";
                string fileName = fileToUpload.fileName(); //"tmp2D26.tmp.jpeg";
                //string fileFormat = "jpeg";
                string userAgent = "O2Platform.com";               
               
                FileStream fs = new FileStream(fileToUpload, FileMode.Open, FileAccess.Read);
                byte[] data = new byte[fs.Length];
                fs.Read(data, 0, data.Length);
                fs.Close();
               
                var postParameters = new Dictionary<string, object>();
                postParameters.Add("Filename", fileName);
                postParameters.Add("_wpnonce", wpnonce);
                postParameters.Add("post_id",postId);
                postParameters.Add("type", "image");
                postParameters.Add("tab", "type");
                postParameters.Add("logged_in_cookie", loggedInCookie);
                postParameters.Add("short", "1");
                postParameters.Add("auth_cookie", authCookie);
               
               
                string fileContentType = "multipart/form-data";//"application/octet-stream";
               
                postParameters.Add("async-upload", new HttpMultiPartForm.FileParameter(data, fileName, fileContentType));
               
                var httpWebResponse = httpMultiPartForm.MultipartFormDataPost( postUrl,  userAgent, postParameters,  cookies);
                StreamReader reader = new StreamReader(httpWebResponse.GetResponseStream());
                string  responseHtml = reader.ReadToEnd();
                httpWebResponse.Close();
                return responseHtml;
            };
var actionPanel = topPanel.insert_Above(20);

//var controls = topPanel.add_1x1();
//var ie = controls[0].add_IE();
//var ie2 = controls[1].add_IE();
var ie = topPanel.add_IE();
var ie2 = topPanel.insert_Right(150).add_IE();

Action uploadImagefromClipboard =
    ()=>{
            "uploading image".info();
            var imageFromClipboard = 0.saveImageFromClipboard().info();
            if (imageFromClipboard.fileExists())
            {
                "[in WordPress.uploadImage_fromClipboard]: uploading file: {0}".info(imageFromClipboard);
                var imageNumber = uploadFile(imageFromClipboard);
                "[in WordPress.uploadImage_fromClipboard]: got image reference {0}".info(imageNumber);
                ie2.open("https://o2platform.wordpress.com/wp-admin/async-upload.php?attachment_id={0}&fetch=1".format(imageNumber));
                var pageHtml  = ie2.IE.Html.htmlDecode();
                "got html with size: {0}".info(pageHtml.size());
                var imageUrl = pageHtml.htmlDocument()
                                       .select("//img[@class='thumbnail']")
                                       .attributes("src")
                                       .values()[0].split("?")[0];
                "found imageUrl: {0}".info(imageUrl);
               
                //ie2.open("https://o2platform.wordpress.com/?attachment_id={0}".format(imageNumber));                        
                ie2.open(imageUrl);
            }

        };

Action mapCookies =
    ()=>{
            ie2.open("https://o2platform.wordpress.com/wp-admin/media-upload.php?post_id={0}&type=image".format(postId));           
            var scriptElement =  ie2.IE.Html.htmlDocument()
                                            .select(@"//script[contains(text(),'logged_in_cookie')]");
            var jint = scriptElement.innerHtml().str().jint_Compile();  
            var postParams = jint.statements<JsonExpression>(true)[0].Values["post_params"];
           
            authCookie =  postParams.statements<JsonExpression>(true)[0].Values["auth_cookie"]
                                      .statements<ValueExpression>()[0].Value.str();
           
            loggedInCookie =  postParams.statements<JsonExpression>(true)[0].Values["logged_in_cookie"]
                                          .statements<ValueExpression>()[0].Value.str();
            cookies = ie2.cookiesRaw();
            wpnonce = ie2.field("_wpnonce").value(); 
           
            "cookies are: {0}".info(cookies);
            "auth_Cookie is: {0}".info(authCookie);
            "logged_in_cookie is: {0}".info(loggedInCookie);
        };
       
var wordPress = new API_WordPress("o2platform.wordpress.com");      
wordPress.addRequiredSitesToIETrustedZone(); //to make sure it works ok in WatiN   
var homepage = "https://o2platform.wordpress.com";

var credential = @"C:\O2\_USERDATA\Accounts.xml".credential("o2platform");
if (credential.isNull())
    credential = ascx_AskUserForLoginDetails.ask();

Action login =
    ()=>{
            ie.open("https://o2platform.wordpress.com/wp-login.php");
              ie.field("log", credential.UserName);
              ie.field("pwd", credential.Password);
              ie.button("Log In").click();
        };

Action newPost =
    ()=>{
            ie.open("https://o2platform.wordpress.com/wp-admin/post-new.php");
            var browser = topPanel.control<WebBrowser>(true);            
            browser.focus();
            browser.sendKeys("{TAB}%+g");
        };

actionPanel.add_Link("login", 0,0,()=> login())          
           .append_Link("stats", ()=> ie.open("https://o2platform.wordpress.com/wp-admin/index.php?page=stats"))
           .append_Link("new post", ()=> newPost())
            .append_Link("Wrap clipboard data with Source Code tags", ()=> wordPress.wrapClipboardTextInSourceCodeTags())
            .append_Link("upload image (from clipboard)", ()=> uploadImagefromClipboard());
         
         
login();
newPost();
postId = ie.field("post_ID").value();
"postId is: {0}".info(postId);

mapCookies();

return "ok";
 
//using System.IO
//using System.Drawing.Imaging
//O2File:API_WordPress.cs
//O2File:Watin_IE.cs
//O2File:ascx_AskUserForLoginDetails.cs
//O2Ref:WordPress_XmlRpc_JoeBlogs.dll
//O2Ref:Interop.SHDocVw.dll
//O2Ref:WatiN.Core.1x.dll
//using Jint.Expressions
//using O2.XRules.Database.Languages_and_Frameworks.Javascript
//using O2.XRules.Database.Utils.ExtensionMethods
//O2File:Jint_ExtensionMethods.cs
//O2File:HtmlAgilityPack_ExtensionMethods.cs
//O2Ref:O2_Misc_Microsoft_MPL_Libs.dll
//O2Ref:jint.dll

April 16, 2011 Posted by | IE Automation, WatiN | 3 Comments

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