Применение PHP в облачных вычислениях: Часть 2. Работа с Amazon EC2 посредством Zend Framework

Использование виртуальных машин с Zend Framework

Среда Zend Framework содержит несколько классов, которые облегчают использование службы хранения данных на базе облака. Первая часть настоящего цикла статей "Облачные вычисления с помощью PHP" посвящена использованию классов Zend для облачной службы хранения данных Amazon S3. В настоящей статье рассматриваются классы Zend, которые облегчают работу с виртуальными машинами в системе Amazon Elastic Compute Cloud (EC2).

Даг Тидуэл (Doug Tidwell), идеолог XML, EMC

Старший Программист Даг Тидуэл является в IBM ведущим авторитетом по Web-сервисам. Он был докладчиком на первой конференции по XML в 1997 году и более десятилетия работал с языками разметки. Он получил степень бакалавра английского языка в Университете Джорджии и степень магистра компьютерных наук в Университете Вандербильда. Его адрес: dtidwell@us.ibm.com. Вы можете также увидеть его Web-страницу на ibm.com/developerWorks/speakers/dtidwell/.


developerWorks Contributing author
        level

12.05.2010

Одним из наиболее интересных аспектов облачных вычислений является возможность использования виртуальных машин в центрах обработки данных поставщиков облачных услуг. Служба EC2 Amazon предоставляет архитекторам и разработчикам возможность создавать образы виртуальных машин и запускать их в облаке. Можно создавать собственные образы, которые содержат необходимые организации программное обеспечение и данные, а затем запускать столько экземпляров виртуальных машин, сколько нужно. В этой статье рассматриваются некоторые классы Zend Framework, облегчающие работу с образами EC2.

EC2 - сложная система, поэтому функции EC2 рассматриваются в двух статьях. Эта статья посвящена основам работы с образами, пуску и останову экземпляров этих образов, а также парам ключей и группам безопасности, которые позволяют защищать эти экземпляры. Такие темы, как эластичные (Elastic) IP-адреса, система мониторинга Amazon CloudWatch и Elastic Block Storage, рассматриваются в другой статье.

Начало работы

Из этой статьи вы узнаете, как решать несколько важных задач, связанных с EC2:

  • поиск принадлежащих вам образов машин Amazon (Amazon Machine Images – AMI);
  • работа с парами ключей, в том числе поиск своих ключей, создание новых ключей и удаление старых;
  • работа с группами безопасности, включая управление доступом к TCP/IP портам своей виртуальной машины;
  • запуск экземпляра AMI;
  • перезагрузка или останов экземпляра AMI.

Как и во всех статьях этого цикла, вы получите максимальную пользу от примеров, если перед началом работы установите среду Zend Framework. Если среда Zend Framework еще не установлена, загрузите и установите полный пакет из zend.com/community/downloads. При этом на компьютер установится Zend Framework, PHP и Web-сервер Apache. После завершения установки откройте в браузере страницу http://localhost/ZendServer/. За подробностями обращайтесь к инструкции по установке Zend Framework. Если вам удалось войти в консоль ZendServer, значит, все готово.

Вам придется также создать учетную запись на Amazon (см. Ресурсы).

В примерах используется класс PHP Credentials, созданный в Части 1. Этот класс управляет верительными данными учетной записи Amazon. Верительные данные хранятся в файле .ini.

Листинг 1. Хранение верительных данных в файле РНР .ini
; Файл конфигурации для хранения секретных ключей, номеров счетов и других полезных
; строк для Amazon и других облачных сервисов..

[amazon]
accessKey=0123456789ABCDEFGHIJ
secretKey=0123456789abcdefghiABCDEFGHI1234567890AB
ownerId=123456789012

В этой статье важную роль играет значение ownerId. На Amazon существуют тысячи AMI, большинство которых недоступны широкой публике. Значение ownerId позволяет отфильтровать те AMI, прав доступа к которым у вас нет. Идентификатор владельца – это 12-значный номер учетной записи Amazon Web Services. Чтобы найти его, зайдите на http://aws.amazon.com/, войдите в свою учетную запись, затем выберите меню Your Account и пункт Security Credentials.

Рисунок 1. Поиск своих верительных данных
Как найти свои верительные данные

Прокрутите страницу до середины, и вы увидите идентификатор своей учетной записи AWS.

Рисунок 2. Ваш идентификатор учетной записи AWS
Прокрутите страницу вниз, и вы увидите свой идентификатор учетной записи AWS

Помещая идентификатор учетной записи в файл cloud.ini, не используйте дефисы. Если бы у вас был такой идентификатор, в файл .ini нужно было бы добавить ownerId=999999999999.

Примечания:

  • При каждом запуске экземпляра AMI вы тратите деньги. Хотя у EC2 разумные тарифы (в некоторых случаях всего 10 центов в час), не следует просто запускать AMI и оставлять его работать на неопределенный срок. Обязательно останавливайте свои экземпляры, когда они больше не нужны.
  • Примеры в данной статье предполагают, что вы создали по крайней мере один AMI. В противном случае можно использовать специальное значение ownerId=amazon. Оно возвращает список более чем из 100 AMI, но несколько из этих образов можно запускать.
  • При использовании ownerId=amazon имейте в виду, что некоторые из этих экземпляров очень дорогие. У IBM® есть ряд AMI, которые представляют собой продукты корпоративного класса. Используя один из них, вы платите лицензионную плату за время работы экземпляра. Если нужно всего лишь поэкспериментировать с EC2, то AMI с ограниченным числом функций, вероятно, будут ограничены и по цене.

О примере приложения

Пример приложения состоит из шести страниц PHP:

  1. amis.php— Список всех AMI, относящихся к вашей учетной записи. Чтобы запустить экземпляр любого AMI, достаточно нажать кнопку.
  2. manage_instance.php— Обрабатывает запросы amis.php по созданию, перезагрузке или останову экземпляра AMI.
  3. instances.php— Список всех запущенных экземпляров, контролируемых вашей учетной записью. Перезагрузка или останов любого запущенного экземпляра выполняется нажатием кнопки.
  4. keypairs.php— Список всех созданных вами пар открытого/секретного ключей. Можно находить существующие пары ключей, удалять их и создавать новые.
  5. securitygroups.php— Список всех групп безопасности, определенных для вашей учетной записи. Нажмите кнопку, чтобы получить информацию о конкретной группе безопасности.
  6. securitygroup.php— Список всех разрешений для определенной группы безопасности. Можно добавлять новые разрешения или удалять существующие.

Работа с AMI

Для начала создайте объект Zend_Service_Amazon_Ec2_Image.

Листинг 2. Создание объекта Zend_Service_Amazon_Ec2_Image
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);

Этот объект позволяет работать с AMI, хранящимися в Amazon. Метод Zend_Service_Amazon_Ec2_Image->describe() возвращает метаданные об AMI. Без аргументов он возвращает сведения о каждом AMI, хранящемся в Amazon. Это приводит к созданию большого объема в основном бесполезных для вас данных. К сожалению, нынешнее воплощение Zend Framework не поддерживает версию describe(), которая позволяет указать идентификатор ownerId. Это означает, что в первый раз, когда вы захотите составить список AMI, относящихся к пользователю, вам придется перебрать весь этот список. Чтобы избежать этого, можно кэшировать идентификаторы AMI, которые нужно отобразить. Логика обработки состоит в том, что если существует список файлов нужных AMI, то достаточно просто прочесть этот файл и вызвать describe('ami-id') для каждого ID. Если файл не существует, его нужно создать; файл PHP предоставляет также возможность обновлять список AMI. На это потребуется время, зато список будет соответствовать данным Amazon.

Код для создания списка AMI представлен в листинге 3.

Листинг 3. Кэширование идентификаторов AMI
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);
}

Этот код проверяет, нужно ли перебирать все AMI в каталоге Amazon. Если файл не существует или имеется явный запрос на его обновление, код получает информацию по всем AMI в Amazon. Цель здесь заключается в создании таблицы AMI.

Рисунок 3. Список AMI
Создание таблицы AMI

Каждая строка таблицы содержит идентификатор AMI, его местонахождение, статус и платформу. Кроме того, имеется два раскрывающихся списка, которые позволяют выбрать пару ключей и группу безопасности. Последний столбец таблицы – это кнопка, которая позволяет запустить AMI с текущей выбранной парой ключей и группой безопасности. Чтобы создать таблицу, используйте метод file() для считывания списка AMI в массив. Для каждого элемента массива создайте строку таблицы, которая содержит всю необходимую информацию. В листинге 4 приводится код, который создает строки таблицы.

Листинг 4. Создание строк таблицы AMI
$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>";
}

Каждая строка таблицы должна быть в отдельном элементе <form>, чтобы при нажатии кнопки Start браузер знал, какая пара ключей и группа безопасности выбрана. При просмотре массива идентификаторов AMI вызов describe() с указанным ID возвращает описание этого конкретного AMI. Остальная часть строки таблицы содержит информацию о местонахождении образа (где именно он хранится в вашей учетной записи S3) и его статусе, раскрывающийся список пар ключей, раскрывающийся список групп безопасности, а также кнопку Start для этого образа. Кнопка Start отображается только в том случае, если статус образа доступен. Элементы управления для каждой строки таблицы представлены на рисунке 4.

Рисунок 4. Элементы управления для каждой строки таблицы
Элементы управления для каждой строки таблицы

Списки пар ключей и групп безопасности создаются за пределами цикла.

Листинг 4. Создание списков пар ключей и групп безопасности
$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>";

Каждый список – это строка, которая содержит элементы <select> и <option> для пар ключей и групп безопасности. (Обратите внимание, что для сортировки имен пар ключей и групп безопасности код использует PHP array_multisort.) Поскольку с запуском экземпляра AMI на вашем счете AWS начинается накопление причитающейся платы, появится диалоговое окно подтверждения.

Рисунок 5. Запуск экземпляра нужно подтверждать
Подтверждение запуска эеземпляра

На этом примере экрана выбрана пара ключей id_rsa-gsg-keypair и группа безопасности default.


Работа с экземплярами

При нажатии кнопки OK для запуска экземпляра информация о новом экземпляре направляется на страницу manage_instance.php. Первый шаг при работе с экземпляром заключается в создании объекта Zend_Service_Amazon_Ec2_Instance.

Листинг 6. Создание объекта Zend_Service_Amazon_Ec2_Instance
$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);

Когда объект создан, можно запустить экземпляр нужного образа.

Листинг 7. Создание нового экземпляра
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/>";
}

Примечание: При запуске экземпляра можно задать другие параметры, например, количество экземпляров, размер экземпляра (сколько памяти и ресурсов процессора он потребляет) и географический регион, в котором должен размещаться экземпляр. Для упрощения примеров все запросы на запуск экземпляра запускают только один экземпляр небольшого размера (в фактическом запросе к Amazon указанно m1.small), размещенный в регионе по умолчанию для учетной записи.

Этот код берет идентификатор AMI и имена пары ключей и группы безопасности, выбранные в форме на странице amis.php. Затем страница отображает статус нового экземпляра.

Рисунок 6. Статус вновь созданного экземпляра
Затем страница отображает статус нового экземпляра.

Нажатие кнопки ОК переносит вас на страницу instances.php. Эта страница отображает текущий список экземпляров.

Рисунок 7. Список экземпляров
Эта страница отображает текущий список экземпляров.

Примечание: Значения ID образа, имени ключей и группы безопасности передаются на страницу manage_instance.php через HTTP POST. Использование промежуточной страницы для создания нового экземпляра означает, что страницу instances.php можно обновить без непреднамеренно запуска еще одного экземпляра. Страница manage_instance.php также обрабатывает запросы на перезагрузку или останов образа.

При запуске экземпляра его начальным статусом будет pending. Это означает, что образ машины загружается, но еще не запущен. Отметим также, что Amazon присвоила этому экземпляру идентификатор i-373c995f; этот идентификатор определяет, как вы будете работать с экземпляром. Нажатие кнопки "Refresh list of instances" (Обновить список экземпляров) обновляет картину.

Рисунок 8. Обновленный список экземпляров
Нажатие кнопки Refresh list of instances (Обновить список экземпляров) обновляет картину.

В обновленном списке статус экземпляра изменился на running. Обратите внимание, что Amazon присвоил этому экземпляру имя DNS ec2-75-101-220-48.compute-1.amazonaws.com. Это означает, что если этому экземпляру разрешен доступ в Интернет и на нем работает Web-сервер через порт 80, можно зайти на http://ec2-75-101-220-48.compute-1.amazonaws.com и увидеть главную страницу экземпляра. (Порт 80 можно разрешить, создав правило в группе безопасности; подробнее о группах безопасности - ниже.)

Для создания строк таблицы экземпляров можно использовать метод Zend_Service_Amazon_Ec2_Instance->describe().

Листинг 8. Создание таблицы экземпляров
$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>&nbsp;</td><td>&nbsp;</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>";
    . . .

Сначала код проверяет наличие каких-либо экземпляров. каждый экземпляр описывается строкой таблицы - в предположении, что существует по крайней мере один. ID экземпляра и ID AMI отображаются вместе с открытым именем DNS, группой безопасности и парой ключей. Как и на странице amis.php, каждая строка таблицы – это форма.

Рисунок 9. Элементы управления экземпляром
Каждая строка таблицы – это форма

В этой таблице перечислены три экземпляра. У двух записей статус running, поэтому для этих экземпляров имеются кнопки Reboot (Перезагрузка) и Terminate (Останов). Для экземпляра с любым другим статусом (pending, shutting-down или terminated) копки не появляются.

Листинг 9. Создание формы с элементами управления для экземпляров
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 &apos;";
      echo $nextInstance['instanceId']."&apos;?\")'>";
      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 &apos;";
      echo $nextInstance['instanceId']."&apos;?\")'>";
      echo "<input type='hidden' name='imagetoterminate' value='";
      echo $nextInstance['instanceId']."'/>";
      echo "<input type='submit' value='Terminate'/></form>";
    }
    echo "</td>";

Если экземпляр запущен, код создает кнопки перезагрузки или останова. Нажатие этих кнопок приводит к появлению диалогового окна подтверждения.

Рисунок 10. Останов или перезагрузка экземпляра должны подтверждаться
Код создает кнопки перезагрузки или останова экземпляра, и нажатие этих кнопок приводит к появлению диалогового окна подтверждения

Нажатие кнопки ОК вновь приведет вас на страницу manage_instance.php.

Рисунок 11. Статус только что остановленного экземпляра
Нажатие кнопки ОК вновь приведет вас на страницу manage_instance.php

При возврате к списку экземпляров отображается обновленный статус.

Рисунок 12. Обновленный список экземпляров
При возврате к списку экземпляров отображается обновленный статус.

В какой-то момент статус экземпляра изменится на terminated (остановлен).

Рисунок 13. Остановленный экземпляр
Статус экзепляра изменится на terminated (остановлен).

Примечание: Через некоторое время после останова экземпляра EC2 удаляет все связанные с ним данные. Обычно это происходит в течение часа. После удаления данных об экземпляре он больше не будет появляться в результатах.


Работа с парами ключей

Пара ключей представляет собой пару из открытого и секретного ключей для аутентификации пользователя. При запуске экземпляра можно указать пару ключей для доступа к экземпляру во время его работы. Amazon связывает с этим экземпляром открытый ключ. В зависимости от того, как настроен AMI, и доступ к экземпляру без ключа может быть невозможен. Файл keypairs.php отображает все пары ключей, определенные для вашей учетной записи.

Рисунок 14. Список пар ключей
Файл keypairs.php отображает все пары ключей, определенные для вашей учетной записи

Для каждой пары ключей в таблице отображается ее имя и контрольная сумма.

Листинг 10. Создание таблицы пар ключей
$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>&nbsp;</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>&nbsp;".$nextKeypair['keyName']."</td>";
    echo "<td>&nbsp;".$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 "&apos;".$nextKeypair['keyName']."&apos;?\");'>";
    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>";

Этот код создает объект Zend_Service_Amazon_Ec2_Keypair, а затем вызывает метод describe(), чтобы получить подробную информацию обо всех парах ключей, определенных для учетной записи. Для каждой пары ключей AWS возвращает имя пары ключей и контрольную сумму. Каждая строка таблицы содержит также HTML-форму с кнопкой Delete. Эта форма требует подтверждения любого запроса на удаление.

Рисунок 15. Для удаления пары ключей требуется подтверждение
Эта форма требует подтверждения любого запроса на удаление.

Метод delete() позволяет легко удалять пары ключей.

Листинг 11. Удаление пары ключей
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/>";
}

На странице keypairs.php содержится также форма для создания новой пары ключей. Единственный параметр - это имя новой пары ключей.

Рисунок 16. Форма для создания новой пары ключей
На странице keypairs.php содержится также форма для создания новой пары ключей

Для создания пары ключей достаточно вызвать метод create().

Листинг 12. Создание таблицы правил в группе безопасности
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>&nbsp;".strtoupper($rule['ipProtocol'])."</td>\n";
  echo "<td>&nbsp;".$rule['fromPort']."</td>\n";
  echo "<td>&nbsp;".$rule['toPort']."</td>\n";

  if ((is_array($rule['ipRanges']) && count($rule['ipRanges']) == 0) ||
      (strlen($rule['ipRanges']) == 0)) {
    echo "<td>&nbsp;---</td>\n";
    echo "<td>&nbsp;</td>\n";
  }
  else {
    echo "<td>&nbsp;".$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>";
  }

Ответ от Amazon содержит секретный ключ для новой пары ключей. Страница PHP отображает эту информацию с сообщением для пользователя.

Рисунок 17. Вновь созданная пара ключей
Страница PHP отображает эту информацию с сообщением для пользователя

Пользователь должен скопировать и вставить информацию секретного ключа в файл. В случае потери этой информации ее нельзя воссоздать. (В качестве упражнения читателю предлагается создать более элегантное решение, которое автоматически записывает данные пары ключей в файл.)


Работа с группами безопасности

Форма, которая позволяет создавать новые экземпляры, требует указания образа машины, пары ключей и группы безопасности. Группа безопасности позволяет определить, каким образом другие машины могут получить доступ к экземпляру. Например, если вы хотите использовать запущенный экземпляр в качестве Web-сервера, вам нужно определить в своей группе безопасности правило, что от любой машины должны приниматься запросы на установление соединения с портом 80. Для каждого правила указывается протокол, диапазон портов и диапазон IP-адресов, которым разрешено обращаться к этим портам через данный протокол. Представление группы безопасности выглядит, как на рисунке 18.

Рисунок 18. Группа безопасности
Представление группы безопасности

В этой таблице перечислены политики безопасности для группы безопасности по умолчанию. В нижней части экрана видно, что политика разрешает хостам 67.93.2.12 и 76.182.90.9 доступ к порту 80. К порту 3389, как правило, используемому для сеансов удаленного рабочего стола виртуальных машин Windows, разрешен также доступ IP-адресу 76.182.90.9. Можно указать диапазон портов; в данном примере политику портов 21, 22 и 23 можно было бы задать одним правилом. Каждая строка таблицы содержит форму для удаления отдельных правил. Код для создания таблицы относительно прост.

Листинг 13. Создание таблицы правил в группе безопасности
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>&nbsp;".strtoupper($rule['ipProtocol'])."</td>\n";
  echo "<td>&nbsp;".$rule['fromPort']."</td>\n";
  echo "<td>&nbsp;".$rule['toPort']."</td>\n";

  if ((is_array($rule['ipRanges']) && count($rule['ipRanges']) == 0) ||
      (strlen($rule['ipRanges']) == 0)) {
    echo "<td>&nbsp;---</td>\n";
    echo "<td>&nbsp;</td>\n";
  }
  else {
    echo "<td>&nbsp;".$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>&nbsp;</td>";

Перед созданием строк таблицы в коде используется функция array_multisort для сортировки массива правил по первому номеру порта для каждого правила. Отображение имени протокола, начального порта и конечного порта программируется легко. Последние два столбца таблицы – это диапазон IP-адресов и кнопка отмены разрешения. В некоторых случаях диапазон IP-адресов возвращается в виде пустого массива или пустой строки. В этом случае таблица вместо кнопки Revoke (Отмена) будет содержать пустые ячейки.

Последняя строка таблицы содержит форму для создания нового правила.

Рисунок 19. Форма для создания нового правила
Последняя строка таблицы содержит форму для создания нового правила

Amazon требует, чтобы IP-адрес указывается в системе обозначений бесклассовой междоменной маршрутизации (CIDR). Система обозначений CIDR – это IP-адрес, за которым следует косая черта и число от 0 до 32. Число после косой черты определяет, сколько битов IP-адреса в префиксе. Например, запись CIDR 9.67.0.0/16 соответствует любому адресу, который начинается с 9.67. Диапазон IP-адресов 0.0.0.0/0 содержит любой IP-адрес, тогда как в диапазон 76.182.90.9/32 входит только IP-адрес 76.182.90.9. Если пользователь вводит IP-адрес не в системе CIDR, PHP-страница добавляет к нему /32. (Подробнее о CIDR см. в разделе Ресурсы.) Код, разрешающий диапазон IP-адресов, чрезвычайно прост.

Листинг 14. Разрешение нового диапазона IP-адресов
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>";
    }
  }

Вызов метода authorizeIp создает новое правило для группы безопасности. Этот код управляет двумя распространенными исключительными ситуациями: Zend Framework инициирует исключительную ситуацию, если вы разрешаете диапазон IP-адресов, который уже разрешен; вторая исключительная ситуация возникает в том случае, если диапазон IP-адресов неверен. В случае любых других исключительных ситуаций код просто выдает на экран сообщение об ошибке.

Примечание: Недавно исправлена ошибка в функции Zend Framework, которая возвращает массив списков, если для некоторого порта разрешен более чем один диапазон адресов. Если в вашей версии Zend Framework эта ошибка не исправлена, вы увидите только один адрес для каждого порта. Все разрешения относятся к группе безопасности, хранящейся в облаке Amazon; Zend просто не отображает их в своих результатах. Образец кода содержит логику для аккуратного решения этой проблемы.

Наконец, нажав кнопку Revoke (Отмена) рядом с правилом, пользователь получит запрос на подтверждение операции.

Рисунок 20. Удаление правила безопасности должно быть подтверждено
Нажав кнопку Revoke (Отмена) рядом с правилом, пользователь получит запрос на подтверждение операции

Удаление правила безопасности осуществляется с помощью метода revokeIp().


Заключение

В данной статье описан набор страниц для работы с образами виртуальной машины, запущенными экземплярами этих образов и парами ключей/группами безопасности, которые позволяют управлять ими. Инфраструктура Zend Framework снова позволяет легко взаимодействовать с облаком. В следующем выпуске этого цикла будет показано, как использовать Zend Framework для работы с более сложными функциями EC2, такими как IP-адреса Elastic, Elastic Block Storage и CloudWatch.


Загрузка

ОписаниеИмяРазмер
Пример кодаos-php-cloud2-source.zip13 KБ

Ресурсы

Научиться

Получить продукты и технологии

Обсудить

Комментарии

developerWorks: Войти

Обязательные поля отмечены звездочкой (*).


Нужен IBM ID?
Забыли Ваш IBM ID?


Забыли Ваш пароль?
Изменить пароль

Нажимая Отправить, Вы принимаете Условия использования developerWorks.

 


Профиль создается, когда вы первый раз заходите в developerWorks. Информация в вашем профиле (имя, страна / регион, название компании) отображается для всех пользователей и будет сопровождать любой опубликованный вами контент пока вы специально не укажите скрыть название вашей компании. Вы можете обновить ваш IBM аккаунт в любое время.

Вся введенная информация защищена.

Выберите имя, которое будет отображаться на экране



При первом входе в developerWorks для Вас будет создан профиль и Вам нужно будет выбрать Отображаемое имя. Оно будет выводиться рядом с контентом, опубликованным Вами в developerWorks.

Отображаемое имя должно иметь длину от 3 символов до 31 символа. Ваше Имя в системе должно быть уникальным. В качестве имени по соображениям приватности нельзя использовать контактный e-mail.

Обязательные поля отмечены звездочкой (*).

(Отображаемое имя должно иметь длину от 3 символов до 31 символа.)

Нажимая Отправить, Вы принимаете Условия использования developerWorks.

 


Вся введенная информация защищена.


  • Bluemix

    Узнайте больше информации о платформе IBM Bluemix, создавайте приложения, используя готовые решения!

  • Библиотека документов

    Более трех тысяч статей, обзоров, руководств и других полезных материалов.

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=40
Zone=Open source
ArticleID=489276
ArticleTitle=Применение PHP в облачных вычислениях: Часть 2. Работа с Amazon EC2 посредством Zend Framework
publish-date=05122010