Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / C#5.0

Using the AWS SDK

4.00/5 (3 votes)
31 May 2014CPOL8 min read 19.1K   272  
A Winforms application for configuring EC2 security groups - a future winforms ec2 console

Introduction

This is an head-on introduction to the Amazon Web Services Software Development Toolkit. By making a Winforms program in C# for configuring security groups of EC2 instances, you will probably get a feel for how to use the SDK. Simply put; this program lets you set ingress[1] rules for instances with a focus on limitations between instances. This program has a great potential in GUI development. Be aware, exception checking is very scarce here.

[1] Ingress rules are kind of like rules you put in the Windows firewall for limiting incoming traffic. The opposite would be setting egress rules, which are rules for outgoing traffic, and which are settings you won't see in the online console.

Background

My idea was to make a kind of control station for my own where I could launch and maintain Amazon EC2 instances. That was until I discovered the AWS Toolkit for Visual Studio, which had it all, and I realized that my programming efforts were in vain. But the Visual Studio plugin is more oriented towards objects (snapshot, Ami, S3 bucket and so on) and not so much towards the process and how you are used to go about doing things. So I started out with the need for configuring instance security groups; mostly because I wanted to change things more rapidly by not having to flip through a lot of web pages in order to read out IP addresses and more.

Using the Code

I am using the Visual Studio Toolkit since it has a GUI... and has some sample applications that will turn up in the New Project menu dialogue.

  1. You will need to download and install the AWS SDK for .NET. This you can get from here: Download SDK. But wait: If you install the Toolkit for Visual Studio, it includes the AWS SDK for .NET, so you don't need to install the SDK separately. The Visual studio Toolkit can be downloaded from here: Visual Studio Toolkit.
  2. When reading this prior to the installation, you will see that there is a part there about AWS access credentials. I recommend setting up a IAm user in the web console first and use that username (with its access key and secret access key) in application development.

The GUI

Code for controlling the GUI elements is intertwined in the code without much thought on the separation of concerns, so bear with me on that.

Double-click an item in the instances list, and the security group for that particular EC2 instance is displayed in the middle list. The Security group data is at this point fetched from internal storage and not from the AWS webservices. All Security groups are fetched from AWS on Form Load, and stored in an internal data structure declared in the files named InstanceModel.cs and SettingsModel.cs.

Left-click an item in the instances list and have the private IP address of the instance filled in for the CIDR box in the Operations group field.

Right-click any cell in the instances list and have the public IP address of the instance filled in for the CIDR box in the Operations group field.

Alternatively, you can click an instance in the left and use the private or public IP buttons in the Operations group field to fill in the CIDR address for the selected instance.

Right-click a second level node in the Security group list to transfer a particular security settings to the Operations panel.

Click Add Rule or Remove Rule to do just that to the currently selected security group.

The Code

Establishing contact

In GetInstancesFromAWS(), the ec2Client object is created for the scope of the whole class. This is the client that communicates with AWS. Whenever you address any of the Amazon web services, you describe a context by declaring an object prefixed with exactly that word (you will find a lot of Describe this'nthat in the Amazon.EC2 API reference). In this context, we use DescribeInstancesRequest to establish an object we can send to AWS. This object contains optional parameters in the form of property settings. For instance, you can use the filter property to request a response object containing only those instances with a certain private IP address associated with the network interface. You can for instance set the InstanceIds property of DescribeInstancesRequest in order to get all the instances with certain instance ids; or just one particular instance. An example: To get information about a particular instance, you can use the InstanceIds property of DescribeInstancesRequest like this:

C#
DescribeInstancesRequest ec2Request = new DescribeInstancesRequest();
ec2Request.InstanceIds = new List<string>() { "i-6407c1xxx", "i-6407c1xxx2"};

If you omit the line declaring the InstanceIds property, you will get in return all the instances. Now this alone won't bring you any good, so you need to establish a response object like this:

C#
DescribeInstancesResponse ec2Response = ec2Client.DescribeInstances(ec2Request);
// int NumberofInstances = ec2Response.Reservations[0].Instances.Count;
int NumberofInstances = ec2Response.Reservations.Count;

You can read out the number of instances returned by the response by calling the Count property of the Reservations list property. What this Mumble Jumble probably means is that instances can be reserved in bulk, and I understand that the information about instances is stored in a list under Reservations. But in practice, I see that counting reservations seems like a better idea, since that gives me the correct number of instances.

Getting the data about the instances

The data about the instances are stored in the list AWSinstancedata. This list is of the SDK type Instance, but I made my own datastructures where I flatten the data from two separate objects, namely Instances and SecurityGroup. Note that in order to read out the security groups, another request and response object is created in the PopulateInternalInstanceModel() method. The rest of the code is plain cruising.

Writing/setting a security rule for a security group

First you populate an IpPermission object with all its necessities, and then you declare a AuthorizeSecurityGroupIngressRequest object for the request and a AuthorizeSecurityGroupIngressResponse object to handle the response. This request object is passed on as a parameter to the aforementioned ec2Client object's AuthorizeSecurityGroupIngress method. The response object will return "OK" if it went through successfully.

Removing a security rule for a security group

This is pretty much the same as setting a security rule, except that you use two different objects when addressing the Amazon webservices through the Ec2Client. First, you populate an IpPermission object with all its necessities; the request object is named RevokeSecurityGroupIngressRequest and the response object is named RevokeSecurityGroupIngressResponse. The concept of removing a rule is as follows:

The IpPermission object you set as a parameter to the RevokeSecurityGroupIngressRequest object must consist of an existing protocol name, an existing security group name, and the port numbers registered for the rule. The response object will return an "OK" string if it went through.

About the Attached Source Code

For what it's worth, and in order to get the packet size down, I have taken out the SDK library file from the zip file and instead uploaded the library AWSSDK.dll as a separate file (AWSSDK.zip). This file can be placed in the project root folder (not the solution folder). But you would be better off using the AWSSDK.dll file that came with your own SDK download.

And Now for Something Completely Different

I wonder if anyone has done some research on how effective Linq queries are, but after experimenting with them for a while, I've found Linq to be a powerful tool. I came over the SelectMany method which makes it easy to project properties from data hierarchies. For example in this program, there is a datastructure called InstanceModel, which in turn contains another structure called SettingsModel (a list of entities of type SettingModel). If I where to project all entities in the child relation SettingsModel which have an index value of 6 for instance, I could use SelectMany. And if I am not mistaken, this would otherwise necessitate SQL subqueries in relational databases.

Here is an example of such you can try in this program:

C#
List<SettingsModel> flattenedinstance2 = 
SecuritySettingsForAllinstances.AsQueryable().SelectMany(w => w.SecuritySettings).Where
(b => b.index == 6).ToList<SettingsModel>();

The result will be a limited number of entities given that the child relation has one or more entities with an index value of 6. Or in other words, if you query a child relation named dog types in the parent relation Animals, you can project all the brown dogs in from the subset. I might be wrong here, but so far I'm baffled by the SelectMany method.

Points of Interest

Possible uses of the AWS SDK is definitely automation of procedures, and in particular, those that ordinarily span several web pages when using the AWS Console online. For example - as in the aforementioned background text - you would need to switch to the Instances page in the online console for reading out the internal IP addresses of an instance, and then back again to the Security group page to insert the CIDR address. Another good example of utility is when you need extra computing power for an application[2], you can spawn a new spot instance programmatically and then use logic from this fabulous program :-) to set access limitations between just the two.

On the use of access keys in AWS: Here is a good read: Best practices.

[2] For example, when you're working parsing large text corpuses, or when you are testing an application against another customer's databases.

History

  • 01.06.2014: Changed the line of code where one counts the instances to count reservations instead.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)