OWASP O2 Platform Blog

O2 Tool – Amazon EC2 Browser

Here is a pretty cool tool that gives quick access to Amazon’s EC2 images. It contains a number of nice features (specially if you have used the web interface before) such as:

  • consolidated list of all instances from all zones,
  • start and stop instances
  • get instance’s log
  • rdp into instance (this opens and auto populates mstsc.exe )

This is what the GUI looks like:

And here is the source code of the script that builds this GUI (note the lamda methods which will eventually be moved into the AP_Amazon_EC2.cs file):

var apiKey = @"C:\O2\_USERDATA\accounts.xml".credential("AmazonAWS");
if (apiKey.isNull())
apiKey = ascx_AskUserForLoginDetails.ask();

var defaultRegion = "eu-west-1";//"us-west-1";
Func<List<string>> getEC2Regions =
()=>{
var ec2Client = new AmazonEC2Client(apiKey.UserName, apiKey.Password);
return (from region in  ec2Client.DescribeRegions(new DescribeRegionsRequest())
.DescribeRegionsResult.Region
select region.RegionName).toList();
};

Func<string, AmazonEC2Client> getEC2Client =
(region) => new AmazonEC2Client(apiKey.UserName,
apiKey.Password,
new AmazonEC2Config()
{ServiceURL = "http://{0}.ec2.amazonaws.com".format(region)}
);

Func<string,List<Reservation>> getReservationsInRegion =
(region)=>{
"Gettting Reservations in region: {0}".info(region);
var ec2ClientInRegion = getEC2Client(region);
var describesInstance = new DescribeInstancesRequest();
var reservations = ec2ClientInRegion.DescribeInstances(describesInstance)
.DescribeInstancesResult
.Reservation;

return reservations;
};

Func<bool, Dictionary<string,List<RunningInstance>>> getEC2Instances =
(onlyShowDefaultRegion)=>{
var instances = new Dictionary<string,List<RunningInstance>>();

var reservations = new List<Reservation>();
if (onlyShowDefaultRegion)
reservations.add(getReservationsInRegion(defaultRegion));
else
foreach(var region in getEC2Regions())
reservations.add(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;
};


Action<RunningInstance> startInstance =
(runningInstance)=>{
"Starting instance with ID: {0}".info(runningInstance.InstanceId);
var ec2Client = getEC2Client(runningInstance.Placement.AvailabilityZone.removeLastChar());
var result = ec2Client.StartInstances(new StartInstancesRequest()
.WithInstanceId(runningInstance.InstanceId));
};

Action<RunningInstance> stopInstance =
(runningInstance)=>{
"Stopping instance with ID: {0}".info(runningInstance.InstanceId);
var ec2Client = getEC2Client(runningInstance.Placement.AvailabilityZone.removeLastChar());
var result = ec2Client.StopInstances(new StopInstancesRequest()
.WithInstanceId(runningInstance.InstanceId));
};

Action<RunningInstance> showConsoleOut =
(runningInstance)=>{
"Getting Console out instance with ID: {0}".info(runningInstance.InstanceId);
var ec2Client = getEC2Client(runningInstance.Placement.AvailabilityZone.removeLastChar());
var consoleOutResult = ec2Client.GetConsoleOutput(new GetConsoleOutputRequest()
.WithInstanceId(runningInstance.InstanceId));``
var consoleOut = consoleOutResult.GetConsoleOutputResult.ConsoleOutput.Output.base64Decode();
consoleOut.showInCodeViewer(".bat");
};

Action<RunningInstance> rdpIntoBox =
(runningInstance)=>{
"Creating RDP connection to instance with ID: {0} and IP ".info(runningInstance.InstanceId,runningInstance.IpAddress );
var terminalServicesClient = Processes.startProcess("mstsc.exe");
var guiAutomation = new API_GuiAutomation(terminalServicesClient);
var window = guiAutomation.window("Remote Desktop Connection");
window.textBox("Computer:").set_Text(runningInstance.IpAddress );
window.button("Connect").mouse().click();

};

/*Action<RunningInstance> testInstance =
(runningInstance)=>{
"Tests on  instance with ID: {0}".info(runningInstance.InstanceId);

};
*/

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) => "{0}  -  {1}  -  {2}  -  {3}  -  {4} ".format(
runningInstance.InstanceId,
runningInstance.InstanceType,
runningInstance.IpAddress,
runningInstance.Placement.AvailabilityZone,
runningInstance.InstanceState.Name))    ;
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 =     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, ()=>  showConsoleOut(selectedInstance));
actionsPanel.add_Link("Start Instance ", 0,220, ()=> startInstance(selectedInstance));
actionsPanel.add_Link("Stop Instance ", 20,220, ()=> stopInstance(selectedInstance));
actionsPanel.add_Link("RDP Instance ", 40,220, ()=> rdpIntoBox(selectedInstance));


/*var link = actionsPanel.add_Link("Test request Instance ", 40,220, ()=> testInstance(selectedInstance));
O2Thread.mtaThread(()=>{
link.sleep(1000);
link.click();
});*/

//actionsPanel.add_Link("Show selected Instance Properties ", 20,0, ()=>  selectedInstance.showInfo()));
//treeView.insert_Above(20)

treeView.afterSelect<RunningInstance>((runningInstance)=> selectedInstance = runningInstance);
//var propertyGrid = actionsPanel.insert_Below().add_PropertyGrid();
//treeView.afterSelect<RunningInstance>((runningInstance)=> runningInstance.details());
//treeView.afterSelect<RunningInstance>((runningInstance)=> propertyGrid.show(runningInstance));

};

//var topPanel = panel.clear().add_Panel();
var topPanel = O2Gui.open<Panel>("AmazonEC2",500,400);
topPanel.insert_Below(100).add_LogViewer();
showRunningInstancesDetails(topPanel);
//using Amazon.EC2
//using Amazon.EC2.Model
//O2Ref:AWSSDK.dll
//O2File:ascx_AskUserForLoginDetails.cs
//O2File:API_GuiAutomation.cs
//O2Ref:White.Core.dll
//O2Ref:WatiN.Core.1x.dll

April 8, 2011 Posted by | EC2, WatiN | 2 Comments