One of the most exciting aspects of cloud computing is the ability to run virtual machines in a cloud provider's data center. Amazon's EC2 gives architects and developers the ability to create virtual-machine images and run them in the cloud. You can create custom images that contain the software and data your organization needs, then you can run as many (or as few) copies of those virtual machines as you need. This article looks at some of the classes in the Zend Framework that make it easy to work with EC2 images.
Because EC2 is a sophisticated product, the EC2 features are split into two articles. This article covers the basics of working with images, starting and stopping instances of those images, and the key pairs and security groups that let you secure the instances. Topics such as Elastic IP addresses, Amazon CloudWatch monitoring and Elastic Block Storage are covered in another article.
In this article, you'll see how to do several important EC2 tasks:
- Find the Amazon Machine Images (AMIs) that belong to you
- Work with key pairs, including finding the ones that belong to you, creating new ones and deleting old ones
- Work with security groups, including controlling access to the TCP/IP ports of your virtual machine
- Start an instance of an AMI
- Reboot or terminate an instance of an AMI
As with all of the articles in this series, you'll get the most out of the
examples if you have the Zend Framework installed before you begin. If you
don't have the Zend Framework installed already, download and install the
full package from
zend.com/community/downloads.
This installs the Zend Framework, PHP, and the Apache Web server on your
machine. When the install is complete, go to
http://localhost/ZendServer/ in your browser.
See the Zend Framework installation documentation for all the details. If
you can log in to the ZendServer console, you're all set.
You'll also need to set up an account with Amazon (see Resources).
The examples use the PHP Credentials class created in Part 1. That class manages the credentials for your Amazon account. The credentials are stored in an .ini file.
Listing 1. Storing credentials in a PHP .ini file
; Configuration file to hold secret keys, account numbers and other useful
; strings for Amazon and other cloud accounts.
[amazon]
accessKey=0123456789ABCDEFGHIJ
secretKey=0123456789abcdefghiABCDEFGHI1234567890AB
ownerId=123456789012
|
In this article, the ownerId value is crucial.
There are thousands of AMIs available at Amazon, most of which are not
available to the public.
You'll use the ownerId
value to filter out the AMIs you don't have
authorization to access. Your owner ID is your 12-digit Amazon Web
Services account number. To find it, go to
http://aws.amazon.com/, log into your account,
then select the Your Account menu and the Security Credentials
item.
Figure 1. Finding your security credentials
Scroll down to the middle of the page, and you'll see your AWS account ID.
Figure 2. Your AWS account ID
When you put your account ID into the cloud.ini
file, don't use the dashes. If this were your ID, you would add
ownerId=999999999999 to the
.ini file.
Notes:
- Whenever you start an instance of an AMI, you're spending money. Even though EC2's charges are reasonable (some instances are as little as 10 cents an hour), you don't want to just start an AMI and leave it running indefinitely. Be sure to terminate your instances when you're through with them.
- The examples in this article assume you have created at least one AMI.
If you haven't, you can use the special value
ownerId=amazon. This returns a list of more than 100 AMIs, but it will give you some images you can launch. - If you're using
ownerId=amazon, be aware that some of those instances can be quite expensive. IBM® has a number of AMIs that feature enterprise-class software products. If you're using one of those AMIs, you're paying a licensing fee as long as the instance is running. If all you want to do is experiment with EC2, an AMI that's light on features is likely light on price, as well.
The sample application consists of six PHP pages:
amis.php— Lists all the AMIs owned by your account. You can start an instance of any AMI just by clicking a button.manage_instance.php— Handles requests fromamis.phpto create, reboot, or terminate an instance of an AMI.instances.php— Lists all running instances controlled by your account. Reboot or terminate any running instance just by clicking a button.keypairs.php— Lists all public/private key pairs you've created. Examine existing key pairs, create new ones, and delete existing ones.securitygroups.php— Lists all security groups defined for your account. Click a button to see the details of a particular security group.securitygroup.php— Lists all permissions for a particular security group. Add new permissions or delete existing ones.
To get things started, create a
Zend_Service_Amazon_Ec2_Image object.
Listing 2. Creating a
Zend_Service_Amazon_Ec2_Image object
require_once 'Credentials.php';
$creds = new Credentials;
$aws_key = $creds->getCredential('amazon', 'accessKey');
$aws_secret = $creds->getCredential('amazon', 'secretKey');
$ec2_img = new Zend_Service_Amazon_Ec2_Image($aws_key, $aws_secret);
|
This object lets you work with the AMIs stored at Amazon. The
Zend_Service_Amazon_Ec2_Image->describe()
method returns the metadata about an AMI. With no argument, it returns the
details of every AMI stored at Amazon. That creates a large amount of
data, most of which isn't useful to you. Unfortunately, the current
incarnation of the Zend Framework doesn't support the version of
describe() that lets you specify an
ownerId. That means the first time you want to
list the AMIs relevant for the user, you have to sort through the
entire list to find the ones you want. To get around this, you can
cache the IDs of the AMIs you want to display. The processing logic
is that if a file listing the relevant AMIs exists, you simply read that
file and call describe('ami-id') for each ID.
If the file doesn't exist, you have to create it; the PHP file also gives
the user the option to refresh the list of AMIs if he wants. That will
take a while, but it ensures that the list is consistent with the data at
Amazon.
The code to create the list of AMIs looks like Listing 3.
Listing 3. Caching the IDs of AMIs
if (!file_exists('amis.text') ||
array_key_exists('refresh', $_POST)) {
$imageData = $ec2_img->describe();
$amiFile = fopen('amis.text', 'w');
$myOwnerId = $creds->getCredential('amazon', 'ownerId');
foreach ($imageData as $nextImage) {
if ($nextImage['imageOwnerId'] === $myOwnerId)
fwrite($amiFile, $nextImage['imageId']."\n");
}
fclose($amiFile);
}
|
The code here checks to see if it needs to sort through all of the AMIs in Amazon's catalog. If the file doesn't exist or there is an explicit request to refresh it, the code gets the list of details for all the AMIs at Amazon. The goal here is to create a table of AMIs.
Figure 3. A listing of AMIs
Each row in the table features the ID of the AMI, its location, its status,
and its platform. In addition, there are two drop-down lists that allow
you to choose a key pair and a security group. The final column in the
table is a push button that lets you start the AMI with the
currently selected key pair and security group. To create the table, use
the PHP file() method to read the list of AMIs
into an array. For each item in the array, create a table row that
contains all the relevant information. Following is the code that creates the
rows of the table.
Listing 4. Generating the rows of the table of AMIs
$amiList = file('amis.text', FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
foreach ($amiList as $nextAmi) {
echo "<tr>";
// Each table row is a form. Clicking the 'Start this image' button submits
// the data from the current row, which tells instances.php which image to
// start and which key pair and security group to use.
echo "<form action='manage_instance.php' method='POST' ";
echo " onsubmit='return confirm(\"Start image '".$nextAmi."'?\")'>";
echo "<input type='hidden' name='imagetostart' value='".$nextAmi."'/>";
echo "<td>".$nextAmi."</td>";
// Get the description of this AMI
$imageData = $ec2_img->describe(array('imageId' => $nextAmi));
echo "<td>".$imageData[0]['imageLocation']."</td>";
echo "<td>".$imageData[0]['imageState']."</td>";
// If the platform is blank, assume it's some flavor of Linux
if (strlen($imageData[0]['platform']))
echo "<td>".$imageData[0]['platform']."</td>";
else
echo "<td>Linux</td>";
// Insert the lists of key pairs and security groups
echo "<td>".$keypairsForm."</td>";
echo "<td>".$secGroupsForm."</td>";
// If the state of the image is "available," insert a start button.
if ($imageData[0]['imageState'] == 'available')
echo "<td><input type='submit' value='Start this image'/></td>";
else
echo "<td>Not available</td>";
echo "</form>";
echo "</tr>";
}
|
Each table row must be in a separate
<form> element so the browser
knows which key pair and security group is selected when the Start button
is clicked. As you iterate through the array of AMI IDs, calling
describe() with a specific ID returns the
description of that particular AMI. The rest of the table row consists of
the location of the image (where the image is stored in your S3 account),
the status of the image, a drop-down list of key pairs, a drop-down list
of security groups, and a Start this image button. The Start button is
displayed only if the status of the image is
available. The form controls for each row of
the table look like Figure 4.
Figure 4. Form controls for each row of the table
The lists of key pairs and security groups are created outside the loop.
Listing 4. Generating the lists of key pairs and security groups
$ec2_kp = new Zend_Service_Amazon_Ec2_Keypair($aws_key, $aws_secret);
$keypairs = $ec2_kp->describe();
foreach ($keypairs as $key => $row) {
$keyName[$key] = $row['keyName'];
$keyFingerprint[$key] = $row['keyFingerprint'];
}
array_multisort($keyName, $keypairs);
$keypairsList = "<select name='keypair'>";
foreach ($keypairs as $nextKeypair) {
$keypairsList = $keypairsList."<option value='".$nextKeypair['keyName']."'>";
$keypairsList = $keypairsList.$nextKeypair['keyName']."</option>";
}
$keypairsList = $keypairsList."</select>";
$secGroupsList = "<select name='secgroup'>";
$ec2_sg = new Zend_Service_Amazon_Ec2_Securitygroups($aws_key, $aws_secret);
$securityGroups = $ec2_sg->describe();
foreach ($securityGroups as $key => $row) {
$groupName[$key] = $row['groupName'];
$groupDescription[$key] = $row['groupDescription'];
}
array_multisort($groupName, $securityGroups);
foreach ($securityGroups as $nextGroup) {
$secGroupsList = $secGroupsList."<option value='".$nextGroup['groupName']."'>";
$secGroupsList = $secGroupsList.$nextGroup['groupName']."</option>";
}
$secGroupsList = $secGroupsList."</select>";
|
Each list is a string that contains the HTML
<select> and
<option> elements for the key
pairs and security groups. (Notice that the code uses the PHP
array_multisort to sort the names of key pairs
and security groups.) Because starting an instance of an AMI means charges
start to accrue in your AWS account, a confirmation dialog appears.
Figure 5. Starting an instance must be confirmed
In this screen capture, the key pair
id_rsa-gsg-keypair and the security group
default are selected.
When you click the OK button to launch an instance, the information about
the new instance is sent to the
manage_instance.php page. The first step in
working with instances is to create a
Zend_Service_Amazon_Ec2_Instance object.
Listing 6. Creating a Zend_Service_Amazon_Ec2_Instance object
$creds = new Credentials;
$aws_key = $creds->getCredential('amazon', 'accessKey');
$aws_secret = $creds->getCredential('amazon', 'secretKey');
$ec2_instance = new Zend_Service_Amazon_Ec2_Instance($aws_key, $aws_secret);
|
With the object created, you can now start an instance of the requested image.
Listing 7. Creating a new instance
if (strlen($imageIdToStart) && strlen($keypairToStart) && strlen($secgroupToStart)) {
$startResults = $ec2_instance->run(array('imageId' => $imageIdToStart,
'keyName' => $keypairToStart,
'securityGroup' => $secgroupToStart));
echo "<p><b>Status of instance ".$startResults['instances'][0]['instanceId'].": ";
echo $startResults['instances'][0]['instanceState']['name'].".</b></p><hr/>";
}
|
Note: You can specify other parameters when you start an instance,
such as the number of instances, the size of the instance (how much memory
and CPU power it has) and the geographic region where the instance should
be hosted. To keep the examples simple, all requests to start an instance
only start one instance, that instance has the smallest size (specified as
m1.small in the actual request to Amazon) and
is hosted in the default region for your account.
This code takes the ID of the AMI and the names of the key pair and
security group selected in the form on the
amis.php page. The page then displays the
status of the new instance.
Figure 6. The status of a newly created instance
Clicking OK sends you to the instances.php page.
That page displays the current list of instances.
Figure 7. The list of instances
Note: The values for the image ID, key name, and security group are
passed to the manage_instance.php page via HTTP
POST. Using an intermediate page to create the new instance means you
can refresh the instances.php page without
inadvertently starting another instance. The
manage_instance.php page also handles requests
to reboot or terminate an image.
When you start an instance, its initial state is
pending. That means the machine image is
booting, but it isn't up and running just yet. Also notice that Amazon has
assigned the instance ID i-373c995f to this
instance; that ID is how you'll work with the instance later. Clicking the
"Refresh list of instances" button updates the display.
Figure 8. Updated list of instances
In the updated listing, the status of the instance is now
running. Notice that Amazon has assigned the
DNS name
ec2-75-101-220-48.compute-1.amazonaws.com to
this instance. That means that if you have enabled this instance for Web
access, and the instance is running a Web
server on port 80, you could visit
http://ec2-75-101-220-48.compute-1.amazonaws.com
to see the home page of the instance. (You can enable port 80 by creating
a rule in a security group; more on security groups in a minute.)
To generate the rows of the instances table, you use the
Zend_Service_Amazon_Ec2_Instance->describe()
method.
Listing 8. Creating the table of instances
$instanceDetails = $ec2_instance->describe();
if (count($instanceDetails['instances'])) {
echo "<table border='1' cellpadding='5'>";
echo "<tr style='font-weight: bold;'>";
echo "<td>Status</td><td>Instance ID</td><td>AMI ID</td><td>Public DNS name</td>";
echo "<td>Security Group</td><td>Key Pair</td><td> </td><td> </td>";
echo "</tr>";
foreach ($instanceDetails['instances'] as $nextInstance) {
echo "<tr>";
$status = $nextInstance['instanceState']['name'];
// Make the cell background green if the status is running.
if (strripos('running', $status) === 0)
echo "<td style='background-color: green; color: white; font-weight: bold;'>";
// Make the cell background yellow if the status is shutting-down.
else if (strripos('shutting-down', $status) === 0)
echo "<td style='background-color: yellow; font-weight: bold;'>";
// Make the cell background red if the status is terminated.
else if (strripos('terminated', $status) === 0)
echo "<td style='background-color: red; color: white; font-weight: bold;'>";
// Make the cell background purple for any other status.
else
echo "<td style='background-color: purple; color: white; font-weight: bold;'>";
echo $status."</td>";
echo "<td>".$nextInstance['instanceId']."</td>";
echo "<td>".$nextInstance['imageId']."</td>";
echo "<td>".$nextInstance['dnsName']."</td>";
echo "<td><a href='securitygroup.php?groupname=".$nextInstance['groupSet'][0];
echo "&previous=instances'>".$nextInstance['groupSet'][0]."</a></td>";
echo "<td>".$nextInstance['keyName']."</td>";
. . .
|
The code first checks to see if there are any instances. Assuming there is
at least one, each instance is described in a row of the table. The
instance ID and AMI ID are displayed, along with the public DNS name,
security group, and key pair. As with the
amis.php page, each row of the table is a
form.
Figure 9. Form controls to manage instances
This table lists three instances. The status of two of the items is
running, so there are Reboot and
Terminate buttons for those instances. For an instance in any other state
(pending,
shutting-down or
terminated), the buttons don't appear.
Listing 9. Creating the form controls for the table of instances
if (strripos('running', $status) === false) {
echo "<i>[Can't reboot]</i>";
}
else {
echo "<form action='manage_instance.php' method='POST' ";
echo "onsubmit='return confirm(\"Reboot instance '";
echo $nextInstance['instanceId']."'?\")'>";
echo "<input type='hidden' name='imagetoreboot' value='";
echo $nextInstance['instanceId']."'/>";
echo "<input type='submit' value='Reboot'/></form>";
}
echo "</td>";
echo "<td style='text-align: center;'>";
if (strripos('running', $status) === false) {
echo "<i>[Can't terminate]</i>";
}
else {
echo "<form action='manage_instance.php' method='POST' ";
echo "onsubmit='return confirm(\"Terminate instance '";
echo $nextInstance['instanceId']."'?\")'>";
echo "<input type='hidden' name='imagetoterminate' value='";
echo $nextInstance['instanceId']."'/>";
echo "<input type='submit' value='Terminate'/></form>";
}
echo "</td>";
|
If the instance is running, the code creates buttons to reboot or terminate the instance. Clicking those buttons leads to a confirmation dialog.
Figure 10. Terminating or rebooting an instance must be confirmed
Clicking OK takes you to the manage_instance.php
page again.
Figure 11. The status of a newly terminated instance
Returning to the list of instances shows the updated status.
Figure 12. The updated list of instances
At some point, the status of the instance will change to
terminated.
Figure 13. A terminated instance
Note: At some point after an instance is terminated, EC2 deletes all the data associated with it. This usually happens within an hour. Once the data about the instance is deleted, it will no longer show up in the results.
A key pair is a pair of public and private keys used to authenticate a user.
When you start an instance, you specify a key pair that can be used to
access the instance when it's up and running. Amazon associates the public
key with that instance. Depending on how the AMI is configured, you might
not be able to access the instance without the private key. The file
keypairs.php displays all of the key pairs
defined for your account.
Figure 14. The list of key pairs
For each key pair, the table displays its name and fingerprint.
Listing 10. Creating the table of key pairs
$creds = new Credentials;
$ec2_kp = new Zend_Service_Amazon_Ec2_Keypair>
($creds->getCredential('amazon', 'accessKey'),
$creds->getCredential('amazon', 'secretKey'));
$keypairs = $ec2_kp->describe();
if (count($keypairs)) {
echo "<p>Here are the key pairs defined for your account:</p>";
echo "<table border='1' cellpadding='5'>";
echo "<tr style='font-weight: bold;'>";
echo "<td>Key Pair Name</td>";
echo "<td>Fingerprint</td>";
echo "<td> </td>";
echo "</tr>";
foreach ($keypairs as $key => $row) {
$keyName[$key] = $row['keyName'];
$keyFingerprint[$key] = $row['keyFingerprint'];
}
array_multisort($keyName, $keypairs);
foreach ($keypairs as $nextKeypair) {
echo "<tr>";
echo "<td> ".$nextKeypair['keyName']."</td>";
echo "<td> ".$nextKeypair['keyFingerprint']."</td>";
echo "<td>";
echo "<form action='".$_SERVER['PHP_SELF']."' method='post'";
echo " onsubmit='return confirm(\"Do you really want to delete the key pair ";
echo "'".$nextKeypair['keyName']."'?\");'>";
echo "<input type='hidden' name='keypairtodelete' ";
echo "value='".$nextKeypair['keyName']."'/>";
echo "<input type='submit' value='Delete'/>";
echo "</form>";
echo "</td>";
echo "</tr>";
}
echo "</table>";
}
else
echo "<p>Sorry, your account doesn't have any key pairs defined.</p>";
|
The code creates a
Zend_Service_Amazon_Ec2_Keypair object, then
calls its describe() method to get the details
of all the key pairs defined for your account. For each key pair, AWS
returns the name of the key pair and its fingerprint. Each row of the table
also contains an HTML form with a Delete button. The form requires that
you confirm any delete request.
Figure 15. Deleting a key pair must be confirmed
The delete() method makes deleting the key pair
straightforward.
Listing 11. Deleting a key pair
if (strlen($keypairToDelete)) {
echo "<p><b>";
try {
$ec2_kp->delete($keypairToDelete);
echo "The key pair named ".$keypairToDelete." was deleted successfully.";
}
catch (Zend_Service_Amazon_Ec2_Exception $ec2e) {
echo "The key pair could not be deleted. The error message from Amazon is:";
echo "<br/><br/><i>".$ec2e->getMessage()."</i>";
}
echo "</b></p><hr/><br/>";
}
|
The keypairs.php page also contains a form to
create a new key pair. The only parameter is a name for the new key pair.
Figure 16. Form to create a new key pair
Creating the key pair is as simple as calling the
create() method.
Listing 12. Creating the table of rules in the security group
foreach ($list[0]['ipPermissions'] as $key => $row) {
$ipProtocol[$key] = $row['ipProtocol'];
$startingPort[$key] = $row['fromPort'];
$toPort[$key] = $row['toPort'];
$ipRanges[$key] = $row['ipRanges'];
}
array_multisort($startingPort, SORT_ASC, $list[0]['ipPermissions']);
foreach($list[0]['ipPermissions'] as $rule) {
. . .
echo "<tr>\n";
echo "<td> ".strtoupper($rule['ipProtocol'])."</td>\n";
echo "<td> ".$rule['fromPort']."</td>\n";
echo "<td> ".$rule['toPort']."</td>\n";
if ((is_array($rule['ipRanges']) && count($rule['ipRanges']) == 0) ||
(strlen($rule['ipRanges']) == 0)) {
echo "<td> ---</td>\n";
echo "<td> </td>\n";
}
else {
echo "<td> ".$rule['ipRanges']."</td>\n";
echo "<td style='text-align: center;'>";
echo "<form action='".$_SERVER['PHP_SELF']."' method='POST'";
echo " onsubmit='return confirm(\"Do you really want to revoke access for IP ";
echo " address range '".$rule['ipRanges']."' on this port?\");'>";
echo "<input type='hidden' name='groupname' value='".$groupName."'/>";
echo "<input type='hidden' name='fromport' value='".$rule['fromPort']."'/>";
echo "<input type='hidden' name='toport' value='".$rule['toPort']."'/>";
echo "<input type='hidden' name='iptorevoke' value='".$rule['ipRanges']."'/>";
echo "<input type='submit' value='Revoke'/></form></td>";
} |
The response from Amazon contains the private key for the new key pair. The PHP page displays that information with a message to the user.
Figure 17. A newly created key pair
The user must copy and paste the private key information into a file. If this information is lost, it cannot be recreated. (Creating a more elegant solution that automatically writes the key pair data to a file is left as an exercise for the reader.)
The form that lets you create new instances requires you to specify a machine image, a key pair, and a security group. A security group lets you define how other machines can access an instance. For example, if you wanted to use a running instance as a Web server, you would define a rule in your security group that connection requests on port 80 should be accepted from any machine. For each rule, you specify a protocol, a range of ports, and a range of IP addresses allowed to access those ports via that protocol. The display of a security group looks like Figure 18.
Figure 18. A security group
The table here lists the security policies for the security group
default. At the bottom of the screen capture,
you can see that the policy allows hosts 67.93.2.12 and 76.182.90.9 to
access port 80. Port 3389, typically used for Remote Desktop sessions with
Windows VMs, is authorized for IP address 76.182.90.9, as well. You can
specify a range of ports; in this example, the rules for ports 21, 22, and
23 could have been defined with a single rule. Each row of the table
contains a form to delete an individual rule. The code to create the table
is relatively straightforward.
Listing 13. Creating the table of rules in the security group
foreach ($list[0]['ipPermissions'] as $key => $row) {
$ipProtocol[$key] = $row['ipProtocol'];
$startingPort[$key] = $row['fromPort'];
$toPort[$key] = $row['toPort'];
$ipRanges[$key] = $row['ipRanges'];
}
array_multisort($startingPort, SORT_ASC, $list[0]['ipPermissions']);
foreach($list[0]['ipPermissions'] as $rule) {
. . .
echo "<tr>\n";
echo "<td> ".strtoupper($rule['ipProtocol'])."</td>\n";
echo "<td> ".$rule['fromPort']."</td>\n";
echo "<td> ".$rule['toPort']."</td>\n";
if ((is_array($rule['ipRanges']) && count($rule['ipRanges']) == 0) ||
(strlen($rule['ipRanges']) == 0)) {
echo "<td> ---</td>\n";
echo "<td> </td>\n";
}
else {
echo "<td> ".$rule['ipRanges']."</td>\n";
if (strripos('0.0.0.0', $rule['ipRanges'][0]) === false) {
echo "<td style='text-align: center;'>";
echo "<form action='".$_SERVER['PHP_SELF']."' method='POST'";
echo " onsubmit='return confirm(\"Do you really want to revoke access for IP ";
echo " address range '".$rule['ipRanges']."' on this port?\");'>";
echo "<input type='hidden' name='groupname' value='".$groupName."'/>";
echo "<input type='hidden' name='fromport' value='".$rule['fromPort']."'/>";
echo "<input type='hidden' name='toport' value='".$rule['toPort']."'/>";
echo "<input type='hidden' name='iptorevoke' value='".$rule['ipRanges']."'/>";
echo "<input type='submit' value='Revoke'/></form></td>";
}
else
echo "<td> </td>"; |
Before building the rows of the table, the code uses the
array_multisort function to sort the array of
rules by the starting port number of each rule. Displaying the name of the
protocol, the starting port, and the ending port is straightforward. The
last two columns in the table are the IP address range and a button to
revoke a permission. In some cases, the IP address range is returned as an
empty array or an empty string. If that is the case, the table contains an
empty cell instead of a Revoke button.
The last row of the table contains a form to create a new rule.
Figure 19. The form to create a new rule
Amazon requires that the IP address be specified in Classless Inter-Domain Routing (CIDR) notation. CIDR notation is an IP address, followed by a slash and a number from 0 to 32. The number after the slash specifies how many bits of the IP address are in the prefix. For example, the CIDR notation 9.67.0.0/16 matches any address that starts with 9.67. The IP range 0.0.0.0/0 matches any IP address, while the range 76.182.90.9/32 matches only the IP address 76.182.90.9. If the user enters an IP address that is not in CIDR notation, the PHP page adds /32 to the address. (See Resources to learn more about CIDR.) The code to authorize an IP range is straightforward.
Listing 14. Authorizing a new IP address range
if (strlen($ipToAuthorize) && strripos($ipToAuthorize, '/') === false)
$ipToAuthorize = $ipToAuthorize."/32";
. . .
try {
$ec2_sg->authorizeIp($groupName, $protocol, $fromPort, $toPort, $ipToAuthorize);
echo "IP address ".$ipToAuthorize." is now authorized.";
}
catch (Zend_Service_Amazon_Ec2_Exception $ec2e) {
// We get an exception if this IP address is already authorized, that's okay.
if ($ec2e->getErrorCode() == 'InvalidPermission.Duplicate')
echo "IP address range ".$ipToAuthorize." is already authorized.";
// If the IP address range isn't formatted correctly, tell the user.
else if ($ec2e->getErrorCode() == 'InvalidPermission.Malformed')
echo "The value ".$ipToAuthorize." is not a valid IP address range.";
// For all other exceptions, we just dump the exception to the screen.
else {
echo "<i>Something really bad happened:</i><br/><pre>";
var_dump($ec2e);
echo "</pre>";
}
}
|
Calling the authorizeIp method creates a new
rule for the security group. The code here handles two common exceptions:
The Zend Framework throws an exception if you authorize an IP address
range that is already authorized, and a second exception occurs when the IP
address range is malformed. For any other exceptions, the code just dumps
the error message to the screen.
Note: A recently fixed bug in the Zend Framework returns an array of listings when more than one address range is authorized for a particular port. If your version of the Zend Framework doesn't have this fix, you will only see one address for each port. All of the authorizations are part of the security group stored in the Amazon cloud; they just don't show up in the results from Zend. The sample code has logic to handle this gracefully.
Finally, clicking the Revoke button next to a rule requires confirmation from the user.
Figure 20. Deleting a security rule must be confirmed
Deleting a security rule is done through the
revokeIp() method.
This article presented a set of pages to work with virtual machine images, running instances of those images, and the key pairs and security groups that allow you to manage them. Once again, the Zend Framework makes it easy to interact with the cloud. The next installment of this series will show you how to use the Zend Framework to work with more advanced EC2 features, such as Elastic IP addresses, Elastic Block Storage and CloudWatch.
| Description | Name | Size | Download method |
|---|---|---|---|
| Sample code | os-php-cloud2-source.zip | 13KB | HTTP |
Information about download methods
Learn
- You can sign up for an Amazon Web Services account at the
Amazon EC2 home page.
-
The article
"Cloud
computing with Amazon Web Services, Part 3: Servers on demand with EC2" is a good overview of EC2.
-
Discover why cloud computing is important,
how to get started, and where to learn more about it in the developerWorks
Cloud computing space.
-
Wikipedia has a
good discussion of CIDR addressing.
-
PHP.net is the central resource for PHP developers.
-
Check out the "Recommended PHP reading list."
-
Browse all the PHP content on developerWorks.
-
Follow developerWorks on Twitter.
-
Expand your PHP skills by checking out IBM developerWorks' PHP project resources.
-
To listen to interesting interviews and discussions for software developers, check out developerWorks podcasts.
-
Using a database with PHP? Check out the Zend Core for
IBM, a seamless, out-of-the-box, easy-to-install PHP development and production environment that supports IBM DB2 V9.
-
Stay current with developerWorks' Technical events and webcasts.
-
Check out upcoming conferences, trade shows, webcasts, and other Events around the world that are of interest to IBM open source developers.
-
Visit the developerWorks Open source zone for extensive how-to information, tools, and project updates to help you develop with open source technologies and use them with IBM's products, as well as our most popular articles and tutorials.
-
Watch and learn about IBM and open source technologies and product functions with the no-cost developerWorks On demand demos.
Get products and technologies
-
Download the
Zend Server Community Edition
to run the examples in this article.
-
Innovate your next open source development project with IBM trial software, available for download or on DVD.
- Download
IBM product evaluation versions
or explore
the online trials in the IBM SOA Sandbox and get your hands on application development tools and middleware products from
DB2®, Lotus®, Rational®, Tivoli®, and WebSphere®.
Discuss
-
Participate in developerWorks blogs and get involved in the developerWorks community.
-
Participate in the developerWorks PHP Forum: Developing PHP applications with IBM Information Management products (DB2, IDS).

Doug Tidwell is a senior software engineer in IBM’s Emerging Technology group. He was a speaker at the first XML conference in 1997 and has been working with markup languages, Web services and SOA technologies for many years. His job as a technology evangelist is to explain the standards and technologies behind cloud computing and to help customers integrate them into their overall business architectures and strategies. He is the author of many articles here at developerWorks and is the author of O’Reilly’s book on XSLT (ISBN 0-596-52721-7), a copy of which makes a thoughtful gift for all occasions. He lives in Chapel Hill, N.C., with his wife, daughter, and dog.
Comments (Undergoing maintenance)





